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 `feed`)
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    feed_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::feed`](de::StreamDeserializer::feed)) so only incomplete atoms (like strings) are
108/// 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: config.clone(),
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.feed_failed {
171            return Err(Error::new(
172                ErrorKind::Unexpected,
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 frame(&mut self, input: &[u8], eof: bool) -> Result<Frame, Error> {
210        let state = &mut self.state;
211        if state.failed {
212            return Err(Error::new(
213                ErrorKind::Unexpected,
214                "cannot continue after an item that is not well-formed",
215            ));
216        }
217        if input.is_empty() && eof {
218            return Ok(Frame::End);
219        }
220        let end = match state.scan(input) {
221            Scan::Complete(end) => end,
222            Scan::Incomplete if !eof => return Ok(Frame::Incomplete { consumed: 0 }),
223            // the parser reports the error
224            Scan::Incomplete => input.len(),
225            Scan::Malformed(offset) => {
226                state.failed = true;
227                offset + 1
228            }
229        };
230        state.pos = 0;
231        state.stack.clear();
232        Ok(Frame::Value {
233            start: 0,
234            end,
235            consumed: end,
236        })
237    }
238
239    fn drive_frame<'de>(
240        &mut self,
241        frame: &'de [u8],
242        driver: &mut DeserializeDriver<'_, 'de>,
243    ) -> Result<(), Error> {
244        let mut de = Deserializer::from_slice_with_config(frame, &self.config);
245        de.drive(driver)?;
246        de.end()
247    }
248
249    fn supports_feed(&self) -> bool {
250        true
251    }
252
253    fn feed(
254        &mut self,
255        input: &[u8],
256        offset: usize,
257        eof: bool,
258        driver: &mut DeserializeDriver<'_, '_>,
259    ) -> Result<Progress, Error> {
260        let pos = match self.skip_to_item(input, offset, eof)? {
261            Ok(pos) => pos,
262            Err(progress) => return Ok(progress),
263        };
264        let state = &mut self.state;
265        state.started = true;
266        match state
267            .parser
268            .parse(input, pos, eof, offset, &mut Copying(driver))
269        {
270            Ok(ParseProgress::Done(end)) => {
271                state.started = false;
272                Ok(Progress::Done { consumed: end })
273            }
274            Ok(ParseProgress::NeedMore(consumed)) => Ok(Progress::NeedMore { consumed }),
275            Err(err) => {
276                state.started = false;
277                match state.parser.recoverable() {
278                    // a sink failed, the next call continues after the
279                    // item.  The input is not consumed on errors.
280                    Some(resume) => {
281                        state.skipping = Some(resume);
282                        Err(err)
283                    }
284                    None => Err(fail(state, err, eof)),
285                }
286            }
287        }
288    }
289
290    fn peek(&mut self, input: &[u8], eof: bool) -> Result<Option<Progress>, Error> {
291        Ok(Some(match self.skip_to_item(input, 0, eof)? {
292            Ok(pos) => Progress::Done { consumed: pos },
293            Err(progress) => progress,
294        }))
295    }
296}
297
298#[cfg(feature = "io")]
299impl DeserializerConfig {
300    /// Creates a reader of a stream of items (see
301    /// [`deser::io::Reader`](deser_core::io::Reader)).
302    ///
303    /// See [`StreamDeserializer`] for how the stream is read.
304    pub fn reader<R: Read>(&self, reader: R) -> deser_core::io::Reader<R, StreamDeserializer> {
305        deser_core::io::Reader::new(reader, StreamDeserializer::with_config(self))
306    }
307
308    /// Deserializes an item from a reader.
309    ///
310    /// See [`from_reader`](crate::from_reader).
311    pub fn from_reader<T: DeserializeOwned, R: Read>(&self, reader: R) -> Result<T, Error> {
312        deser_core::io::from_reader(reader, StreamDeserializer::with_config(self))
313    }
314}
315
316/// Deserializes an item from a reader.
317///
318/// The reader is read to the end, no data may follow the item.  The reader
319/// does not need to be buffered.  To read more than one item use [`DeserializerConfig::reader`].
320///
321/// ```
322/// let value: Vec<u32> =
323///     deser_msgpack::from_reader(&[0x92, 0x01, 0x02][..]).unwrap();
324/// assert_eq!(value, [1, 2]);
325/// ```
326#[cfg(feature = "io")]
327pub fn from_reader<T: DeserializeOwned, R: Read>(reader: R) -> Result<T, Error> {
328    DeserializerConfig::new().from_reader(reader)
329}
330
331/// Ends the stream after an error that cannot be recovered from.
332fn fail(state: &mut StreamState, err: Error, eof: bool) -> Error {
333    state.parser.reset();
334    state.feed_failed = true;
335    // after an incomplete item at the end there are no more items
336    state.ended = eof && err.kind() == ErrorKind::EndOfFile;
337    err
338}