Skip to main content

one_brackets/
ser.rs

1//! Serialization of user types into a [`Node`] tree, the mirror of [`de`](crate::de):
2//! fields become list items in declaration order, strings are quoted
3//! (see [`atom`](crate::atom) for unquoted ones), `None` and `()` are empty atoms,
4//! enum variants are written by index.
5
6use serde::ser::{self, Serialize};
7
8use crate::serde_impls::{ATOM, REST, VALUE};
9use crate::{Node, SerializeError, Value};
10
11/// Serializes a user type into a node tree.
12pub fn to_node<T: Serialize + ?Sized>(value: &T) -> Result<Node, SerializeError> {
13    Ok(match value.serialize(NodeSerializer)? {
14        Item::One(node) => node,
15        Item::Splice(items) => Node::list(items),
16    })
17}
18
19/// Serializes a user type into bracket text in the platform layout.
20pub fn to_string<T: Serialize + ?Sized>(value: &T) -> Result<String, SerializeError> {
21    to_node(value).map(|node| node.to_string())
22}
23
24/// A [`Rest`](crate::Rest) is spliced into the enclosing list instead of nesting.
25enum Item {
26    One(Node),
27    Splice(Vec<Node>),
28}
29
30fn one(node: Node) -> Result<Item, SerializeError> {
31    Ok(Item::One(node))
32}
33
34struct NodeSerializer;
35
36macro_rules! serialize_display {
37    ($($method:ident: $t:ty),* $(,)?) => {$(
38        fn $method(self, v: $t) -> Result<Item, SerializeError> {
39            one(Node::atom(v.to_string()))
40        }
41    )*};
42}
43
44impl ser::Serializer for NodeSerializer {
45    type Ok = Item;
46    type Error = SerializeError;
47    type SerializeSeq = List;
48    type SerializeTuple = List;
49    type SerializeTupleStruct = List;
50    type SerializeTupleVariant = List;
51    type SerializeMap = Map;
52    type SerializeStruct = List;
53    type SerializeStructVariant = List;
54
55    fn serialize_bool(self, v: bool) -> Result<Item, SerializeError> {
56        one(Node::from(v))
57    }
58
59    serialize_display! {
60        serialize_i8: i8,
61        serialize_i16: i16,
62        serialize_i32: i32,
63        serialize_i64: i64,
64        serialize_i128: i128,
65        serialize_u8: u8,
66        serialize_u16: u16,
67        serialize_u32: u32,
68        serialize_u64: u64,
69        serialize_u128: u128,
70        serialize_f32: f32,
71        serialize_f64: f64,
72    }
73
74    fn serialize_char(self, v: char) -> Result<Item, SerializeError> {
75        one(Node::string(v))
76    }
77
78    fn serialize_str(self, v: &str) -> Result<Item, SerializeError> {
79        one(Node::string(v))
80    }
81
82    fn serialize_bytes(self, _v: &[u8]) -> Result<Item, SerializeError> {
83        Err(SerializeError::new(
84            "byte arrays are not supported: write binary data as a `#base64:` atom",
85        ))
86    }
87
88    fn serialize_none(self) -> Result<Item, SerializeError> {
89        one(Node::atom(""))
90    }
91
92    fn serialize_some<T: Serialize + ?Sized>(self, value: &T) -> Result<Item, SerializeError> {
93        value.serialize(self)
94    }
95
96    fn serialize_unit(self) -> Result<Item, SerializeError> {
97        one(Node::atom(""))
98    }
99
100    fn serialize_unit_struct(self, _name: &'static str) -> Result<Item, SerializeError> {
101        one(Node::atom(""))
102    }
103
104    fn serialize_unit_variant(
105        self,
106        _name: &'static str,
107        index: u32,
108        _variant: &'static str,
109    ) -> Result<Item, SerializeError> {
110        one(Node::from(index))
111    }
112
113    fn serialize_newtype_struct<T: Serialize + ?Sized>(
114        self,
115        name: &'static str,
116        value: &T,
117    ) -> Result<Item, SerializeError> {
118        match name {
119            REST => match to_node(value)?.into_list() {
120                Some(items) => Ok(Item::Splice(items)),
121                None => Err(SerializeError::new("a rest must serialize as a sequence")),
122            },
123            ATOM => match to_node(value)?.into_value() {
124                Value::Str(s) | Value::Atom(s) => one(Node::atom(s)),
125                Value::List(_) => Err(SerializeError::new("an atom must serialize as a string")),
126            },
127            _ => value.serialize(self),
128        }
129    }
130
131    fn serialize_newtype_variant<T: Serialize + ?Sized>(
132        self,
133        name: &'static str,
134        index: u32,
135        _variant: &'static str,
136        value: &T,
137    ) -> Result<Item, SerializeError> {
138        if name == VALUE {
139            return value.serialize(self);
140        }
141        one(Node::list([Node::from(index), to_node(value)?]))
142    }
143
144    fn serialize_seq(self, len: Option<usize>) -> Result<List, SerializeError> {
145        Ok(List::with_capacity(len.unwrap_or(0)))
146    }
147
148    fn serialize_tuple(self, len: usize) -> Result<List, SerializeError> {
149        Ok(List::with_capacity(len))
150    }
151
152    fn serialize_tuple_struct(
153        self,
154        _name: &'static str,
155        len: usize,
156    ) -> Result<List, SerializeError> {
157        Ok(List::with_capacity(len))
158    }
159
160    fn serialize_tuple_variant(
161        self,
162        _name: &'static str,
163        index: u32,
164        _variant: &'static str,
165        len: usize,
166    ) -> Result<List, SerializeError> {
167        Ok(List::tagged(index, len))
168    }
169
170    fn serialize_map(self, len: Option<usize>) -> Result<Map, SerializeError> {
171        Ok(Map {
172            items: Vec::with_capacity(len.unwrap_or(0)),
173            key: None,
174        })
175    }
176
177    fn serialize_struct(self, _name: &'static str, len: usize) -> Result<List, SerializeError> {
178        Ok(List::with_capacity(len))
179    }
180
181    fn serialize_struct_variant(
182        self,
183        _name: &'static str,
184        index: u32,
185        _variant: &'static str,
186        len: usize,
187    ) -> Result<List, SerializeError> {
188        Ok(List::tagged(index, len))
189    }
190}
191
192struct List {
193    items: Vec<Node>,
194}
195
196impl List {
197    fn with_capacity(len: usize) -> Self {
198        List {
199            items: Vec::with_capacity(len),
200        }
201    }
202
203    fn tagged(index: u32, len: usize) -> Self {
204        let mut list = List::with_capacity(len + 1);
205        list.items.push(Node::from(index));
206        list
207    }
208
209    fn push<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), SerializeError> {
210        match value.serialize(NodeSerializer)? {
211            Item::One(node) => self.items.push(node),
212            Item::Splice(items) => self.items.extend(items),
213        }
214        Ok(())
215    }
216
217    fn finish(self) -> Result<Item, SerializeError> {
218        one(Node::list(self.items))
219    }
220}
221
222macro_rules! impl_list {
223    ($($trait:ident :: $method:ident($($key:ident: $key_ty:ty)?)),* $(,)?) => {$(
224        impl ser::$trait for List {
225            type Ok = Item;
226            type Error = SerializeError;
227
228            fn $method<T: Serialize + ?Sized>(
229                &mut self,
230                $($key: $key_ty,)?
231                value: &T,
232            ) -> Result<(), SerializeError> {
233                self.push(value)
234            }
235
236            fn end(self) -> Result<Item, SerializeError> {
237                self.finish()
238            }
239        }
240    )*};
241}
242
243impl_list! {
244    SerializeSeq::serialize_element(),
245    SerializeTuple::serialize_element(),
246    SerializeTupleStruct::serialize_field(),
247    SerializeTupleVariant::serialize_field(),
248}
249
250impl ser::SerializeStruct for List {
251    type Ok = Item;
252    type Error = SerializeError;
253
254    fn serialize_field<T: Serialize + ?Sized>(
255        &mut self,
256        _key: &'static str,
257        value: &T,
258    ) -> Result<(), SerializeError> {
259        self.push(value)
260    }
261
262    /// `skip_serializing_if` must not shift the following fields: an empty atom keeps the slot.
263    fn skip_field(&mut self, _key: &'static str) -> Result<(), SerializeError> {
264        self.items.push(Node::atom(""));
265        Ok(())
266    }
267
268    fn end(self) -> Result<Item, SerializeError> {
269        self.finish()
270    }
271}
272
273impl ser::SerializeStructVariant for List {
274    type Ok = Item;
275    type Error = SerializeError;
276
277    fn serialize_field<T: Serialize + ?Sized>(
278        &mut self,
279        _key: &'static str,
280        value: &T,
281    ) -> Result<(), SerializeError> {
282        self.push(value)
283    }
284
285    fn skip_field(&mut self, _key: &'static str) -> Result<(), SerializeError> {
286        self.items.push(Node::atom(""));
287        Ok(())
288    }
289
290    fn end(self) -> Result<Item, SerializeError> {
291        self.finish()
292    }
293}
294
295/// Written as a list of `{key,value}` pairs.
296struct Map {
297    items: Vec<Node>,
298    key: Option<Node>,
299}
300
301impl ser::SerializeMap for Map {
302    type Ok = Item;
303    type Error = SerializeError;
304
305    fn serialize_key<T: Serialize + ?Sized>(&mut self, key: &T) -> Result<(), SerializeError> {
306        self.key = Some(to_node(key)?);
307        Ok(())
308    }
309
310    fn serialize_value<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), SerializeError> {
311        let key = self
312            .key
313            .take()
314            .ok_or_else(|| SerializeError::new("map value written before its key"))?;
315        self.items.push(Node::list([key, to_node(value)?]));
316        Ok(())
317    }
318
319    fn end(self) -> Result<Item, SerializeError> {
320        one(Node::list(self.items))
321    }
322}