wrap-cli icon indicating copy to clipboard operation
wrap-cli copied to clipboard

Abstract away the msgpack de/serialization as a higher level abstract trait in rust

Open Niraj-Kamdar opened this issue 1 year ago • 1 comments

Summary

Currently, we implement de/serialization functions as a simple implementation of the type struct, we should instead implement a high-level trait with these functions and implement those for every type, this will extend the programmability for devs who want to use this trait on their own custom type and implementations.

Current codegen:

pub struct AssetPlatform {
    pub id: String,
    pub chain_identifier: Option<i32>,
    pub name: String,
    pub shortname: String,
}

impl AssetPlatform {
    pub fn new() -> AssetPlatform {
        AssetPlatform {
            id: String::new(),
            chain_identifier: None,
            name: String::new(),
            shortname: String::new(),
        }
    }

    pub fn to_buffer(args: &AssetPlatform) -> Result<Vec<u8>, EncodeError> {
        serialize_asset_platform(args).map_err(|e| EncodeError::TypeWriteError(e.to_string()))
    }

    pub fn from_buffer(args: &[u8]) -> Result<AssetPlatform, DecodeError> {
        deserialize_asset_platform(args).map_err(|e| DecodeError::TypeReadError(e.to_string()))
    }

    pub fn write<W: Write>(args: &AssetPlatform, writer: &mut W) -> Result<(), EncodeError> {
        write_asset_platform(args, writer).map_err(|e| EncodeError::TypeWriteError(e.to_string()))
    }

    pub fn read<R: Read>(reader: &mut R) -> Result<AssetPlatform, DecodeError> {
        read_asset_platform(reader).map_err(|e| DecodeError::TypeReadError(e.to_string()))
    }
}

Expected codegen


pub struct AssetPlatform {
    pub id: String,
    pub chain_identifier: Option<i32>,
    pub name: String,
    pub shortname: String,
}

trait MsgpackSerializable {
      pub fn to_buffer(&self) -> Result<Vec<u8>, EncodeError> {}

    pub fn from_buffer(args: &[u8]) -> Result<Self, DecodeError> {}
}

trait MsgpackIO {
    pub fn write<W: Write>(args: &self, writer: &mut W) -> Result<(), EncodeError> {}

    pub fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {}
}

impl AssetPlatform {
    pub fn new() -> AssetPlatform {
        AssetPlatform {
            id: String::new(),
            chain_identifier: None,
            name: String::new(),
            shortname: String::new(),
        }
    }
}

impl MsgpackSerializable for AssetPlatform {
    pub fn to_buffer(args: &AssetPlatform) -> Result<Vec<u8>, EncodeError> {
        serialize_asset_platform(args).map_err(|e| EncodeError::TypeWriteError(e.to_string()))
    }

    pub fn from_buffer(args: &[u8]) -> Result<AssetPlatform, DecodeError> {
        deserialize_asset_platform(args).map_err(|e| DecodeError::TypeReadError(e.to_string()))
    }
}

impl MsgpackIO for AssetPlatform {
    pub fn write<W: Write>(args: &AssetPlatform, writer: &mut W) -> Result<(), EncodeError> {
        write_asset_platform(args, writer).map_err(|e| EncodeError::TypeWriteError(e.to_string()))
    }

    pub fn read<R: Read>(reader: &mut R) -> Result<AssetPlatform, DecodeError> {
        read_asset_platform(reader).map_err(|e| DecodeError::TypeReadError(e.to_string()))
    }
}

Note: the above code is just for understanding the issue and possible solution. It may not compile in its current form and may require modifications.

Why should we do this?

  • separation of concerns
  • ability to de/serialize or read/write is a trait that any type can have
  • Even native type can have these traits after this modification.
    • Ex: you can implement MsgpackSerializable for String and then you can do "xyz".to_buffer() and get msgpack
  • In the future, we can introduce a derive macro for this trait and users can effortlessly compose different serializable types.

Niraj-Kamdar avatar Sep 21 '22 10:09 Niraj-Kamdar

Alternatively we can even use serde but more research is required

Niraj-Kamdar avatar Sep 22 '22 14:09 Niraj-Kamdar