No description
Find a file
2021-01-07 22:56:55 +01:00
example Implement msgpack deserialization 2021-01-03 22:28:39 +01:00
macroserde Don't Err on unknown field 2021-01-07 22:56:55 +01:00
macroserde-json Don't Err on unknown field 2021-01-07 22:56:55 +01:00
macroserde-msgpack Don't Err on unknown field 2021-01-07 22:56:55 +01:00
.gitignore Initial commit 2020-12-20 00:28:18 +01:00
Cargo.lock Msgpack serialization 2021-01-03 20:46:02 +01:00
Cargo.toml Msgpack serialization 2021-01-03 20:46:02 +01:00
README.md Implement msgpack deserialization 2021-01-03 22:28:39 +01:00

This is an experimental serialization framework for Rust that uses macros instead of procedural macros to generate the serialization and deserialization code. The in-memory representation of the deserialized data is exactly what one could expect from defining the same structures in Rust.

Like miniserde it avoids monomorphization, and supports renaming. However it also supports enumerations and discriminated unions (Rust's enums basically).

Like protobuf, struct fields, enum variants, and union variants, are identified by unique identifiers. Those identifiers are checked for unicity at compile-time. Serializers can use the ID, the name, or both to identify them. This is useful for making the serialization formats human-readable. Deserializers can check the ID when it's available or the name when it's available. The ID is supposed to be more reliable but in human-edited data, only the field/variant name may be present.

Example

macroserde! {
    #[derive(Debug, PartialEq)]
    enum Month {
        January = 1 @ "JAN",
        February = 2 @ "FEB",
        March = 3 @ "MAR",
        April = 4 @ "APR",
        May = 5 @ "MAY",
        June = 6 @ "JUN",
        July = 7 @ "JUL",
        August = 8 @ "AUG",
        September = 9 @ "SEP",
        October = 10 @ "OCT",
        November = 11 @ "NOV",
        December = 12 @ "DEC",
    }
}

impl Default for Month {
    fn default() -> Self {
        Self::January
    }
}

macroserde! {
    #[derive(Debug, PartialEq, Default)]
    struct Date {
        day: u8 = 1,
        month: Month = 2,
        year: u32 = 3,
    }
}

macroserde! {
    #[derive(Debug, PartialEq)]
    union Occupation {
        Unemployed = 1,
        Employed(String) = 2 @ "hasJob",
    }
}

impl Default for Occupation {
    fn default() -> Self {
        Self::Unemployed
    }
}

macroserde! {
    #[derive(Debug, PartialEq, Default)]
    struct Person {
        name: String = 1,
        age: i16 = 2,
        birth_date: Date = 3,
        pets: Vec<String> = 4,
        height: Option<f32> = 5,
        car_brand: Option<String> = 88 @ "carBrand",
        is_cool: bool = 6 @ "IsCool",
        occupation: Occupation = 7,
    }
}

fn main() {
    let stuff = Person {
        name: "Steven".to_owned(),
        age: 27,
        height: Some(1.735),
        car_brand: None,
        is_cool: true,
        birth_date: Date {
            day: 19,
            month: Month::October,
            year: 1993,
        },
        pets: vec!["Bouboul".to_owned(), "Monsieur Puppy".to_owned()],
        occupation: Occupation::Employed("Engineer".to_owned()),
    };

    let mut ser = macroserde_json::Serializer::new();
    stuff.serialize(&mut ser).unwrap();

    ser.write_pretty(&mut std::io::stdout(), 2).unwrap();
}

The code above would produce:

{
  "1:name": "Steven",
  "2:age": 27,
  "3:birth_date": {
    "1:day": 19,
    "2:month": "10:OCT",
    "3:year": 1993
  },
  "4:pets": [
    "Bouboul",
    "Monsieur Puppy"
  ],
  "5:height": 1.7350000143051148,
  "88:carBrand": null,
  "6:IsCool": true,
  "7:occupation": {
    "2:hasJob": "Engineer"
  }
}

Future work