Skip to main content

deser_core/ser/
stream.rs

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