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 /// Like [`seq`](Self::seq) but the emitter does not need to outlive
88 /// `'a`.
89 ///
90 /// This is for the emitters of sequences which are generic over
91 /// adapters (see [`erase_unbounded`](crate::ser::handle::erase_unbounded)).
92 ///
93 /// # Safety
94 ///
95 /// The parts of `E` that do not outlive `'a` must be adapters that are
96 /// only used for their functions, `E` holds no values of them.
97 #[inline(always)]
98 pub(crate) unsafe fn seq_unbounded<E: SeqEmitter>(emitter: E, state: &mut State) -> Emit<'a> {
99 // like every type parameter, `E` outlives this function
100 let emitter = unsize(Boxed::arena(emitter, state), |x| {
101 x as *mut (dyn SeqEmitter + '_)
102 });
103 // SAFETY: guaranteed by the caller
104 Emit::Seq(unsafe {
105 core::mem::transmute::<Boxed<dyn SeqEmitter + '_>, Boxed<dyn SeqEmitter + 'a>>(emitter)
106 })
107 }
108
109 /// Like [`map`](Self::map) but the emitter does not need to outlive
110 /// `'a`.
111 ///
112 /// # Safety
113 ///
114 /// See [`seq_unbounded`](Self::seq_unbounded).
115 #[inline(always)]
116 pub(crate) unsafe fn map_unbounded<E: MapEmitter>(emitter: E, state: &mut State) -> Emit<'a> {
117 // like every type parameter, `E` outlives this function
118 let emitter = unsize(Boxed::arena(emitter, state), |x| {
119 x as *mut (dyn MapEmitter + '_)
120 });
121 // SAFETY: guaranteed by the caller
122 Emit::Map(unsafe {
123 core::mem::transmute::<Boxed<dyn MapEmitter + '_>, Boxed<dyn MapEmitter + 'a>>(emitter)
124 })
125 }
126}
127
128impl<'a> From<Atom<'a>> for Emit<'a> {
129 fn from(atom: Atom<'a>) -> Self {
130 Emit::Atom(atom)
131 }
132}
133
134macro_rules! impl_from {
135 ($ty:ty, $atom:ident) => {
136 impl From<$ty> for Emit<'static> {
137 fn from(value: $ty) -> Self {
138 Emit::Atom(Atom::$atom(value as _))
139 }
140 }
141 };
142}
143
144impl_from!(u64, U64);
145impl_from!(i64, I64);
146impl_from!(usize, U64);
147impl_from!(isize, I64);
148impl_from!(bool, Bool);
149impl_from!(char, Char);
150
151impl From<f64> for Emit<'static> {
152 fn from(value: f64) -> Self {
153 Emit::Atom(Atom::F64(value))
154 }
155}
156
157impl From<f32> for Emit<'static> {
158 fn from(value: f32) -> Self {
159 Emit::Atom(Atom::F32(value))
160 }
161}
162
163impl From<()> for Emit<'static> {
164 fn from(_: ()) -> Emit<'static> {
165 Emit::Atom(Atom::Null)
166 }
167}
168
169impl<'a> From<&'a str> for Emit<'a> {
170 fn from(value: &'a str) -> Emit<'a> {
171 Emit::Atom(Atom::Str(Text::borrowed(value)))
172 }
173}
174
175impl<'a> From<&'a [u8]> for Emit<'a> {
176 fn from(value: &'a [u8]) -> Emit<'a> {
177 Emit::Atom(Atom::Bytes(Bytes::borrowed(value)))
178 }
179}
180
181impl From<String> for Emit<'static> {
182 fn from(value: String) -> Emit<'static> {
183 Emit::Atom(Atom::Str(Text::owned(value)))
184 }
185}
186
187#[cfg(target_pointer_width = "64")]
188const _: () = assert!(core::mem::size_of::<Emit<'static>>() == 32);
189#[cfg(target_pointer_width = "32")]
190const _: () = assert!(core::mem::size_of::<Emit<'static>>() == 24);