Skip to main content

deser_msgpack/
stream.rs

1//! Reading MessagePack streams.
2#[cfg(feature = "io")]
3use std::io::Read;
4
5use alloc::vec::Vec;
6#[cfg(feature = "io")]
7use deser_core::de::DeserializeOwned;
8use deser_core::de::{self, DeserializeDriver, Frame, Progress};
9use deser_core::{Error, ErrorKind, State};
10
11use crate::de::{Deserializer, DeserializerConfig};
12use crate::head::{Head, HeadError, decode_head};
13use crate::parser::{Copying, Discard, Parser, Progress as ParseProgress};
14
15/// The state of a MessagePack stream that is read.
16#[derive(Default)]
17struct StreamState {
18    // the position up to which the item was scanned
19    pos: usize,
20    // the number of items the open containers still need
21    stack: Vec<u64>,
22    // an item was not well-formed
23    failed: bool,
24    // parses items while their input arrives (see `drive_partial`)
25    parser: Parser,
26    // the driver of the current item was set up
27    started: bool,
28    // the rest of an item that failed in a sink is skipped from the
29    // position in the input
30    skipping: Option<usize>,
31    // parsing failed, the stream cannot be continued
32    partial_failed: bool,
33    // the stream ended within an item
34    ended: bool,
35}
36
37impl core::fmt::Debug for StreamState {
38    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
39        f.debug_struct("StreamState").finish_non_exhaustive()
40    }
41}
42
43/// The result of scanning an item.
44enum Scan {
45    /// The item ends at the given offset.
46    Complete(usize),
47    /// More input is needed.
48    Incomplete,
49    /// The item is not well-formed at the given offset.
50    Malformed(usize),
51}
52
53impl StreamState {
54    /// Scans the item from the current position.
55    fn scan(&mut self, input: &[u8]) -> Scan {
56        loop {
57            let head_start = self.pos;
58            let (head, len) = match decode_head(&input[head_start..]) {
59                Ok(rv) => rv,
60                Err(HeadError::Incomplete) => return Scan::Incomplete,
61                Err(HeadError::Reserved) => return Scan::Malformed(head_start),
62            };
63            let mut pos = head_start + len;
64            let items = match head {
65                Head::Str(len) | Head::Bin(len) | Head::Ext(_, len) => {
66                    match pos.checked_add(len as usize) {
67                        Some(end) if end <= input.len() => pos = end,
68                        _ => return Scan::Incomplete,
69                    }
70                    0
71                }
72                Head::Array(len) => u64::from(len),
73                Head::Map(len) => u64::from(len) * 2,
74                _ => 0,
75            };
76            self.pos = pos;
77
78            if items > 0 {
79                self.stack.push(items);
80                continue;
81            }
82            // account for the item in the containers it completes
83            loop {
84                match self.stack.last_mut() {
85                    None => return Scan::Complete(pos),
86                    Some(remaining) => {
87                        *remaining -= 1;
88                        if *remaining > 0 {
89                            break;
90                        }
91                        self.stack.pop();
92                    }
93                }
94            }
95        }
96    }
97}
98
99/// Reads a stream of MessagePack items into items (see [`deser::stream`](deser_core::stream)).
100///
101/// The items of the stream follow each other without separators.  An item
102/// is complete once its last byte was read.  Reading continues after items that fail to deserialize,
103/// items that are not well-formed end the stream.
104///
105/// Items which do not borrow are deserialized while their input arrives
106/// (see
107/// [`StreamDeserializer::drive_partial`](de::StreamDeserializer::drive_partial))
108/// so only incomplete atoms (like strings) are buffered.
109///
110/// ```
111/// # #[cfg(feature = "io")] {
112/// use deser_msgpack::DeserializerConfig;
113///
114/// let mut reader =
115///     DeserializerConfig::new().reader(&[0x01, 0xa2, b'h', b'i'][..]);
116/// assert_eq!(reader.read::<u32>().unwrap(), Some(1));
117/// assert_eq!(reader.read::<String>().unwrap().as_deref(), Some("hi"));
118/// assert_eq!(reader.read::<u32>().unwrap(), None);
119/// # }
120/// ```
121///
122/// Items are parsed like with a [`Deserializer`], so they can borrow from
123/// the stream's buffer (see
124/// [`InputBuffer::deserialize`](deser_core::stream::InputBuffer::deserialize)).
125#[derive(Debug)]
126pub struct StreamDeserializer {
127    config: DeserializerConfig,
128    state: StreamState,
129}
130
131impl Default for StreamDeserializer {
132    fn default() -> StreamDeserializer {
133        StreamDeserializer::new()
134    }
135}
136
137impl StreamDeserializer {
138    /// Creates a stream deserializer.
139    pub fn new() -> StreamDeserializer {
140        StreamDeserializer::with_config(DeserializerConfig::new())
141    }
142
143    /// Creates a stream deserializer with the given configuration.
144    pub fn with_config(config: DeserializerConfig) -> StreamDeserializer {
145        StreamDeserializer {
146            config,
147            state: StreamState::default(),
148        }
149    }
150
151    /// Returns the configuration.
152    pub fn config(&self) -> &DeserializerConfig {
153        &self.config
154    }
155
156    /// Skips the rest of an item that failed in a sink.
157    ///
158    /// Returns where the next item starts, or the progress if there is no
159    /// item (yet).
160    fn skip_to_item(
161        &mut self,
162        input: &[u8],
163        offset: usize,
164        eof: bool,
165    ) -> Result<Result<usize, Progress>, Error> {
166        let state = &mut self.state;
167        if state.ended {
168            return Ok(Err(Progress::End));
169        }
170        if state.partial_failed {
171            return Err(Error::new(
172                ErrorKind::InvalidState,
173                "cannot continue after an error",
174            ));
175        }
176
177        // skip the rest of an item that failed in a sink
178        let mut pos = 0;
179        if let Some(skip) = state.skipping {
180            let mut discard = Discard(State::new());
181            match state.parser.parse(input, skip, eof, offset, &mut discard) {
182                Ok(ParseProgress::Done(end)) => {
183                    state.skipping = None;
184                    pos = end;
185                }
186                Ok(ParseProgress::NeedMore(consumed)) => {
187                    state.skipping = Some(0);
188                    return Ok(Err(Progress::NeedMore { consumed }));
189                }
190                Err(err) => {
191                    state.skipping = None;
192                    return Err(fail(state, err, eof));
193                }
194            }
195        }
196
197        if !state.started && pos == input.len() {
198            return Ok(Err(if eof {
199                Progress::End
200            } else {
201                Progress::NeedMore { consumed: pos }
202            }));
203        }
204        Ok(Ok(pos))
205    }
206}
207
208impl de::StreamDeserializer for StreamDeserializer {
209    fn context(&self) -> deser_core::Context {
210        self.config.context().clone()
211    }
212
213    fn frame(&mut self, input: &[u8], eof: bool) -> Result<Frame, Error> {
214        let state = &mut self.state;
215        if state.failed {
216            return Err(Error::new(
217                ErrorKind::InvalidState,
218                "cannot continue after an item that is not well-formed",
219            ));
220        }
221        if input.is_empty() && eof {
222            return Ok(Frame::End);
223        }
224        let end = match state.scan(input) {
225            Scan::Complete(end) => end,
226            Scan::Incomplete if !eof => return Ok(Frame::Incomplete { consumed: 0 }),
227            // the parser reports the error
228            Scan::Incomplete => input.len(),
229            Scan::Malformed(offset) => {
230                state.failed = true;
231                offset + 1
232            }
233        };
234        state.pos = 0;
235        state.stack.clear();
236        Ok(Frame::Value {
237            start: 0,
238            end,
239            consumed: end,
240        })
241    }
242
243    fn drive_frame<'de>(
244        &mut self,
245        frame: &'de [u8],
246        driver: &mut DeserializeDriver<'_, 'de>,
247    ) -> Result<(), Error> {
248        let mut de = Deserializer::from_slice_with_config(frame, self.config.without_context());
249        de.drive(driver)?;
250        de.end()
251    }
252
253    fn supports_partial(&self) -> bool {
254        true
255    }
256
257    fn drive_partial(
258        &mut self,
259        input: &[u8],
260        offset: usize,
261        eof: bool,
262        driver: &mut DeserializeDriver<'_, '_>,
263    ) -> Result<Progress, Error> {
264        let pos = match self.skip_to_item(input, offset, eof)? {
265            Ok(pos) => pos,
266            Err(progress) => return Ok(progress),
267        };
268        let state = &mut self.state;
269        state.started = true;
270        match state
271            .parser
272            .parse(input, pos, eof, offset, &mut Copying(driver))
273        {
274            Ok(ParseProgress::Done(end)) => {
275                state.started = false;
276                Ok(Progress::Done { consumed: end })
277            }
278            Ok(ParseProgress::NeedMore(consumed)) => Ok(Progress::NeedMore { consumed }),
279            Err(err) => {
280                state.started = false;
281                match state.parser.recoverable() {
282                    // a sink failed, the next call continues after the
283                    // item.  The input is not consumed on errors.
284                    Some(resume) => {
285                        state.skipping = Some(resume);
286                        Err(err)
287                    }
288                    None => Err(fail(state, err, eof)),
289                }
290            }
291        }
292    }
293
294    fn peek(&mut self, input: &[u8], eof: bool) -> Result<Option<Progress>, Error> {
295        Ok(Some(match self.skip_to_item(input, 0, eof)? {
296            Ok(pos) => Progress::Done { consumed: pos },
297            Err(progress) => progress,
298        }))
299    }
300}
301
302#[cfg(feature = "io")]
303impl DeserializerConfig {
304    /// Creates a reader of a stream of items (see
305    /// [`deser::io::Reader`](deser_core::io::Reader)).
306    ///
307    /// See [`StreamDeserializer`] for how the stream is read.
308    pub fn reader<R: Read>(&self, reader: R) -> deser_core::io::Reader<R, StreamDeserializer> {
309        deser_core::io::Reader::new(reader, StreamDeserializer::with_config(self.clone()))
310    }
311
312    /// Deserializes an item from a reader.
313    ///
314    /// See [`from_reader`].
315    pub fn from_reader<T: DeserializeOwned, R: Read>(&self, reader: R) -> Result<T, Error> {
316        deser_core::io::from_reader(reader, StreamDeserializer::with_config(self.clone()))
317    }
318}
319
320/// Deserializes an item from a reader.
321///
322/// The reader is read to the end, no data may follow the item.  The reader
323/// does not need to be buffered.  To read more than one item use [`DeserializerConfig::reader`].
324///
325/// ```
326/// let value: Vec<u32> =
327///     deser_msgpack::from_reader(&[0x92, 0x01, 0x02][..]).unwrap();
328/// assert_eq!(value, [1, 2]);
329/// ```
330#[cfg(feature = "io")]
331pub fn from_reader<T: DeserializeOwned, R: Read>(reader: R) -> Result<T, Error> {
332    DeserializerConfig::new().from_reader(reader)
333}
334
335/// Ends the stream after an error that cannot be recovered from.
336fn fail(state: &mut StreamState, err: Error, eof: bool) -> Error {
337    state.parser.reset();
338    state.partial_failed = true;
339    // after an incomplete item at the end there are no more items
340    state.ended = eof && err.kind() == ErrorKind::EndOfFile;
341    err
342}