Skip to main content

deser_php/
stream.rs

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