Deserialize

Derive Macro Deserialize 

Source
#[derive(Deserialize)]
Expand description

Derives the Deserialize trait implementation

§Example

use proc_contra::Deserialize;
use lib_contra::{deserialize::Deserialize, position::Position, deserialize::Deserializer, error::AnyError};
#[derive(Deserialize)]
struct Point {
    x: f32,
    y: f32,
    z: f32
}

Expands into:

use lib_contra::{deserialize::{MapAccess, Visitor, Deserialize}, position::Position, deserialize::Deserializer, error::AnyError};

struct Point {
    x: f32,
    y: f32,
    z: f32
}

impl Deserialize for Point {
    fn deserialize<D: Deserializer>(de: D) -> Result<Self, AnyError> {
        enum Field {
            x, y, z
        }
        impl Deserialize for Field {
            fn deserialize<D: Deserializer>(de: D) -> Result<Self, AnyError> {
                struct FieldVisitor {}
                impl Visitor for FieldVisitor {
                    type Value = Field;
                    fn expected_a(self) -> String { "Point field".to_string() }
                    fn visit_str(self, v: &str) -> Result<Self::Value, AnyError> {
                        match v {
                            "x" => Ok(Field::x),
                            "y" => Ok(Field::y),
                            "z" => Ok(Field::z),
                            val => Err(format!("unexpected Point field {}", val).into())
                        }
                    }
                }
                de.deserialize_str(FieldVisitor {})
            }
        }

        struct PointVisitor {}
        impl Visitor for PointVisitor {
            type Value = Point;
            fn expected_a(self) -> String { "Point object".to_string() }
            fn visit_map<M: MapAccess>(self, mut map: M) -> Result<Self::Value, AnyError> {
                let mut x = None;
                let mut y = None;
                let mut z = None;
                 
                while let Some(key) = map.next_key()? {
                    match key {
                        Field::x => { if x.is_some() { return Err("duplicate field x".into()); } x = Some(map.next_value()?) },
                        Field::y => { if y.is_some() { return Err("duplicate field y".into()); } y = Some(map.next_value()?) },
                        Field::z => { if z.is_some() { return Err("duplicate field z".into()); } z = Some(map.next_value()?) },
                    }
                }

                let x = x.ok_or_else(|| "missing field x")?;
                let y = y.ok_or_else(|| "missing field y")?;
                let z = z.ok_or_else(|| "missing field z")?;

                Ok(Point {
                    x, y, z
                })
            }
        }

        de.deserialize_struct(PointVisitor {})
    }
}