Robbepop / modular-bitfield

Macro to generate bitfields for structs that allow for modular use of enums.
Apache License 2.0
155 stars 40 forks source link

Implement serde derives replacement #74

Open jam1garner opened 2 years ago

jam1garner commented 2 years ago

Currently the easiest way to serialize/deserialize modular-bitfields using serde is by converting to/from another struct when serializing/deserializing. Ideally this could be handled automatically by modular-bitfield similarly to Debug impls (see #32).

I'd be willing to handle implementation, however I'd appreciate thoughts on if this is an acceptable feature for inclusion and if so any thoughts on how you like it to be implemented.

jam1garner commented 2 years ago

one thing of note @Robbepop is that my current workaround (and likely how I would recommend going about implementing such a derive) is using serde's top-level from/into attributes.

For example:

#[bitfield]
#[derive(Serialize, Deserialize)]
struct MyBitfield {
    a: bool,
    b: B4,
    #[skip] __: B3,
}

could be expanded like such:

#[allow(non_camel_case_types, non_snake_case)]
mod __bitfield_serde_MyBitfield {
    use super::*;
    #[derive(Serialize, Deserialize)]
    struct __bitfield_internal_MyBitfield {
        a: <bool as Specifier>::InOut,
        b: <B4 as Specifier>::InOut,
    }

    impl From<MyBitfield> for __bitfield_internal_MyBitfield {
        fn from(bitfield: MyBitfield) -> Self {
            Self {
                a: bitfield.a(),
                b: bitfield.b()
            }
        }
    }

    impl From<__bitfield_internal_MyBitfield> for MyBitfield {
        fn from(internal: __bitfield_internal_MyBitfield) -> Self {
            let __bitfield_internal_MyBitfield { a, b } = internal;
            Self::new()
                .with_a(a)
                .with_b(b)
        }
    }
}

#[derive(Serialize, Deserialize)]
#[serde(from = "__bitfield_serde_MyBitfield::__bitfield_internal_MyBitfield")]
#[serde(into = "__bitfield_serde_MyBitfield::__bitfield_internal_MyBitfield")]
struct MyBitfield {
    a: bool,
    b: B4,
    #[skip] __: B3,
}

if the above approach sounds good to you I can proceed with implementing and send a PR :)

jam1garner commented 2 years ago

also another question about implementation strategy: should this be automatic (i.e. assume all derives named "Serialize" and "Deserialize" are serde) or manual (i.e. require something like #[bitfield(serialize, deserialize)])?