Deserialize

Derive Macro Deserialize 

Source
#[derive(Deserialize)]
Expand description

Derives the Decodable trait, generating implementations for deserializing a struct from a byte stream, including its structure, field decoding, and a method for creating a static version.

This procedural macro generates the Decodable trait for a struct, which allows it to be decoded from a binary stream, with support for handling fields of different types and nested generics. The macro also includes implementations for from_decoded_fields, get_structure, and methods to return a static version of the struct.

§Example

Given a struct:

struct Test {
    a: u32,
    b: u8,
    c: U24,
}

Using #[derive(Decodable)] on Test generates the following implementations:

mod impl_parse_decodable_test {
    use super::{
        binary_codec_sv2::{
            decodable::{DecodableField, FieldMarker},
            Decodable, Error, SizeHint,
        },
        *,
    };

    struct Test {
        a: u32,
        b: u8,
        c: U24,
    }

    impl<'decoder> Decodable<'decoder> for Test {
        fn get_structure(data: &[u8]) -> Result<Vec<FieldMarker>, Error> {
            let mut fields = Vec::new();
            let mut offset = 0;

            let a: Vec<FieldMarker> = u32::get_structure(&data[offset..])?;
            offset += a.size_hint_(&data, offset)?;
            let a = a.try_into()?;
            fields.push(a);

            let b: Vec<FieldMarker> = u8::get_structure(&data[offset..])?;
            offset += b.size_hint_(&data, offset)?;
            let b = b.try_into()?;
            fields.push(b);

            let c: Vec<FieldMarker> = U24::get_structure(&data[offset..])?;
            offset += c.size_hint_(&data, offset)?;
            let c = c.try_into()?;
            fields.push(c);

            Ok(fields)
        }

        fn from_decoded_fields(mut data: Vec<DecodableField<'decoder>>) -> Result<Self, Error> {
            Ok(Self {
                c: U24::from_decoded_fields(
                    data.pop().ok_or(Error::NoDecodableFieldPassed)?.into(),
                )?,
                b: u8::from_decoded_fields(
                    data.pop().ok_or(Error::NoDecodableFieldPassed)?.into(),
                )?,
                a: u32::from_decoded_fields(
                    data.pop().ok_or(Error::NoDecodableFieldPassed)?.into(),
                )?,
            })
        }
    }

    impl Test {
        pub fn into_static(self) -> Test {
            Test {
                a: self.a.clone(),
                b: self.b.clone(),
                c: self.c.clone(),
            }
        }
    }

    impl Test {
        pub fn as_static(&self) -> Test {
            Test {
                a: self.a.clone(),
                b: self.b.clone(),
                c: self.c.clone(),
            }
        }
    }
}

This generated code enables Test to be decoded from a binary stream, defines how each field should be parsed, and provides into_static and as_static methods to facilitate ownership and lifetime management of decoded fields in the struct.