serde_encom/des/
stream_deserializer.rs

1use super::deserializer::Deserializer;
2use super::read::Fused;
3use super::read::Read;
4use crate::error::{Error, ErrorCode, Result};
5use core::iter::FusedIterator;
6use core::marker::PhantomData;
7use serde::de;
8
9/// Iterator that deserializes a stream into multiple EnCom values.
10///
11/// A stream deserializer can be created from any EnCom deserializer using the
12/// `Deserializer::into_iter` method.
13///
14/// The data can consist of any EnCom value. Values need to be a self-delineating value e.g.
15/// arrays, objects, or strings, or be followed by whitespace or a self-delineating value.
16///
17/// ```
18/// use serde_encom::{Deserializer, Value};
19///
20/// fn main() {
21///     let data = "{\"k\": 3}1\"cool\"\"stuff\" 3{}  [0, 1, 2]";
22///
23///     let stream = Deserializer::from_str(data).into_iter::<Value>();
24///
25///     for value in stream {
26///         println!("{}", value.unwrap());
27///     }
28/// }
29/// ```
30pub struct StreamDeserializer<'de, R, T> {
31    pub(crate) de: Deserializer<R>,
32    pub(crate) offset: usize,
33    pub(crate) failed: bool,
34    pub(crate) output: PhantomData<T>,
35    pub(crate) lifetime: PhantomData<&'de ()>,
36}
37
38impl<'de, R, T> StreamDeserializer<'de, R, T>
39where
40    R: Read<'de>,
41    T: de::Deserialize<'de>,
42{
43    /// Create an EnCom stream deserializer from one of the possible serde_encom
44    /// input sources.
45    ///
46    /// Typically it is more convenient to use one of these methods instead:
47    ///
48    ///   - Deserializer::from_str(...).into_iter()
49    ///   - Deserializer::from_slice(...).into_iter()
50    ///   - Deserializer::from_reader(...).into_iter()
51    pub fn new(read: R) -> Self {
52        let offset = read.byte_offset();
53        StreamDeserializer {
54            de: Deserializer::new(read),
55            offset,
56            failed: false,
57            output: PhantomData,
58            lifetime: PhantomData,
59        }
60    }
61
62    /// Returns the number of bytes so far deserialized into a successful `T`.
63    ///
64    /// If a stream deserializer returns an EOF error, new data can be joined to
65    /// `old_data[stream.byte_offset()..]` to try again.
66    ///
67    /// ```
68    /// let data = b"0 1 ";
69    ///
70    /// let de = serde_encom::Deserializer::from_slice(data);
71    /// let mut stream = de.into_iter::<Vec<i32>>();
72    /// assert_eq!(0, stream.byte_offset());
73    ///
74    /// println!("{:?}", stream.next()); // [0]
75    /// assert_eq!(3, stream.byte_offset());
76    ///
77    /// println!("{:?}", stream.next()); // [1]
78    /// assert_eq!(7, stream.byte_offset());
79    ///
80    /// println!("{:?}", stream.next()); // error
81    /// assert_eq!(8, stream.byte_offset());
82    ///
83    /// // If err.is_eof(), can join the remaining data to new data and continue.
84    /// let remaining = &data[stream.byte_offset()..];
85    /// ```
86    ///
87    /// *Note:* In the future this method may be changed to return the number of
88    /// bytes so far deserialized into a successful T *or* syntactically valid
89    /// EnCom skipped over due to a type error. See [serde-rs/json#70] for an
90    /// example illustrating this.
91    ///
92    /// [serde-rs/json#70]: https://github.com/serde-rs/json/issues/70
93    pub fn byte_offset(&self) -> usize {
94        self.offset
95    }
96
97    fn peek_end_of_value(&mut self) -> Result<()> {
98        match self.de.peek()? {
99            Some(b' ' | b'\n' | b'\t' | b'\r' | b'{' | b'}' | b'[' | b']' | b':') | None => Ok(()),
100            Some(_) => {
101                let position = self.de.read.peek_position();
102                Err(Error::syntax(
103                    ErrorCode::TrailingCharacters,
104                    position.line,
105                    position.column,
106                ))
107            }
108        }
109    }
110}
111
112impl<'de, R, T> Iterator for StreamDeserializer<'de, R, T>
113where
114    R: Read<'de>,
115    T: de::Deserialize<'de>,
116{
117    type Item = Result<T>;
118
119    fn next(&mut self) -> Option<Result<T>> {
120        if R::SHOULD_EARLY_RETURN_IF_FAILED && self.failed {
121            return None;
122        }
123
124        // skip whitespaces, if any
125        // this helps with trailing whitespaces, since whitespaces between
126        // values are handled for us.
127        match self.de.parse_whitespace() {
128            Ok(None) => {
129                self.offset = self.de.read.byte_offset();
130                None
131            }
132            Ok(Some(b)) => {
133                // If the value does not have a clear way to show the end of the value
134                // (like numbers, null, true etc.) we have to look for whitespace or
135                // the beginning of a self-delineated value.
136                let self_delineated_value = match b {
137                    b'{' | b'[' => true,
138                    _ => false,
139                };
140                self.offset = self.de.read.byte_offset();
141                let result = de::Deserialize::deserialize(&mut self.de);
142
143                Some(match result {
144                    Ok(value) => {
145                        self.offset = self.de.read.byte_offset();
146                        if self_delineated_value {
147                            Ok(value)
148                        } else {
149                            self.peek_end_of_value().map(|()| value)
150                        }
151                    }
152                    Err(e) => {
153                        self.de.read.set_failed(&mut self.failed);
154                        Err(e)
155                    }
156                })
157            }
158            Err(e) => {
159                self.de.read.set_failed(&mut self.failed);
160                Some(Err(e))
161            }
162        }
163    }
164}
165
166impl<'de, R, T> FusedIterator for StreamDeserializer<'de, R, T>
167where
168    R: Read<'de> + Fused,
169    T: de::Deserialize<'de>,
170{
171}