deser_pickle/de.rs
1use core::marker::PhantomData;
2
3use deser_core::Error;
4use deser_core::de::{self, Deserialize, DeserializeDriver, deserialize_value};
5
6use crate::emit::emit;
7use crate::vm::{Machine, syntax_error};
8
9/// The default of [`DeserializerConfig::set_max_shared_events`].
10const DEFAULT_MAX_SHARED_EVENTS: usize = 1 << 20;
11
12/// Configures how pickles are deserialized.
13///
14/// The configuration is independent of the input so it can be created once
15/// (even as a constant) and used for many inputs. The method
16/// [`from_slice`](Self::from_slice) works like the function of the same
17/// name.
18///
19/// ```
20/// use deser_pickle::DeserializerConfig;
21///
22/// const CONFIG: DeserializerConfig = DeserializerConfig::new();
23/// // `pickle.dumps([1, 2], 4)`
24/// let input = b"\x80\x04\x95\x09\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x02e.";
25/// assert_eq!(CONFIG.from_slice::<Vec<u32>>(input).unwrap(), [1, 2]);
26/// ```
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct DeserializerConfig {
29 context: deser_core::Context,
30 max_shared_events: usize,
31}
32
33impl Default for DeserializerConfig {
34 fn default() -> DeserializerConfig {
35 DeserializerConfig::new()
36 }
37}
38
39impl DeserializerConfig {
40 /// Creates the default configuration.
41 pub const fn new() -> DeserializerConfig {
42 DeserializerConfig {
43 context: deser_core::Context::new(),
44 max_shared_events: DEFAULT_MAX_SHARED_EVENTS,
45 }
46 }
47
48 /// Returns a builder for the configuration (see [`DeserializerConfigBuilder`]).
49 pub const fn builder() -> DeserializerConfigBuilder {
50 DeserializerConfigBuilder::new()
51 }
52
53 /// Returns a builder that starts with this configuration.
54 pub const fn into_builder(self) -> DeserializerConfigBuilder {
55 DeserializerConfigBuilder { value: self }
56 }
57
58 /// Sets the context the values are deserialized in.
59 ///
60 /// The values of the context are the defaults of the extension values
61 /// of the state (see [`Context`](deser_core::Context)), for instance
62 /// the variants of open enums. The deserializers and readers created
63 /// with the configuration use this context. A context set on the
64 /// driver takes precedence.
65 pub fn set_context(&mut self, context: deser_core::Context) {
66 self.context = context;
67 }
68
69 /// Returns the configuration without its context (for the frames of
70 /// streams, which get the context of the stream).
71 pub(crate) fn without_context(&self) -> DeserializerConfig {
72 let mut config = self.clone();
73 config.context = deser_core::Context::default();
74 config
75 }
76
77 /// Returns the context the values are deserialized in.
78 pub fn context(&self) -> &deser_core::Context {
79 &self.context
80 }
81
82 /// Limits the events of values that are emitted more than once.
83 ///
84 /// Values that are reached more than once are emitted at every place
85 /// (see [References](crate#references)). A small pickle can reach the
86 /// same values very often (each level of a list that holds the level
87 /// below twice doubles the output), this limits the number of events
88 /// that are emitted for values that were emitted before. The default
89 /// is 1048576.
90 pub fn set_max_shared_events(&mut self, max: usize) {
91 self.max_shared_events = max;
92 }
93
94 /// Returns the limit of the events of values that are emitted more
95 /// than once.
96 pub fn max_shared_events(&self) -> usize {
97 self.max_shared_events
98 }
99
100 /// Deserializes a value.
101 ///
102 /// See [`from_slice`].
103 pub fn from_slice<'de, T: Deserialize<'de>>(&self, input: &'de [u8]) -> Result<T, Error> {
104 deserialize_value(|driver| self.drive_slice(input, driver))
105 }
106
107 /// The part of [`from_slice`](Self::from_slice) that does not depend on
108 /// the type of the value, it exists once.
109 fn drive_slice<'de>(
110 &self,
111 input: &'de [u8],
112 driver: &mut DeserializeDriver<'_, 'de>,
113 ) -> Result<(), Error> {
114 let mut deserializer = Deserializer::from_slice_with_config(input, self.clone());
115 de::Deserializer::drive(&mut deserializer, driver)?;
116 deserializer.end()
117 }
118}
119
120/// Builds a [`DeserializerConfig`].
121///
122/// The methods have the names of the setters of [`DeserializerConfig`] (without `set_`).
123#[derive(Debug, Clone)]
124#[must_use]
125pub struct DeserializerConfigBuilder {
126 value: DeserializerConfig,
127}
128
129impl DeserializerConfigBuilder {
130 /// Creates a builder that starts with the default.
131 pub const fn new() -> DeserializerConfigBuilder {
132 DeserializerConfigBuilder {
133 value: DeserializerConfig::new(),
134 }
135 }
136
137 /// Sets the context the values are deserialized in.
138 ///
139 /// See [`DeserializerConfig::set_context`].
140 pub fn context(mut self, context: deser_core::Context) -> DeserializerConfigBuilder {
141 self.value.set_context(context);
142 self
143 }
144
145 /// Limits the events of values that are emitted more than once.
146 ///
147 /// See [`DeserializerConfig::set_max_shared_events`].
148 pub const fn max_shared_events(mut self, max: usize) -> DeserializerConfigBuilder {
149 self.value.max_shared_events = max;
150 self
151 }
152
153 /// Returns the built [`DeserializerConfig`].
154 pub const fn build(self) -> DeserializerConfig {
155 // the value cannot be moved out of the builder in a const fn as the
156 // builder needs dropping (the context has a destructor)
157 // SAFETY: the value is read once and the builder is forgotten
158 let value = unsafe { core::ptr::read(&self.value) };
159 core::mem::forget(self);
160 value
161 }
162}
163
164impl Default for DeserializerConfigBuilder {
165 fn default() -> DeserializerConfigBuilder {
166 DeserializerConfigBuilder::new()
167 }
168}
169
170/// Deserializes pickles.
171///
172/// A deserializer reads values from a slice. Pickles end with a `STOP`
173/// opcode, so they can be concatenated (like the pickles `pickle.dump`
174/// writes to a file one after another) and a deserializer can read more
175/// than one:
176///
177/// ```
178/// use deser_pickle::Deserializer;
179///
180/// // `pickle.dumps(1, 4) + pickle.dumps("hi", 4)`
181/// let input = b"\x80\x04K\x01.\x80\x04\x95\x06\x00\x00\x00\x00\x00\x00\x00\x8c\x02hi\x94.";
182/// let mut de = Deserializer::from_slice(input);
183/// assert_eq!(de.deserialize::<u32>().unwrap(), 1);
184/// assert_eq!(de.deserialize::<String>().unwrap(), "hi");
185/// assert!(de.is_end());
186/// ```
187///
188/// To deserialize a single value, use [`from_slice`]
189/// (or the method of the same name on [`DeserializerConfig`]).
190pub struct Deserializer<'a> {
191 input: &'a [u8],
192 pos: usize,
193 config: DeserializerConfig,
194}
195
196impl<'a> Deserializer<'a> {
197 /// Creates a new deserializer for a byte slice.
198 pub fn from_slice(input: &'a [u8]) -> Deserializer<'a> {
199 Deserializer::from_slice_with_config(input, DeserializerConfig::new())
200 }
201
202 /// Creates a new deserializer for a byte slice with the given
203 /// configuration.
204 pub fn from_slice_with_config(input: &'a [u8], config: DeserializerConfig) -> Deserializer<'a> {
205 Deserializer {
206 input,
207 pos: 0,
208 config,
209 }
210 }
211
212 /// Returns the configuration.
213 pub fn config(&self) -> &DeserializerConfig {
214 &self.config
215 }
216
217 /// Returns the current offset in the input.
218 pub fn offset(&self) -> usize {
219 self.pos
220 }
221
222 /// Returns `true` if the entire input was consumed.
223 pub fn is_end(&self) -> bool {
224 self.pos >= self.input.len()
225 }
226
227 /// Fails if the input was not consumed entirely.
228 ///
229 /// Unlike Python (which ignores data after the `STOP` opcode) the
230 /// functions that deserialize a single value reject it.
231 pub fn end(&self) -> Result<(), Error> {
232 if self.is_end() {
233 Ok(())
234 } else {
235 Err(syntax_error(self.pos, "trailing data after STOP"))
236 }
237 }
238
239 /// Deserializes the next value.
240 ///
241 /// This does not check if there is more data after the value. Use
242 /// [`end`](Self::end) for this or [`from_slice`] which does it
243 /// automatically.
244 ///
245 /// To configure the deserialization (for instance to add layers) use
246 /// [`deserialize_with`](Self::deserialize_with).
247 pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> {
248 de::Deserializer::deserialize(self)
249 }
250
251 /// Deserializes the next value with a configured driver.
252 ///
253 /// The callback is invoked with the driver before the value is
254 /// deserialized, for instance to add [`Layer`](deser_core::de::Layer)s.
255 pub fn deserialize_with<T, F>(&mut self, setup: F) -> Result<T, Error>
256 where
257 T: Deserialize<'a>,
258 F: FnOnce(&mut DeserializeDriver<'_, 'a>),
259 {
260 de::Deserializer::deserialize_with(self, setup)
261 }
262
263 /// Returns an iterator over the remaining values.
264 ///
265 /// The iterator stops after the first error.
266 ///
267 /// ```
268 /// let mut de = deser_pickle::Deserializer::from_slice(b"K\x01.K\x02.K\x03.");
269 /// let items = de.iter::<u32>().collect::<Result<Vec<_>, _>>().unwrap();
270 /// assert_eq!(items, [1, 2, 3]);
271 /// ```
272 pub fn iter<T: Deserialize<'a>>(&mut self) -> Iter<'_, 'a, T> {
273 Iter {
274 de: self,
275 failed: false,
276 _marker: PhantomData,
277 }
278 }
279
280 /// Runs the next pickle and feeds the events of its value into the
281 /// given driver.
282 ///
283 /// This is useful to deserialize into a custom
284 /// [`Sink`](deser_core::de::Sink) or to wrap the sink of a value.
285 ///
286 /// The pickle is run to its end before the first event is emitted.
287 /// Strings are passed on borrowed from the input where they can be.
288 /// The byte ranges of the opcodes that created the values are
289 /// published as input ranges (see
290 /// [`State::input_range`](deser_core::State::input_range)) and errors
291 /// carry the offset in the input (see [`Error::offset`]).
292 ///
293 /// The context of the configuration is given to the driver (values that
294 /// the context of the driver has take precedence, see
295 /// [`DeserializeDriver::set_default_context`]).
296 pub fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
297 if !self.config.context.is_empty() {
298 driver.set_default_context(self.config.context.clone());
299 }
300 let (graph, end) = Machine::new(self.input, self.pos).run()?;
301 emit(&graph, driver, self.config.max_shared_events)?;
302 self.pos = end;
303 Ok(())
304 }
305}
306
307/// An iterator over concatenated pickles.
308///
309/// See [`Deserializer::iter`].
310pub struct Iter<'b, 'a, T> {
311 de: &'b mut Deserializer<'a>,
312 failed: bool,
313 _marker: PhantomData<fn() -> T>,
314}
315
316impl<'b, 'a, T: Deserialize<'a>> Iterator for Iter<'b, 'a, T> {
317 type Item = Result<T, Error>;
318
319 fn next(&mut self) -> Option<Self::Item> {
320 if self.failed || self.de.is_end() {
321 return None;
322 }
323 let rv = self.de.deserialize();
324 self.failed = rv.is_err();
325 Some(rv)
326 }
327}
328
329impl<'a> de::Deserializer<'a> for Deserializer<'a> {
330 fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
331 Deserializer::drive(self, driver)
332 }
333}
334
335/// Deserializes a pickle.
336///
337/// The input must contain exactly one pickle. This uses the default
338/// [`DeserializerConfig`].
339///
340/// ```
341/// #[derive(deser::Deserialize)]
342/// struct Package {
343/// name: String,
344/// tags: Vec<String>,
345/// }
346///
347/// // `pickle.dumps({"name": "deser", "tags": ["a", "b"]}, 4)`
348/// let input = b"\x80\x04\x95'\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x05deser\x94\x8c\x04tags\x94]\x94(\x8c\x01a\x94\x8c\x01b\x94eu.";
349/// let package: Package = deser_pickle::from_slice(input).unwrap();
350/// assert_eq!(package.name, "deser");
351/// assert_eq!(package.tags, ["a", "b"]);
352/// ```
353pub fn from_slice<'de, T: Deserialize<'de>>(input: &'de [u8]) -> Result<T, Error> {
354 DeserializerConfig::new().from_slice(input)
355}