deser_core/ser/stream.rs
1use crate::error::Error;
2use crate::ser::{SerializeDriver, Serializer};
3
4/// The result of [`StreamSerializer::drive_partial`].
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum Written {
7 /// The value is complete, the output holds the rest of it.
8 Done,
9 /// The value is not complete.
10 ///
11 /// The output holds a part of it which the caller takes (and clears)
12 /// before it calls [`drive_partial`](StreamSerializer::drive_partial)
13 /// again with the same driver to continue.
14 Partial,
15}
16
17/// A [`Serializer`] that writes bytes which can be taken while values are
18/// serialized.
19///
20/// This is implemented by the serializers of the data formats (for
21/// instance `deser_json::Serializer`). They hold the state of a stream of
22/// values (for instance how many values were written, or the names of the
23/// columns of a CSV file) and write everything that separates the values
24/// of a stream, like the line breaks of JSON Lines or the markers between
25/// YAML documents.
26///
27/// The bytes serialized so far are in [`output`](Self::output), whoever
28/// writes them to a stream clears them with
29/// [`clear_output`](Self::clear_output) afterwards. This makes stream
30/// serializers usable without IO (sans-io): the writers of `deser::io`
31/// and of other IO adapters (like `deser-tokio`) only move the output to
32/// their stream.
33///
34/// ```
35/// use deser::ser::{SerializeDriver, Serializer, StreamSerializer};
36/// use deser::{Atom, Error, Event};
37///
38/// /// A format with a number per line.
39/// #[derive(Default)]
40/// struct Lines(Vec<u8>);
41///
42/// impl Serializer for Lines {
43/// fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
44/// driver.drive(|event, _| {
45/// if let Event::Atom(Atom::U64(value)) = event {
46/// self.0.extend_from_slice(format!("{value}\n").as_bytes());
47/// }
48/// Ok(())
49/// })
50/// }
51/// }
52///
53/// impl StreamSerializer for Lines {
54/// fn output(&self) -> &[u8] {
55/// &self.0
56/// }
57///
58/// fn clear_output(&mut self) {
59/// self.0.clear();
60/// }
61/// }
62///
63/// let mut lines = Lines::default();
64/// lines.serialize(&1u64).unwrap();
65/// lines.serialize(&2u64).unwrap();
66/// // the output would be written to a stream here
67/// assert_eq!(lines.output(), b"1\n2\n");
68/// lines.clear_output();
69/// ```
70///
71/// # Serializing in Parts
72///
73/// Formats which can write the output of a value before the value is
74/// complete additionally implement [`drive_partial`](Self::drive_partial).
75/// Writers use it to write large values in parts, so the memory used does
76/// not depend on the size of the values. While a value is written in
77/// parts, [`in_progress`](Self::in_progress) is `true`.
78pub trait StreamSerializer: Serializer {
79 /// Returns the bytes serialized so far which were not cleared yet.
80 ///
81 /// The output only holds final bytes: output that can still change
82 /// (for instance the header of a container whose length is not known
83 /// yet) is kept by the serializer until it's final.
84 fn output(&self) -> &[u8];
85
86 /// Discards the bytes returned by [`output`](Self::output), for
87 /// instance because they were written.
88 fn clear_output(&mut self);
89
90 /// Returns `true` if the serializer implements
91 /// [`drive_partial`](Self::drive_partial).
92 ///
93 /// This can depend on the configuration.
94 fn supports_partial(&self) -> bool {
95 false
96 }
97
98 /// Serializes a value, or a part of it, and appends its bytes to the
99 /// output.
100 ///
101 /// This works like [`drive`](Serializer::drive) but the serializer can
102 /// stop once the output holds at least `limit` bytes (it can hold
103 /// more) and return [`Written::Partial`]. The caller then takes the
104 /// output, clears it and calls again with the same driver until the
105 /// value is complete ([`Written::Done`]). In between
106 /// [`in_progress`](Self::in_progress) is `true` and no other value can
107 /// be serialized. With a limit of `usize::MAX` the value is always
108 /// completed in a single call, which allows serializers to use faster
109 /// paths (see [`SerializeDriver::drive_until`]).
110 ///
111 /// If this fails in the first call for a value, the output and the
112 /// state are as before the call (like with [`drive`](Serializer::drive))
113 /// and the next value can be serialized. If it fails after a part was
114 /// returned, the bytes of the part cannot be taken back: the value
115 /// stays in progress and the stream cannot continue.
116 ///
117 /// The provided implementation serializes the whole value with
118 /// [`drive`](Serializer::drive).
119 fn drive_partial(
120 &mut self,
121 driver: &mut SerializeDriver<'_>,
122 limit: usize,
123 ) -> Result<Written, Error> {
124 let _ = limit;
125 self.drive(driver)?;
126 Ok(Written::Done)
127 }
128
129 /// Returns `true` if a value is partially serialized.
130 ///
131 /// This is the case after [`drive_partial`](Self::drive_partial)
132 /// returned [`Written::Partial`] until it returns [`Written::Done`].
133 /// If the value is abandoned (because it failed, or because the caller
134 /// gave up on it, for instance when a write failed), this stays `true`:
135 /// the output of the stream holds an incomplete value, so the stream
136 /// cannot continue. Serializing another value fails with
137 /// [`Error::in_progress`].
138 fn in_progress(&self) -> bool {
139 false
140 }
141}
142
143impl<S: StreamSerializer + ?Sized> StreamSerializer for &mut S {
144 fn output(&self) -> &[u8] {
145 (**self).output()
146 }
147
148 fn clear_output(&mut self) {
149 (**self).clear_output()
150 }
151
152 fn supports_partial(&self) -> bool {
153 (**self).supports_partial()
154 }
155
156 fn drive_partial(
157 &mut self,
158 driver: &mut SerializeDriver<'_>,
159 limit: usize,
160 ) -> Result<Written, Error> {
161 (**self).drive_partial(driver, limit)
162 }
163
164 fn in_progress(&self) -> bool {
165 (**self).in_progress()
166 }
167}