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}