Skip to main content

yaml_rt_serde/value/
ser.rs

1use serde::Serialize;
2use serde::de::DeserializeOwned;
3use serde::ser::{self, SerializeTuple as _};
4
5use super::{Mapping, Number, TAGGED_VALUE_TOKEN, Tag, TaggedValue, Value};
6use crate::{Error, Result};
7
8/// Serializer whose output is an in-memory [`Value`].
9#[derive(Clone, Copy, Debug, Default)]
10pub struct Serializer;
11
12/// Converts a serializable value into a generic YAML [`Value`].
13///
14/// # Errors
15///
16/// Returns an error raised by the value's `Serialize` implementation or when
17/// it requests a representation unsupported by yaml-rt-serde.
18pub fn to_value<T>(value: T) -> Result<Value>
19where
20    T: Serialize,
21{
22    value.serialize(Serializer)
23}
24
25/// Converts a generic YAML [`Value`] into a typed value.
26///
27/// # Errors
28///
29/// Returns an error when the value does not match `T`.
30pub fn from_value<T>(value: Value) -> Result<T>
31where
32    T: DeserializeOwned,
33{
34    T::deserialize(value)
35}
36
37/// Sequence accumulator used by [`Serializer`].
38#[doc(hidden)]
39pub struct SerializeSequence {
40    values: Vec<Value>,
41    tag: Option<Tag>,
42}
43
44impl SerializeSequence {
45    fn new(len: Option<usize>, tag: Option<Tag>) -> Self {
46        Self {
47            values: Vec::with_capacity(len.unwrap_or(0)),
48            tag,
49        }
50    }
51
52    fn push<T>(&mut self, value: &T) -> Result<()>
53    where
54        T: ?Sized + Serialize,
55    {
56        self.values.push(value.serialize(Serializer)?);
57        Ok(())
58    }
59
60    fn finish(self) -> Value {
61        tagged(self.tag, Value::Sequence(self.values))
62    }
63}
64
65impl ser::SerializeSeq for SerializeSequence {
66    type Ok = Value;
67    type Error = Error;
68
69    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
70    where
71        T: ?Sized + Serialize,
72    {
73        self.push(value)
74    }
75
76    fn end(self) -> Result<Value> {
77        Ok(self.finish())
78    }
79}
80
81impl ser::SerializeTuple for SerializeSequence {
82    type Ok = Value;
83    type Error = Error;
84
85    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
86    where
87        T: ?Sized + Serialize,
88    {
89        self.push(value)
90    }
91
92    fn end(self) -> Result<Value> {
93        Ok(self.finish())
94    }
95}
96
97impl ser::SerializeTupleStruct for SerializeSequence {
98    type Ok = Value;
99    type Error = Error;
100
101    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
102    where
103        T: ?Sized + Serialize,
104    {
105        self.push(value)
106    }
107
108    fn end(self) -> Result<Value> {
109        Ok(self.finish())
110    }
111}
112
113impl ser::SerializeTupleVariant for SerializeSequence {
114    type Ok = Value;
115    type Error = Error;
116
117    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
118    where
119        T: ?Sized + Serialize,
120    {
121        self.push(value)
122    }
123
124    fn end(self) -> Result<Value> {
125        Ok(self.finish())
126    }
127}
128
129/// Mapping accumulator used by [`Serializer`].
130#[doc(hidden)]
131pub struct SerializeMapping {
132    entries: Mapping,
133    pending: Option<Value>,
134    tag: Option<Tag>,
135}
136
137impl SerializeMapping {
138    fn new(len: Option<usize>, tag: Option<Tag>) -> Self {
139        Self {
140            entries: Mapping::with_capacity(len.unwrap_or(0)),
141            pending: None,
142            tag,
143        }
144    }
145
146    fn insert(&mut self, key: Value, value: Value) {
147        self.entries.insert(key, value);
148    }
149
150    fn finish(self) -> Result<Value> {
151        if self.pending.is_some() {
152            return Err(Error::message("map ended before serializing a value"));
153        }
154        Ok(tagged(self.tag, Value::Mapping(self.entries)))
155    }
156}
157
158impl ser::SerializeMap for SerializeMapping {
159    type Ok = Value;
160    type Error = Error;
161
162    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
163    where
164        T: ?Sized + Serialize,
165    {
166        if self.pending.is_some() {
167            return Err(Error::message("map key serialized before its value"));
168        }
169        self.pending = Some(key.serialize(Serializer)?);
170        Ok(())
171    }
172
173    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
174    where
175        T: ?Sized + Serialize,
176    {
177        let key = self
178            .pending
179            .take()
180            .ok_or_else(|| Error::message("map value serialized before its key"))?;
181        self.insert(key, value.serialize(Serializer)?);
182        Ok(())
183    }
184
185    fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<()>
186    where
187        K: ?Sized + Serialize,
188        V: ?Sized + Serialize,
189    {
190        self.insert(key.serialize(Serializer)?, value.serialize(Serializer)?);
191        Ok(())
192    }
193
194    fn end(self) -> Result<Value> {
195        self.finish()
196    }
197}
198
199impl ser::SerializeStruct for SerializeMapping {
200    type Ok = Value;
201    type Error = Error;
202
203    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
204    where
205        T: ?Sized + Serialize,
206    {
207        self.insert(Value::String(key.to_owned()), value.serialize(Serializer)?);
208        Ok(())
209    }
210
211    fn end(self) -> Result<Value> {
212        self.finish()
213    }
214}
215
216impl ser::SerializeStructVariant for SerializeMapping {
217    type Ok = Value;
218    type Error = Error;
219
220    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
221    where
222        T: ?Sized + Serialize,
223    {
224        ser::SerializeStruct::serialize_field(self, key, value)
225    }
226
227    fn end(self) -> Result<Value> {
228        self.finish()
229    }
230}
231
232impl ser::Serializer for Serializer {
233    type Ok = Value;
234    type Error = Error;
235    type SerializeSeq = SerializeSequence;
236    type SerializeTuple = SerializeSequence;
237    type SerializeTupleStruct = SerializeSequence;
238    type SerializeTupleVariant = SerializeSequence;
239    type SerializeMap = SerializeMapping;
240    type SerializeStruct = SerializeMapping;
241    type SerializeStructVariant = SerializeMapping;
242
243    fn serialize_bool(self, value: bool) -> Result<Value> {
244        Ok(Value::Bool(value))
245    }
246
247    fn serialize_i8(self, value: i8) -> Result<Value> {
248        self.serialize_i128(value.into())
249    }
250
251    fn serialize_i16(self, value: i16) -> Result<Value> {
252        self.serialize_i128(value.into())
253    }
254
255    fn serialize_i32(self, value: i32) -> Result<Value> {
256        self.serialize_i128(value.into())
257    }
258
259    fn serialize_i64(self, value: i64) -> Result<Value> {
260        self.serialize_i128(value.into())
261    }
262
263    fn serialize_i128(self, value: i128) -> Result<Value> {
264        Ok(Value::Number(Number::from(value)))
265    }
266
267    fn serialize_u8(self, value: u8) -> Result<Value> {
268        self.serialize_u128(value.into())
269    }
270
271    fn serialize_u16(self, value: u16) -> Result<Value> {
272        self.serialize_u128(value.into())
273    }
274
275    fn serialize_u32(self, value: u32) -> Result<Value> {
276        self.serialize_u128(value.into())
277    }
278
279    fn serialize_u64(self, value: u64) -> Result<Value> {
280        self.serialize_u128(value.into())
281    }
282
283    fn serialize_u128(self, value: u128) -> Result<Value> {
284        Ok(Value::Number(Number::from(value)))
285    }
286
287    fn serialize_f32(self, value: f32) -> Result<Value> {
288        Ok(Value::Number(Number::from(value)))
289    }
290
291    fn serialize_f64(self, value: f64) -> Result<Value> {
292        Ok(Value::Number(Number::from(value)))
293    }
294
295    fn serialize_char(self, value: char) -> Result<Value> {
296        Ok(Value::String(value.to_string()))
297    }
298
299    fn serialize_str(self, value: &str) -> Result<Value> {
300        Ok(Value::String(value.to_owned()))
301    }
302
303    fn serialize_bytes(self, _value: &[u8]) -> Result<Value> {
304        Err(Error::message(
305            "serialization and deserialization of bytes in YAML is not implemented",
306        ))
307    }
308
309    fn serialize_none(self) -> Result<Value> {
310        Ok(Value::Null)
311    }
312
313    fn serialize_some<T>(self, value: &T) -> Result<Value>
314    where
315        T: ?Sized + Serialize,
316    {
317        value.serialize(self)
318    }
319
320    fn serialize_unit(self) -> Result<Value> {
321        Ok(Value::Null)
322    }
323
324    fn serialize_unit_struct(self, _name: &'static str) -> Result<Value> {
325        Ok(Value::Null)
326    }
327
328    fn serialize_unit_variant(
329        self,
330        _name: &'static str,
331        _index: u32,
332        variant: &'static str,
333    ) -> Result<Value> {
334        Ok(Value::String(variant.to_owned()))
335    }
336
337    fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<Value>
338    where
339        T: ?Sized + Serialize,
340    {
341        let value = value.serialize(self)?;
342        if name != TAGGED_VALUE_TOKEN {
343            return Ok(value);
344        }
345        let Value::Sequence(mut parts) = value else {
346            return Err(Error::message("invalid tagged value payload"));
347        };
348        if parts.len() != 2 {
349            return Err(Error::message("invalid tagged value payload"));
350        }
351        let inner = parts.pop().expect("tagged payload contains a value");
352        let tag = parts.pop().expect("tagged payload contains a tag");
353        let Value::String(tag) = tag else {
354            return Err(Error::message("invalid tagged value tag"));
355        };
356        Ok(Value::Tagged(Box::new(TaggedValue {
357            tag: Tag::new(tag),
358            value: inner,
359        })))
360    }
361
362    fn serialize_newtype_variant<T>(
363        self,
364        _name: &'static str,
365        _index: u32,
366        variant: &'static str,
367        value: &T,
368    ) -> Result<Value>
369    where
370        T: ?Sized + Serialize,
371    {
372        let value = value.serialize(self)?;
373        if matches!(value, Value::Tagged(_)) {
374            return Err(Error::message(
375                "serializing nested enums in YAML is not supported",
376            ));
377        }
378        Ok(tagged(Some(Tag::new(variant)), value))
379    }
380
381    fn serialize_seq(self, len: Option<usize>) -> Result<SerializeSequence> {
382        Ok(SerializeSequence::new(len, None))
383    }
384
385    fn serialize_tuple(self, len: usize) -> Result<SerializeSequence> {
386        Ok(SerializeSequence::new(Some(len), None))
387    }
388
389    fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<SerializeSequence> {
390        Ok(SerializeSequence::new(Some(len), None))
391    }
392
393    fn serialize_tuple_variant(
394        self,
395        _name: &'static str,
396        _index: u32,
397        variant: &'static str,
398        len: usize,
399    ) -> Result<SerializeSequence> {
400        Ok(SerializeSequence::new(Some(len), Some(Tag::new(variant))))
401    }
402
403    fn serialize_map(self, len: Option<usize>) -> Result<SerializeMapping> {
404        Ok(SerializeMapping::new(len, None))
405    }
406
407    fn serialize_struct(self, _name: &'static str, len: usize) -> Result<SerializeMapping> {
408        Ok(SerializeMapping::new(Some(len), None))
409    }
410
411    fn serialize_struct_variant(
412        self,
413        _name: &'static str,
414        _index: u32,
415        variant: &'static str,
416        len: usize,
417    ) -> Result<SerializeMapping> {
418        Ok(SerializeMapping::new(Some(len), Some(Tag::new(variant))))
419    }
420
421    fn collect_str<T>(self, value: &T) -> Result<Value>
422    where
423        T: ?Sized + std::fmt::Display,
424    {
425        Ok(Value::String(value.to_string()))
426    }
427
428    fn is_human_readable(&self) -> bool {
429        true
430    }
431}
432
433fn tagged(tag: Option<Tag>, value: Value) -> Value {
434    match tag {
435        Some(tag) => Value::Tagged(Box::new(TaggedValue { tag, value })),
436        None => value,
437    }
438}
439
440struct TaggedPayload<'a>(&'a TaggedValue);
441
442impl Serialize for TaggedPayload<'_> {
443    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
444    where
445        S: serde::Serializer,
446    {
447        let mut tuple = serializer.serialize_tuple(2)?;
448        tuple.serialize_element(&self.0.tag.to_string())?;
449        tuple.serialize_element(&self.0.value)?;
450        tuple.end()
451    }
452}
453
454impl Serialize for Value {
455    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
456    where
457        S: serde::Serializer,
458    {
459        match self {
460            Self::Null => serializer.serialize_unit(),
461            Self::Bool(value) => serializer.serialize_bool(*value),
462            Self::Number(value) => value.serialize(serializer),
463            Self::String(value) => serializer.serialize_str(value),
464            Self::Sequence(values) => values.serialize(serializer),
465            Self::Mapping(mapping) => mapping.serialize(serializer),
466            Self::Tagged(tagged) => {
467                serializer.serialize_newtype_struct(TAGGED_VALUE_TOKEN, &TaggedPayload(tagged))
468            }
469        }
470    }
471}