Skip to main content

perde_core/decode/
class.rs

1use crate::{
2    error::{Convert, Result},
3    schema::*,
4    types::{self, Object},
5};
6use serde::de::{self, DeserializeSeed, Deserializer, IgnoredAny, MapAccess, Visitor};
7use std::{borrow::Cow, collections::HashMap, fmt};
8
9pub struct ClassVisitor<'a>(pub &'a Class);
10
11impl<'a, 'de> Visitor<'de> for ClassVisitor<'a> {
12    type Value = Object;
13
14    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
15        write!(f, "a class")
16    }
17
18    fn visit_map<M>(self, mut access: M) -> std::result::Result<Self::Value, M::Error>
19    where
20        M: MapAccess<'de>,
21    {
22        if self.0.flatten_fields.is_empty() {
23            let mut tuple = types::Tuple::new(self.0.fields.len()).de()?;
24            let mut setcount = 0;
25
26            while let Some(key) = access.next_key()? {
27                let key: Cow<str> = key;
28
29                if let Some(s) = self.0.field(&key).de()? {
30                    let value: Object = access.next_value_seed(&s.schema)?;
31
32                    tuple.set(s.pos, value);
33                    setcount += 1;
34                } else {
35                    let _: IgnoredAny = access.next_value()?;
36                }
37            }
38
39            if setcount != self.0.num_fields() {
40                return Err(de::Error::custom("missing field"));
41            }
42
43            self.0.ty.construct(tuple).de()
44        } else {
45            let mut map = HashMap::new();
46
47            while let Some(key) = access.next_key()? {
48                let key: Cow<str> = key;
49
50                if let Some(s) = self.0.field(&key).de()? {
51                    let value: Object = access.next_value_seed(&s.schema)?;
52
53                    map.insert(key, value);
54                } else {
55                    let _: IgnoredAny = access.next_value()?;
56                }
57            }
58
59            let cls = self.0.call(&mut map).de()?;
60
61            if !map.is_empty() && self.0.attr.deny_unknown_fields {
62                // TODO: Error
63            }
64
65            Ok(cls)
66        }
67    }
68}
69
70impl<'a, 'de> DeserializeSeed<'de> for &'a Class {
71    type Value = Object;
72
73    fn deserialize<D>(self, deserializer: D) -> std::result::Result<Self::Value, D::Error>
74    where
75        D: Deserializer<'de>,
76    {
77        deserializer.deserialize_map(ClassVisitor(self))
78    }
79}
80
81impl Class {
82    pub fn num_fields(&self) -> usize {
83        if self.flatten_fields.is_empty() {
84            self.fields.len()
85        } else {
86            self.flatten_fields.len()
87        }
88    }
89
90    pub fn field(&self, name: &str) -> Result<Option<&FieldSchema>> {
91        let map = if self.flatten_fields.is_empty() {
92            &self.fields
93        } else {
94            &self.flatten_fields
95        };
96
97        map.get(name)
98            .map(|v| {
99                if v.attr.skip || v.attr.skip_deserializing {
100                    Ok(None)
101                } else {
102                    Ok(Some(v))
103                }
104            })
105            .unwrap_or_else(|| {
106                if self.attr.deny_unknown_fields {
107                    Err(err!("the field `{}` is missing", name,))
108                } else {
109                    Ok(None)
110                }
111            })
112    }
113
114    pub fn call(&self, map: &mut HashMap<Cow<str>, Object>) -> Result<Object> {
115        let args: Result<Vec<_>> = self
116            .fields
117            .iter()
118            .map(|(k, s)| {
119                if s.attr.flatten {
120                    match &s.schema {
121                        Schema::Class(cls) => return cls.call(map),
122                        Schema::Dict(_) => {
123                            let map = std::mem::replace(map, HashMap::new());
124
125                            let mut dict = types::Dict::new()?;
126                            for (k, v) in map {
127                                dict.set(Object::new_str(&k)?, v)?;
128                            }
129                            return Ok(dict.into_inner());
130                        }
131                        _ => return Err(err!("found `flatten` attribute an non-map type",)),
132                    }
133                }
134
135                let k: &str = k.as_ref();
136                match map.remove(k) {
137                    Some(v) => Ok(v),
138                    None => {
139                        if self.attr.default
140                            || s.attr.default.is_some()
141                            || s.attr.skip
142                            || s.attr.skip_deserializing
143                        {
144                            if let Some(d) = s.attr.default.as_ref() {
145                                return Ok(d.clone());
146                            } else if let Some(d) = s.attr.default_factory.as_ref() {
147                                return d.call_noarg();
148                            }
149                        }
150                        Err(err!("missing field \"{}\"", k))
151                    }
152                }
153            })
154            .collect();
155
156        self.construct(args?)
157    }
158
159    pub fn construct(&self, args: Vec<Object>) -> Result<Object> {
160        let mut tuple = types::Tuple::new(args.len())?;
161        for (i, arg) in args.into_iter().enumerate() {
162            tuple.set(i, arg);
163        }
164        self.ty.construct(tuple)
165    }
166}