valuable_serde/
lib.rs

1#![warn(
2    missing_debug_implementations,
3    missing_docs,
4    rust_2018_idioms,
5    unreachable_pub
6)]
7#![cfg_attr(not(feature = "std"), no_std)]
8
9//! [`serde::Serialize`] implementation for [`Valuable`] types.
10//!
11//! [Valuable][`valuable`] provides object-safe value inspection. Use cases
12//! include passing structured data to trait objects and object-safe serialization.
13//!
14//! This crate provides a bridge between [`valuable`] and the [`serde`]
15//! serialization ecosystem. Using [`Serializable`] allows any type
16//! that implements `valuable`'s [`Valuable`] trait to be serialized by any
17//! [`serde::ser::Serializer`].
18//!
19//! [`valuable`]: https://docs.rs/valuable
20//! [`serde`]: https://docs.rs/serde
21//!
22//! # Examples
23//!
24//! ```
25//! use valuable::Valuable;
26//! use valuable_serde::Serializable;
27//!
28//! #[derive(Valuable)]
29//! struct Point {
30//!     x: i32,
31//!     y: i32,
32//! }
33//!
34//! let point = Point { x: 1, y: 2 };
35//!
36//! let value = Serializable::new(&point);
37//!
38//! assert_eq!(
39//!     serde_json::to_string(&value).unwrap(),
40//!     r#"{"x":1,"y":2}"#,
41//! );
42//! ```
43
44use core::{fmt, mem};
45
46use serde::ser::{
47    Error, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
48    SerializeTupleStruct, SerializeTupleVariant,
49};
50use serde::{Serialize, Serializer};
51use valuable::{
52    EnumDef, Fields, NamedValues, StructDef, TupleDef, Valuable, Value, Variant, VariantDef, Visit,
53};
54
55/// A wrapper around [`Valuable`] types that implements [`Serialize`].
56pub struct Serializable<V>(V);
57
58impl<V> Serializable<V>
59where
60    V: Valuable,
61{
62    /// Creates a new `Serializable`.
63    pub fn new(v: V) -> Self {
64        Self(v)
65    }
66
67    /// Returns a reference to the underlying value.
68    pub fn get_ref(&self) -> &V {
69        &self.0
70    }
71
72    /// Returns a mutable reference to the underlying value.
73    pub fn get_mut(&mut self) -> &mut V {
74        &mut self.0
75    }
76
77    /// Unwraps this `Serializable`, returning the underlying value.
78    pub fn into_inner(self) -> V {
79        self.0
80    }
81}
82
83impl<V> fmt::Debug for Serializable<V>
84where
85    V: Valuable,
86{
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        fmt::Debug::fmt(&self.as_value(), f)
89    }
90}
91
92impl<V> Valuable for Serializable<V>
93where
94    V: Valuable,
95{
96    fn as_value(&self) -> Value<'_> {
97        self.0.as_value()
98    }
99
100    fn visit(&self, visit: &mut dyn Visit) {
101        self.0.visit(visit);
102    }
103}
104
105impl<V> Serialize for Serializable<V>
106where
107    V: Valuable,
108{
109    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
110    where
111        S: Serializer,
112    {
113        match self.0.as_value() {
114            Value::Bool(b) => serializer.serialize_bool(b),
115            Value::I8(n) => serializer.serialize_i8(n),
116            Value::I16(n) => serializer.serialize_i16(n),
117            Value::I32(n) => serializer.serialize_i32(n),
118            Value::I64(n) => serializer.serialize_i64(n),
119            Value::I128(n) => serializer.serialize_i128(n),
120            Value::Isize(n) => serializer.serialize_i64(n as _),
121            Value::U8(n) => serializer.serialize_u8(n),
122            Value::U16(n) => serializer.serialize_u16(n),
123            Value::U32(n) => serializer.serialize_u32(n),
124            Value::U64(n) => serializer.serialize_u64(n),
125            Value::U128(n) => serializer.serialize_u128(n),
126            Value::Usize(n) => serializer.serialize_u64(n as _),
127            Value::F32(n) => serializer.serialize_f32(n),
128            Value::F64(n) => serializer.serialize_f64(n),
129            Value::Char(c) => serializer.serialize_char(c),
130            Value::String(s) => serializer.serialize_str(s),
131            Value::Unit => serializer.serialize_unit(),
132            Value::Listable(l) => {
133                let size_hint = l.size_hint();
134                let mut ser = serializer.serialize_seq(Some(size_hint.1.unwrap_or(size_hint.0)))?;
135                let mut visitor = VisitList::<S>::Serializer(&mut ser);
136                l.visit(&mut visitor);
137                if let VisitList::Error(e) = visitor {
138                    return Err(e);
139                }
140                ser.end()
141            }
142            Value::Mappable(m) => {
143                let size_hint = m.size_hint();
144                let mut ser = serializer.serialize_map(size_hint.1)?;
145                let mut visitor = VisitMap::<S>::Serializer(&mut ser);
146                m.visit(&mut visitor);
147                if let VisitMap::Error(e) = visitor {
148                    return Err(e);
149                }
150                ser.end()
151            }
152            Value::Structable(s) => match s.definition() {
153                StructDef::Static { name, fields, .. } => {
154                    let mut visitor = VisitStaticStruct::Start {
155                        name,
156                        fields,
157                        serializer,
158                    };
159                    s.visit(&mut visitor);
160                    match visitor {
161                        VisitStaticStruct::End(res) => res,
162                        _ => unreachable!(),
163                    }
164                }
165                StructDef::Dynamic { fields, .. } => {
166                    if fields.is_named() {
167                        // TODO: size_hint?
168                        let mut ser = serializer.serialize_map(None)?;
169                        let mut visitor = VisitDynamic::<S>::NamedFields(&mut ser);
170                        s.visit(&mut visitor);
171                        if let VisitDynamic::Error(e) = visitor {
172                            return Err(e);
173                        }
174                        ser.end()
175                    } else {
176                        // TODO: size_hint?
177                        let mut ser = serializer.serialize_seq(None)?;
178                        let mut visitor = VisitDynamic::<S>::UnnamedFields(&mut ser);
179                        s.visit(&mut visitor);
180                        if let VisitDynamic::Error(e) = visitor {
181                            return Err(e);
182                        }
183                        ser.end()
184                    }
185                }
186                def => unreachable!("{:?}", def),
187            },
188            Value::Enumerable(e) => match (e.definition(), e.variant()) {
189                (
190                    EnumDef::Static {
191                        name,
192                        variants: def,
193                        ..
194                    },
195                    Variant::Static(variant),
196                ) => {
197                    let mut visitor = VisitStaticEnum::Start {
198                        name,
199                        def,
200                        variant,
201                        serializer,
202                    };
203                    e.visit(&mut visitor);
204                    match visitor {
205                        VisitStaticEnum::End(res) => res,
206                        _ => unreachable!(),
207                    }
208                }
209                (EnumDef::Dynamic { .. }, variant) => {
210                    if variant.is_named_fields() {
211                        // TODO: size_hint?
212                        let mut ser = serializer.serialize_map(None)?;
213                        let mut visitor = VisitDynamic::<S>::NamedFields(&mut ser);
214                        e.visit(&mut visitor);
215                        if let VisitDynamic::Error(e) = visitor {
216                            return Err(e);
217                        }
218                        ser.end()
219                    } else {
220                        // TODO: size_hint?
221                        let mut ser = serializer.serialize_seq(None)?;
222                        let mut visitor = VisitDynamic::<S>::UnnamedFields(&mut ser);
223                        e.visit(&mut visitor);
224                        if let VisitDynamic::Error(e) = visitor {
225                            return Err(e);
226                        }
227                        ser.end()
228                    }
229                }
230                (EnumDef::Static { .. }, Variant::Dynamic(..)) => {
231                    Err(S::Error::custom("dynamic variant in static enum"))
232                }
233                def => unreachable!("{:?}", def),
234            },
235            Value::Tuplable(t) => {
236                let def = t.definition();
237                if def.is_unit() {
238                    return serializer.serialize_unit();
239                }
240                match def {
241                    TupleDef::Static { fields: len, .. } => {
242                        let ser = serializer.serialize_tuple(len)?;
243                        let mut visitor = VisitStaticTuple::<S>::Start(ser);
244                        t.visit(&mut visitor);
245                        match visitor {
246                            VisitStaticTuple::End(res) => res,
247                            _ => unreachable!(),
248                        }
249                    }
250                    TupleDef::Dynamic {
251                        fields: size_hint, ..
252                    } => {
253                        let mut ser = serializer.serialize_seq(size_hint.1)?;
254                        let mut visitor = VisitDynamic::<S>::UnnamedFields(&mut ser);
255                        t.visit(&mut visitor);
256                        if let VisitDynamic::Error(e) = visitor {
257                            return Err(e);
258                        }
259                        ser.end()
260                    }
261                    def => unreachable!("{:?}", def),
262                }
263            }
264            #[cfg(feature = "std")]
265            Value::Path(p) => Serialize::serialize(p, serializer),
266            #[cfg(feature = "std")]
267            Value::Error(e) => SerializeError(e).serialize(serializer),
268
269            v => unimplemented!("{:?}", v),
270        }
271    }
272}
273
274enum VisitList<'a, S: Serializer> {
275    Serializer(&'a mut S::SerializeSeq),
276    Error(S::Error),
277}
278
279impl<S: Serializer> Visit for VisitList<'_, S> {
280    fn visit_value(&mut self, value: Value<'_>) {
281        if let Self::Serializer(ser) = self {
282            if let Err(e) = ser.serialize_element(&Serializable(value)) {
283                *self = Self::Error(e);
284            }
285        }
286    }
287
288    fn visit_entry(&mut self, _: Value<'_>, _: Value<'_>) {
289        if !matches!(self, Self::Error(..)) {
290            *self = Self::Error(S::Error::custom("visit_entry in list"));
291        }
292    }
293
294    fn visit_named_fields(&mut self, _: &NamedValues<'_>) {
295        if !matches!(self, Self::Error(..)) {
296            *self = Self::Error(S::Error::custom("visit_named_fields in list"));
297        }
298    }
299
300    fn visit_unnamed_fields(&mut self, _: &[Value<'_>]) {
301        if !matches!(self, Self::Error(..)) {
302            *self = Self::Error(S::Error::custom("visit_unnamed_fields in list"));
303        }
304    }
305}
306
307enum VisitMap<'a, S: Serializer> {
308    Serializer(&'a mut S::SerializeMap),
309    Error(S::Error),
310}
311
312impl<S: Serializer> Visit for VisitMap<'_, S> {
313    fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
314        if let Self::Serializer(ser) = self {
315            if let Err(e) = ser.serialize_entry(&Serializable(key), &Serializable(value)) {
316                *self = Self::Error(e);
317            }
318        }
319    }
320
321    fn visit_value(&mut self, _: Value<'_>) {
322        if !matches!(self, Self::Error(..)) {
323            *self = Self::Error(S::Error::custom("visit_value in map"));
324        }
325    }
326
327    fn visit_named_fields(&mut self, _: &NamedValues<'_>) {
328        if !matches!(self, Self::Error(..)) {
329            *self = Self::Error(S::Error::custom("visit_named_fields in map"));
330        }
331    }
332
333    fn visit_unnamed_fields(&mut self, _: &[Value<'_>]) {
334        if !matches!(self, Self::Error(..)) {
335            *self = Self::Error(S::Error::custom("visit_unnamed_fields in map"));
336        }
337    }
338}
339
340enum VisitStaticStruct<S: Serializer> {
341    Start {
342        name: &'static str,
343        fields: Fields<'static>,
344        serializer: S,
345    },
346    End(Result<S::Ok, S::Error>),
347    Tmp,
348}
349
350impl<S: Serializer> Visit for VisitStaticStruct<S> {
351    fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
352        let (name, fields, serializer) = match mem::replace(self, Self::Tmp) {
353            Self::Start {
354                name,
355                fields: Fields::Named(fields),
356                serializer,
357            } => (name, fields, serializer),
358            mut res @ Self::End(..) => {
359                if matches!(res, Self::End(Ok(..))) {
360                    res = Self::End(Err(S::Error::custom(
361                        "visit_named_fields called multiple times in static struct",
362                    )));
363                }
364                *self = res;
365                return;
366            }
367            _ => unreachable!(),
368        };
369        let mut ser = match serializer.serialize_struct(name, named_values.len()) {
370            Ok(ser) => ser,
371            Err(e) => {
372                *self = Self::End(Err(e));
373                return;
374            }
375        };
376        for (i, (_, v)) in named_values.iter().enumerate() {
377            if let Err(e) = ser.serialize_field(fields[i].name(), &Serializable(v)) {
378                *self = Self::End(Err(e));
379                return;
380            }
381        }
382        *self = Self::End(ser.end());
383    }
384
385    fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
386        let (name, serializer) = match mem::replace(self, Self::Tmp) {
387            Self::Start {
388                name,
389                fields: Fields::Unnamed(_),
390                serializer,
391            } => (name, serializer),
392            mut res @ Self::End(..) => {
393                if matches!(res, Self::End(Ok(..))) {
394                    res = Self::End(Err(S::Error::custom(
395                        "visit_unnamed_fields called multiple times in static struct",
396                    )));
397                }
398                *self = res;
399                return;
400            }
401            _ => unreachable!(),
402        };
403        if values.len() == 1 {
404            *self = Self::End(serializer.serialize_newtype_struct(name, &Serializable(values[0])));
405            return;
406        }
407        let mut ser = match serializer.serialize_tuple_struct(name, values.len()) {
408            Ok(ser) => ser,
409            Err(e) => {
410                *self = Self::End(Err(e));
411                return;
412            }
413        };
414        for v in values {
415            if let Err(e) = ser.serialize_field(&Serializable(v)) {
416                *self = Self::End(Err(e));
417                return;
418            }
419        }
420        *self = Self::End(ser.end());
421    }
422
423    fn visit_entry(&mut self, _: Value<'_>, _: Value<'_>) {
424        if !matches!(self, Self::End(Err(..))) {
425            *self = Self::End(Err(S::Error::custom("visit_entry in struct")));
426        }
427    }
428
429    fn visit_value(&mut self, _: Value<'_>) {
430        if !matches!(self, Self::End(Err(..))) {
431            *self = Self::End(Err(S::Error::custom("visit_value in struct")));
432        }
433    }
434}
435
436enum VisitStaticEnum<S: Serializer> {
437    Start {
438        name: &'static str,
439        def: &'static [VariantDef<'static>],
440        variant: &'static VariantDef<'static>,
441        serializer: S,
442    },
443    End(Result<S::Ok, S::Error>),
444    Tmp,
445}
446
447impl<S: Serializer> Visit for VisitStaticEnum<S> {
448    fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
449        let (name, def, variant, serializer) = match mem::replace(self, Self::Tmp) {
450            Self::Start {
451                name,
452                def,
453                variant,
454                serializer,
455            } => (name, def, variant, serializer),
456            mut res @ Self::End(..) => {
457                if matches!(res, Self::End(Ok(..))) {
458                    res = Self::End(Err(S::Error::custom(
459                        "visit_named_fields called multiple times in static enum",
460                    )));
461                }
462                *self = res;
463                return;
464            }
465            _ => unreachable!(),
466        };
467        let variant_name = variant.name();
468        let variant_index = def.iter().position(|v| v.name() == variant_name).unwrap();
469        assert!(variant_index <= u32::MAX as usize);
470        let mut ser = match serializer.serialize_struct_variant(
471            name,
472            variant_index as _,
473            variant_name,
474            named_values.len(),
475        ) {
476            Ok(ser) => ser,
477            Err(e) => {
478                *self = Self::End(Err(e));
479                return;
480            }
481        };
482        let fields = match variant.fields() {
483            Fields::Named(fields) => fields,
484            Fields::Unnamed(_) => unreachable!(),
485        };
486        for (i, (_, v)) in named_values.iter().enumerate() {
487            if let Err(e) = ser.serialize_field(fields[i].name(), &Serializable(v)) {
488                *self = Self::End(Err(e));
489                return;
490            }
491        }
492        *self = Self::End(ser.end());
493    }
494
495    fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
496        let (name, def, variant, serializer) = match mem::replace(self, Self::Tmp) {
497            Self::Start {
498                name,
499                def,
500                variant,
501                serializer,
502            } => (name, def, variant, serializer),
503            mut res @ Self::End(..) => {
504                if matches!(res, Self::End(Ok(..))) {
505                    res = Self::End(Err(S::Error::custom(
506                        "visit_unnamed_fields called multiple times in static enum",
507                    )));
508                }
509                *self = res;
510                return;
511            }
512            _ => unreachable!(),
513        };
514        let variant_name = variant.name();
515        let variant_index = def.iter().position(|v| v.name() == variant_name).unwrap();
516        assert!(variant_index <= u32::MAX as usize);
517        if values.len() == 1 {
518            *self = Self::End(serializer.serialize_newtype_variant(
519                name,
520                variant_index as _,
521                variant_name,
522                &Serializable(values[0]),
523            ));
524            return;
525        }
526        let mut ser = match serializer.serialize_tuple_variant(
527            name,
528            variant_index as _,
529            variant_name,
530            values.len(),
531        ) {
532            Ok(ser) => ser,
533            Err(e) => {
534                *self = Self::End(Err(e));
535                return;
536            }
537        };
538        for v in values {
539            if let Err(e) = ser.serialize_field(&Serializable(v)) {
540                *self = Self::End(Err(e));
541                return;
542            }
543        }
544        *self = Self::End(ser.end());
545    }
546
547    fn visit_entry(&mut self, _: Value<'_>, _: Value<'_>) {
548        if !matches!(self, Self::End(Err(..))) {
549            *self = Self::End(Err(S::Error::custom("visit_entry in enum")));
550        }
551    }
552
553    fn visit_value(&mut self, _: Value<'_>) {
554        if !matches!(self, Self::End(Err(..))) {
555            *self = Self::End(Err(S::Error::custom("visit_value in enum")));
556        }
557    }
558}
559
560enum VisitStaticTuple<S: Serializer> {
561    Start(S::SerializeTuple),
562    End(Result<S::Ok, S::Error>),
563    Tmp,
564}
565
566impl<S: Serializer> Visit for VisitStaticTuple<S> {
567    fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
568        let mut ser = match mem::replace(self, Self::Tmp) {
569            Self::Start(ser) => ser,
570            mut res @ Self::End(..) => {
571                if matches!(res, Self::End(Ok(..))) {
572                    res = Self::End(Err(S::Error::custom(
573                        "visit_unnamed_fields called multiple times in static tuple",
574                    )));
575                }
576                *self = res;
577                return;
578            }
579            _ => unreachable!(),
580        };
581        for v in values {
582            if let Err(e) = ser.serialize_element(&Serializable(v)) {
583                *self = Self::End(Err(e));
584                return;
585            }
586        }
587        *self = Self::End(ser.end());
588    }
589
590    fn visit_named_fields(&mut self, _: &NamedValues<'_>) {
591        if !matches!(self, Self::End(Err(..))) {
592            *self = Self::End(Err(S::Error::custom("visit_named_fields in tuple")));
593        }
594    }
595
596    fn visit_entry(&mut self, _: Value<'_>, _: Value<'_>) {
597        if !matches!(self, Self::End(Err(..))) {
598            *self = Self::End(Err(S::Error::custom("visit_entry in tuple")));
599        }
600    }
601
602    fn visit_value(&mut self, _: Value<'_>) {
603        if !matches!(self, Self::End(Err(..))) {
604            *self = Self::End(Err(S::Error::custom("visit_value in tuple")));
605        }
606    }
607}
608
609// Dynamic struct, variant of dynamic enum, and dynamic tuple will be serialized as map or sequence.
610enum VisitDynamic<'a, S: Serializer> {
611    // `Structable` or `Enumerable` with named fields.
612    // Serialized as map.
613    NamedFields(&'a mut S::SerializeMap),
614    // `Structable` or `Enumerable` with unnamed fields, or `Tuplable`.
615    // Serialized as sequence.
616    UnnamedFields(&'a mut S::SerializeSeq),
617    Error(S::Error),
618}
619
620impl<S: Serializer> Visit for VisitDynamic<'_, S> {
621    fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
622        let ser = match self {
623            Self::NamedFields(ser) => ser,
624            Self::Error(..) => return,
625            Self::UnnamedFields(..) => {
626                *self = Self::Error(S::Error::custom(
627                    "visit_named_fields in unnamed dynamic struct/variant",
628                ));
629                return;
630            }
631        };
632        for (f, v) in named_values {
633            if let Err(e) = ser.serialize_entry(f.name(), &Serializable(v)) {
634                *self = Self::Error(e);
635                return;
636            }
637        }
638    }
639
640    fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
641        let ser = match self {
642            Self::UnnamedFields(ser) => ser,
643            Self::Error(..) => return,
644            Self::NamedFields(..) => {
645                *self = Self::Error(S::Error::custom(
646                    "visit_unnamed_fields in named dynamic struct/variant",
647                ));
648                return;
649            }
650        };
651        for v in values {
652            if let Err(e) = ser.serialize_element(&Serializable(v)) {
653                *self = Self::Error(e);
654                return;
655            }
656        }
657    }
658
659    fn visit_entry(&mut self, _: Value<'_>, _: Value<'_>) {
660        if !matches!(self, Self::Error(..)) {
661            *self = Self::Error(S::Error::custom("visit_entry in dynamic struct/variant"));
662        }
663    }
664
665    fn visit_value(&mut self, _: Value<'_>) {
666        if !matches!(self, Self::Error(..)) {
667            *self = Self::Error(S::Error::custom("visit_value in dynamic struct/variant"));
668        }
669    }
670}
671
672#[cfg(feature = "std")]
673struct SerializeError<'a>(&'a dyn std::error::Error);
674
675#[cfg(feature = "std")]
676impl Serialize for SerializeError<'_> {
677    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
678        struct CollectStr<'a>(&'a dyn std::error::Error);
679        impl Serialize for CollectStr<'_> {
680            fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
681                serializer.collect_str(&self.0)
682            }
683        }
684        let mut s = serializer.serialize_struct("Error", 2)?;
685        s.serialize_field("message", &CollectStr(self.0))?;
686        s.serialize_field("source", &self.0.source().map(SerializeError))?;
687        s.end()
688    }
689}