deser_core/ser/emit.rs
1use crate::event::{Atom, Bytes};
2use crate::ser::boxed::unsize;
3use crate::ser::{Boxed, MapEmitter, SeqEmitter, SerializeHandle, StructEmitter};
4use crate::{State, Text};
5use alloc::string::String;
6
7/// Describes how a value is emitted, returned by
8/// [`Serialize::serialize`](crate::ser::Serialize::serialize).
9///
10/// A value is either emitted as an atom, by a stateful emitter or by
11/// forwarding to another value. For instance `Emit::Atom(Atom::Bool(true))`
12/// is emitted to a serializer directly. On the other hand an `Emit::Map`
13/// contains a stateful emitter that keeps yielding values until it's done
14/// walking over the map.
15///
16/// The emitters are typically allocated in the arena of the state
17/// with [`Emit::seq`], [`Emit::map`] and [`Emit::structure`] (see
18/// [`Boxed`]). They are the serialization equivalent of the
19/// [`Sink`](crate::de::Sink)s of deserialization: they hold the state of a
20/// value that is being serialized.
21pub enum Emit<'a> {
22 Atom(Atom<'a>),
23 Struct(Boxed<dyn StructEmitter + 'a>),
24 Map(Boxed<dyn MapEmitter + 'a>),
25 Seq(Boxed<dyn SeqEmitter + 'a>),
26 /// Serializes another value in place of this one.
27 ///
28 /// The driver serializes the value in the handle as if it was produced
29 /// instead of the value that returned the `Emit`. This is useful to
30 /// serialize a value by converting it into another value first as the
31 /// handle can own that value:
32 ///
33 /// ```
34 /// use deser::ser::{Emit, Serialize, SerializeHandle};
35 /// use deser::{Error, State};
36 ///
37 /// struct Point(u32, u32);
38 ///
39 /// impl Serialize for Point {
40 /// fn serialize<'a>(value: &'a Self, state: &mut State) -> Result<Emit<'a>, Error> {
41 /// // serialize as a vector
42 /// Ok(Emit::Forward(SerializeHandle::arena(
43 /// vec![value.0, value.1],
44 /// state,
45 /// )))
46 /// }
47 /// }
48 /// ```
49 ///
50 /// The [`container_shape`](crate::ser::Serialize::container_shape) of the
51 /// value that returned the `Emit` is not used, the forwarded value provides
52 /// its own.
53 /// [`finish`](crate::ser::Serialize::finish) is invoked on the forwarded
54 /// value first and then on the value that returned the `Emit`.
55 ///
56 /// Values that forward cannot be flattened into structs.
57 Forward(SerializeHandle<'a>),
58}
59
60impl<'a> Emit<'a> {
61 /// Emits a sequence with an emitter in the arena of the
62 /// serialization.
63 #[inline(always)]
64 pub fn seq<E: SeqEmitter + 'a>(emitter: E, state: &mut State) -> Emit<'a> {
65 Emit::Seq(unsize(Boxed::arena(emitter, state), |x| {
66 x as *mut (dyn SeqEmitter + 'a)
67 }))
68 }
69
70 /// Emits a map with an emitter in the arena of the state.
71 #[inline(always)]
72 pub fn map<E: MapEmitter + 'a>(emitter: E, state: &mut State) -> Emit<'a> {
73 Emit::Map(unsize(Boxed::arena(emitter, state), |x| {
74 x as *mut (dyn MapEmitter + 'a)
75 }))
76 }
77
78 /// Emits a struct with an emitter in the arena of the
79 /// serialization.
80 #[inline(always)]
81 pub fn structure<E: StructEmitter + 'a>(emitter: E, state: &mut State) -> Emit<'a> {
82 Emit::Struct(unsize(Boxed::arena(emitter, state), |x| {
83 x as *mut (dyn StructEmitter + 'a)
84 }))
85 }
86}
87
88impl<'a> From<Atom<'a>> for Emit<'a> {
89 fn from(atom: Atom<'a>) -> Self {
90 Emit::Atom(atom)
91 }
92}
93
94macro_rules! impl_from {
95 ($ty:ty, $atom:ident) => {
96 impl From<$ty> for Emit<'static> {
97 fn from(value: $ty) -> Self {
98 Emit::Atom(Atom::$atom(value as _))
99 }
100 }
101 };
102}
103
104impl_from!(u64, U64);
105impl_from!(i64, I64);
106impl_from!(usize, U64);
107impl_from!(isize, I64);
108impl_from!(bool, Bool);
109impl_from!(char, Char);
110
111impl From<f64> for Emit<'static> {
112 fn from(value: f64) -> Self {
113 Emit::Atom(Atom::F64(value))
114 }
115}
116
117impl From<f32> for Emit<'static> {
118 fn from(value: f32) -> Self {
119 Emit::Atom(Atom::F32(value))
120 }
121}
122
123impl From<()> for Emit<'static> {
124 fn from(_: ()) -> Emit<'static> {
125 Emit::Atom(Atom::Null)
126 }
127}
128
129impl<'a> From<&'a str> for Emit<'a> {
130 fn from(value: &'a str) -> Emit<'a> {
131 Emit::Atom(Atom::Str(Text::borrowed(value)))
132 }
133}
134
135impl<'a> From<&'a [u8]> for Emit<'a> {
136 fn from(value: &'a [u8]) -> Emit<'a> {
137 Emit::Atom(Atom::Bytes(Bytes::borrowed(value)))
138 }
139}
140
141impl From<String> for Emit<'static> {
142 fn from(value: String) -> Emit<'static> {
143 Emit::Atom(Atom::Str(Text::owned(value)))
144 }
145}
146
147#[cfg(target_pointer_width = "64")]
148const _: () = assert!(core::mem::size_of::<Emit<'static>>() == 32);
149#[cfg(target_pointer_width = "32")]
150const _: () = assert!(core::mem::size_of::<Emit<'static>>() == 24);