Skip to main content

deser_pickle/
stream.rs

1//! Reading values from streams.
2#[cfg(feature = "io")]
3use std::io::Read;
4
5#[cfg(feature = "io")]
6use deser_core::de::DeserializeOwned;
7use deser_core::de::{self, DeserializeDriver, Frame};
8use deser_core::{Error, ErrorKind};
9
10use crate::de::{Deserializer, DeserializerConfig};
11use crate::vm;
12
13/// Reads pickles from a stream (see [`deser::stream`](deser_core::stream)).
14///
15/// A stream holds pickles one after another (what `pickle.dump` writes to
16/// a file when it's called more than once).  A pickle is read up to its
17/// `STOP` opcode before it's run, the rest of the stream is not waited for.
18///
19/// ```
20/// # #[cfg(feature = "io")] {
21/// use deser_pickle::DeserializerConfig;
22///
23/// let mut reader = DeserializerConfig::new().reader(&b"K\x01.\x8c\x03two."[..]);
24/// assert_eq!(reader.read::<u32>().unwrap(), Some(1));
25/// assert_eq!(reader.read::<String>().unwrap().as_deref(), Some("two"));
26/// assert_eq!(reader.read::<String>().unwrap(), None);
27/// # }
28/// ```
29#[derive(Debug, Default)]
30pub struct StreamDeserializer {
31    config: DeserializerConfig,
32}
33
34impl StreamDeserializer {
35    /// Creates a stream deserializer.
36    pub fn new() -> StreamDeserializer {
37        StreamDeserializer::with_config(DeserializerConfig::new())
38    }
39
40    /// Creates a stream deserializer with the given configuration.
41    pub fn with_config(config: DeserializerConfig) -> StreamDeserializer {
42        StreamDeserializer { config }
43    }
44
45    /// Returns the configuration.
46    pub fn config(&self) -> &DeserializerConfig {
47        &self.config
48    }
49}
50
51impl de::StreamDeserializer for StreamDeserializer {
52    fn context(&self) -> deser_core::Context {
53        self.config.context().clone()
54    }
55
56    fn frame(&mut self, input: &[u8], eof: bool) -> Result<Frame, Error> {
57        match vm::find_end(input, 0)? {
58            Some(end) => Ok(Frame::Value {
59                start: 0,
60                end,
61                consumed: end,
62            }),
63            None if !eof => Ok(Frame::Incomplete { consumed: 0 }),
64            None if input.is_empty() => Ok(Frame::End),
65            None => Err(Error::with_offset(
66                ErrorKind::EndOfFile,
67                "unexpected end of input",
68                input.len(),
69            )),
70        }
71    }
72
73    fn drive_frame<'de>(
74        &mut self,
75        frame: &'de [u8],
76        driver: &mut DeserializeDriver<'_, 'de>,
77    ) -> Result<(), Error> {
78        Deserializer::from_slice_with_config(frame, self.config.without_context()).drive(driver)
79    }
80}
81
82#[cfg(feature = "io")]
83impl DeserializerConfig {
84    /// Creates a reader of values (see
85    /// [`deser::io::Reader`](deser_core::io::Reader)).
86    ///
87    /// See [`StreamDeserializer`].
88    pub fn reader<R: Read>(&self, reader: R) -> deser_core::io::Reader<R, StreamDeserializer> {
89        deser_core::io::Reader::new(reader, StreamDeserializer::with_config(self.clone()))
90    }
91
92    /// Deserializes a value from a reader.
93    ///
94    /// See [`from_reader`].
95    pub fn from_reader<T: DeserializeOwned, R: Read>(&self, reader: R) -> Result<T, Error> {
96        deser_core::io::from_reader(reader, StreamDeserializer::with_config(self.clone()))
97    }
98}
99
100/// Deserializes a pickle from a reader.
101///
102/// The reader does not need to be buffered.  The stream must contain
103/// exactly one pickle.
104///
105/// ```
106/// let value: Vec<u32> = deser_pickle::from_reader(&b"\x80\x04](K\x01K\x02e."[..]).unwrap();
107/// assert_eq!(value, [1, 2]);
108/// ```
109#[cfg(feature = "io")]
110pub fn from_reader<T: DeserializeOwned, R: Read>(reader: R) -> Result<T, Error> {
111    DeserializerConfig::new().from_reader(reader)
112}