Skip to main content

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}