Skip to main content

perde_core/
encode.rs

1use crate::{
2    error::Convert,
3    schema::{FieldSchema, Primitive, Schema, WithSchema},
4    types::{AttrStr, DictRef, ListRef, ObjectRef, Set, SetRef, TupleRef},
5};
6use indexmap::IndexMap;
7use serde::ser::Error;
8use serde::{
9    ser::{SerializeMap, SerializeSeq, Serializer},
10    Serialize,
11};
12
13lazy_static::lazy_static! {
14    static ref ATTR_NAME: AttrStr = AttrStr::new("name");
15    static ref ATTR_VALUE: AttrStr = AttrStr::new("value");
16}
17
18impl<'a> Serialize for WithSchema<'a> {
19    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
20    where
21        S: Serializer,
22    {
23        match self.schema {
24            Schema::Primitive(Primitive::Bool) => s.serialize_bool(self.object.as_bool().ser()?),
25            Schema::Primitive(Primitive::Int) => s.serialize_i64(self.object.as_i64().ser()?),
26            Schema::Primitive(Primitive::Str) => s.serialize_str(self.object.as_str().ser()?),
27            Schema::Primitive(Primitive::Float) => s.serialize_f64(self.object.as_f64().ser()?),
28            Schema::Primitive(Primitive::ByteArray) => {
29                s.serialize_bytes(self.object.as_bytearray().ser()?)
30            }
31            Schema::Primitive(Primitive::Bytes) => s.serialize_bytes(self.object.as_bytes().ser()?),
32            Schema::List(l) => {
33                let list = ListRef::new(self.object);
34                let len = list.len();
35                let mut seq = s.serialize_seq(Some(len))?;
36                for i in 0..len {
37                    let obj = list.get(i).unwrap();
38                    let w = obj.with_schema(&l.value);
39                    seq.serialize_element(&w)?;
40                }
41                seq.end()
42            }
43            Schema::Set(l) => {
44                let set = SetRef::new(self.object);
45                let len = set.len();
46                let mut seq = s.serialize_seq(Some(len))?;
47
48                while let Some(item) = set.pop() {
49                    let w = item.with_schema(&l.value);
50                    seq.serialize_element(&w)?;
51                }
52                seq.end()
53            }
54            Schema::FrozenSet(l) => {
55                let set = Set::from_iter(self.object).ser()?;
56                let len = set.len();
57                let mut seq = s.serialize_seq(Some(len))?;
58
59                while let Some(item) = set.pop() {
60                    let w = item.with_schema(&l.value);
61                    seq.serialize_element(&w)?;
62                }
63                seq.end()
64            }
65            Schema::Tuple(t) => {
66                let tuple = TupleRef::new(self.object);
67                let iter = tuple.iter();
68                let len = iter.len();
69                let mut seq = s.serialize_seq(Some(len))?;
70                for (obj, schema) in iter.zip(t.args.iter()) {
71                    let w = obj.with_schema(schema);
72                    seq.serialize_element(&w)?;
73                }
74                seq.end()
75            }
76            Schema::Dict(d) => {
77                let dict = DictRef::new(self.object);
78                let mut map = s.serialize_map(Some(dict.len()))?;
79                for (k, v) in dict.iter() {
80                    let k = k.with_schema(&d.key);
81                    let v = v.with_schema(&d.value);
82                    map.serialize_entry(&k, &v)?;
83                }
84                map.end()
85            }
86            Schema::Class(c) => {
87                let mut map = s.serialize_map(Some(c.fields.len()))?;
88                serialize_fields(&self.object, &c.fields, &mut map)?;
89                map.end()
90            }
91            Schema::Enum(e) => {
92                let name = self.object.get_attr(&ATTR_NAME).ser()?;
93                let name = name.as_str().ser()?;
94                if !e.variants.contains_key(name) {
95                    return Err(S::Error::custom(format!("no such variant: {}", name)));
96                }
97                s.serialize_str(&name)
98            }
99            Schema::Optional(o) => {
100                if self.object.is_none() {
101                    s.serialize_none()
102                } else {
103                    let w = self.object.with_schema(&o.value);
104                    s.serialize_some(&w)
105                }
106            }
107            Schema::Union(u) => {
108                let vs = self.object.get_type().ser()?.resolve(None).ser()?;
109                let vs = match u.variants.iter().find(|v| v == &vs) {
110                    Some(vs) => vs,
111                    None => return Err(S::Error::custom(format!("no such variant"))),
112                };
113                let v = self.object.with_schema(vs);
114                v.serialize(s)
115            }
116            Schema::Any(_) => self.object.resolved_object().ser()?.serialize(s),
117        }
118    }
119}
120
121fn serialize_fields<T, E>(
122    object: &ObjectRef,
123    fields: &IndexMap<String, FieldSchema>,
124    map: &mut T,
125) -> Result<(), E>
126where
127    T: SerializeMap<Error = E>,
128    E: serde::ser::Error,
129{
130    for (name, field) in fields {
131        let obj = object.get_attr(&field.name).ser()?;
132        if field.attr.flatten {
133            match &field.schema {
134                Schema::Class(cls) => {
135                    serialize_fields(&obj, &cls.fields, map)?;
136                }
137                _ => return Err(E::custom(format!("found flatten flag for non-class type"))),
138            }
139        } else {
140            let f = obj.with_schema(&field.schema);
141            map.serialize_entry(&name, &f)?;
142        }
143    }
144    Ok(())
145}