Skip to main content

nested_text/
ser.rs

1use crate::dumper::{dumps, DumpOptions};
2use crate::error::{Error, ErrorKind};
3use crate::value::Value;
4
5use serde::ser::{self, Serialize};
6
7/// Serialize a value to a NestedText string.
8pub fn to_string<T: Serialize>(value: &T) -> Result<String, Error> {
9    let v = value.serialize(ValueSerializer)?;
10    Ok(dumps(&v, &DumpOptions::default()))
11}
12
13/// Serialize a value to a NestedText string with custom options.
14pub fn to_string_with_options<T: Serialize>(
15    value: &T,
16    options: &DumpOptions,
17) -> Result<String, Error> {
18    let v = value.serialize(ValueSerializer)?;
19    Ok(dumps(&v, options))
20}
21
22struct ValueSerializer;
23
24impl ser::Serializer for ValueSerializer {
25    type Ok = Value;
26    type Error = Error;
27    type SerializeSeq = SeqSerializer;
28    type SerializeTuple = SeqSerializer;
29    type SerializeTupleStruct = SeqSerializer;
30    type SerializeTupleVariant = TupleVariantSerializer;
31    type SerializeMap = MapSerializer;
32    type SerializeStruct = MapSerializer;
33    type SerializeStructVariant = StructVariantSerializer;
34
35    fn serialize_bool(self, v: bool) -> Result<Value, Error> {
36        Ok(Value::String(v.to_string()))
37    }
38
39    fn serialize_i8(self, v: i8) -> Result<Value, Error> {
40        Ok(Value::String(v.to_string()))
41    }
42
43    fn serialize_i16(self, v: i16) -> Result<Value, Error> {
44        Ok(Value::String(v.to_string()))
45    }
46
47    fn serialize_i32(self, v: i32) -> Result<Value, Error> {
48        Ok(Value::String(v.to_string()))
49    }
50
51    fn serialize_i64(self, v: i64) -> Result<Value, Error> {
52        Ok(Value::String(v.to_string()))
53    }
54
55    fn serialize_u8(self, v: u8) -> Result<Value, Error> {
56        Ok(Value::String(v.to_string()))
57    }
58
59    fn serialize_u16(self, v: u16) -> Result<Value, Error> {
60        Ok(Value::String(v.to_string()))
61    }
62
63    fn serialize_u32(self, v: u32) -> Result<Value, Error> {
64        Ok(Value::String(v.to_string()))
65    }
66
67    fn serialize_u64(self, v: u64) -> Result<Value, Error> {
68        Ok(Value::String(v.to_string()))
69    }
70
71    fn serialize_f32(self, v: f32) -> Result<Value, Error> {
72        Ok(Value::String(v.to_string()))
73    }
74
75    fn serialize_f64(self, v: f64) -> Result<Value, Error> {
76        Ok(Value::String(v.to_string()))
77    }
78
79    fn serialize_char(self, v: char) -> Result<Value, Error> {
80        Ok(Value::String(v.to_string()))
81    }
82
83    fn serialize_str(self, v: &str) -> Result<Value, Error> {
84        Ok(Value::String(v.to_string()))
85    }
86
87    fn serialize_bytes(self, _v: &[u8]) -> Result<Value, Error> {
88        Err(Error::new(
89            ErrorKind::UnsupportedType,
90            "NestedText does not support byte arrays",
91        ))
92    }
93
94    fn serialize_none(self) -> Result<Value, Error> {
95        Ok(Value::String(String::new()))
96    }
97
98    fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Value, Error> {
99        value.serialize(self)
100    }
101
102    fn serialize_unit(self) -> Result<Value, Error> {
103        Ok(Value::String(String::new()))
104    }
105
106    fn serialize_unit_struct(self, _name: &'static str) -> Result<Value, Error> {
107        Ok(Value::String(String::new()))
108    }
109
110    fn serialize_unit_variant(
111        self,
112        _name: &'static str,
113        _variant_index: u32,
114        variant: &'static str,
115    ) -> Result<Value, Error> {
116        Ok(Value::String(variant.to_string()))
117    }
118
119    fn serialize_newtype_struct<T: ?Sized + Serialize>(
120        self,
121        _name: &'static str,
122        value: &T,
123    ) -> Result<Value, Error> {
124        value.serialize(self)
125    }
126
127    fn serialize_newtype_variant<T: ?Sized + Serialize>(
128        self,
129        _name: &'static str,
130        _variant_index: u32,
131        variant: &'static str,
132        value: &T,
133    ) -> Result<Value, Error> {
134        let inner = value.serialize(ValueSerializer)?;
135        Ok(Value::Dict(vec![(variant.to_string(), inner)]))
136    }
137
138    fn serialize_seq(self, len: Option<usize>) -> Result<SeqSerializer, Error> {
139        Ok(SeqSerializer {
140            items: Vec::with_capacity(len.unwrap_or(0)),
141        })
142    }
143
144    fn serialize_tuple(self, len: usize) -> Result<SeqSerializer, Error> {
145        self.serialize_seq(Some(len))
146    }
147
148    fn serialize_tuple_struct(
149        self,
150        _name: &'static str,
151        len: usize,
152    ) -> Result<SeqSerializer, Error> {
153        self.serialize_seq(Some(len))
154    }
155
156    fn serialize_tuple_variant(
157        self,
158        _name: &'static str,
159        _variant_index: u32,
160        variant: &'static str,
161        len: usize,
162    ) -> Result<TupleVariantSerializer, Error> {
163        Ok(TupleVariantSerializer {
164            variant: variant.to_string(),
165            items: Vec::with_capacity(len),
166        })
167    }
168
169    fn serialize_map(self, len: Option<usize>) -> Result<MapSerializer, Error> {
170        Ok(MapSerializer {
171            pairs: Vec::with_capacity(len.unwrap_or(0)),
172            next_key: None,
173        })
174    }
175
176    fn serialize_struct(
177        self,
178        _name: &'static str,
179        len: usize,
180    ) -> Result<MapSerializer, Error> {
181        self.serialize_map(Some(len))
182    }
183
184    fn serialize_struct_variant(
185        self,
186        _name: &'static str,
187        _variant_index: u32,
188        variant: &'static str,
189        len: usize,
190    ) -> Result<StructVariantSerializer, Error> {
191        Ok(StructVariantSerializer {
192            variant: variant.to_string(),
193            pairs: Vec::with_capacity(len),
194        })
195    }
196}
197
198// Sequence serializer
199struct SeqSerializer {
200    items: Vec<Value>,
201}
202
203impl ser::SerializeSeq for SeqSerializer {
204    type Ok = Value;
205    type Error = Error;
206
207    fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
208        self.items.push(value.serialize(ValueSerializer)?);
209        Ok(())
210    }
211
212    fn end(self) -> Result<Value, Error> {
213        Ok(Value::List(self.items))
214    }
215}
216
217impl ser::SerializeTuple for SeqSerializer {
218    type Ok = Value;
219    type Error = Error;
220
221    fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
222        ser::SerializeSeq::serialize_element(self, value)
223    }
224
225    fn end(self) -> Result<Value, Error> {
226        ser::SerializeSeq::end(self)
227    }
228}
229
230impl ser::SerializeTupleStruct for SeqSerializer {
231    type Ok = Value;
232    type Error = Error;
233
234    fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
235        ser::SerializeSeq::serialize_element(self, value)
236    }
237
238    fn end(self) -> Result<Value, Error> {
239        ser::SerializeSeq::end(self)
240    }
241}
242
243// Tuple variant serializer
244struct TupleVariantSerializer {
245    variant: String,
246    items: Vec<Value>,
247}
248
249impl ser::SerializeTupleVariant for TupleVariantSerializer {
250    type Ok = Value;
251    type Error = Error;
252
253    fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
254        self.items.push(value.serialize(ValueSerializer)?);
255        Ok(())
256    }
257
258    fn end(self) -> Result<Value, Error> {
259        Ok(Value::Dict(vec![(
260            self.variant,
261            Value::List(self.items),
262        )]))
263    }
264}
265
266// Map serializer
267struct MapSerializer {
268    pairs: Vec<(String, Value)>,
269    next_key: Option<String>,
270}
271
272impl ser::SerializeMap for MapSerializer {
273    type Ok = Value;
274    type Error = Error;
275
276    fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), Error> {
277        let key_value = key.serialize(ValueSerializer)?;
278        let key_str = match key_value {
279            Value::String(s) => s,
280            _ => {
281                return Err(Error::new(
282                    ErrorKind::UnsupportedType,
283                    "map keys must be strings",
284                ))
285            }
286        };
287        self.next_key = Some(key_str);
288        Ok(())
289    }
290
291    fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
292        let key = self.next_key.take().expect("serialize_value called before serialize_key");
293        self.pairs.push((key, value.serialize(ValueSerializer)?));
294        Ok(())
295    }
296
297    fn end(self) -> Result<Value, Error> {
298        Ok(Value::Dict(self.pairs))
299    }
300}
301
302impl ser::SerializeStruct for MapSerializer {
303    type Ok = Value;
304    type Error = Error;
305
306    fn serialize_field<T: ?Sized + Serialize>(
307        &mut self,
308        key: &'static str,
309        value: &T,
310    ) -> Result<(), Error> {
311        self.pairs
312            .push((key.to_string(), value.serialize(ValueSerializer)?));
313        Ok(())
314    }
315
316    fn end(self) -> Result<Value, Error> {
317        Ok(Value::Dict(self.pairs))
318    }
319}
320
321// Struct variant serializer
322struct StructVariantSerializer {
323    variant: String,
324    pairs: Vec<(String, Value)>,
325}
326
327impl ser::SerializeStructVariant for StructVariantSerializer {
328    type Ok = Value;
329    type Error = Error;
330
331    fn serialize_field<T: ?Sized + Serialize>(
332        &mut self,
333        key: &'static str,
334        value: &T,
335    ) -> Result<(), Error> {
336        self.pairs
337            .push((key.to_string(), value.serialize(ValueSerializer)?));
338        Ok(())
339    }
340
341    fn end(self) -> Result<Value, Error> {
342        Ok(Value::Dict(vec![(
343            self.variant,
344            Value::Dict(self.pairs),
345        )]))
346    }
347}
348
349// Make Error work with serde::ser
350impl ser::Error for Error {
351    fn custom<T: std::fmt::Display>(msg: T) -> Self {
352        Error::new(ErrorKind::UnsupportedType, msg.to_string())
353    }
354}
355
356#[cfg(test)]
357mod tests {
358    use super::*;
359    use serde::Serialize;
360
361    #[test]
362    fn test_serialize_struct() {
363        #[derive(Serialize)]
364        struct Config {
365            name: String,
366            age: u32,
367        }
368        let config = Config {
369            name: "Alice".to_string(),
370            age: 30,
371        };
372        let s = to_string(&config).unwrap();
373        assert_eq!(s, "name: Alice\nage: 30\n");
374    }
375
376    #[test]
377    fn test_serialize_vec() {
378        let v = vec!["hello", "world"];
379        let s = to_string(&v).unwrap();
380        assert_eq!(s, "- hello\n- world\n");
381    }
382
383    #[test]
384    fn test_serialize_bool() {
385        #[derive(Serialize)]
386        struct Flags {
387            debug: bool,
388        }
389        let flags = Flags { debug: true };
390        let s = to_string(&flags).unwrap();
391        assert_eq!(s, "debug: true\n");
392    }
393
394    #[test]
395    fn test_serialize_option() {
396        #[derive(Serialize)]
397        struct MaybeValue {
398            present: Option<String>,
399            absent: Option<String>,
400        }
401        let v = MaybeValue {
402            present: Some("hello".to_string()),
403            absent: None,
404        };
405        let s = to_string(&v).unwrap();
406        assert_eq!(s, "present: hello\nabsent:\n");
407    }
408
409    #[test]
410    fn test_serialize_enum() {
411        #[derive(Serialize)]
412        enum Color {
413            Red,
414        }
415        let s = to_string(&Color::Red).unwrap();
416        assert_eq!(s, "> Red\n");
417    }
418
419    #[test]
420    fn test_serialize_nested() {
421        #[derive(Serialize)]
422        struct Outer {
423            items: Vec<String>,
424        }
425        let v = Outer {
426            items: vec!["a".to_string(), "b".to_string()],
427        };
428        let s = to_string(&v).unwrap();
429        assert_eq!(s, "items:\n    - a\n    - b\n");
430    }
431}