deser_pickle/lib.rs
1//! Parse and serialize Python's pickle format compatible with deser.
2//!
3//! ```rust
4//! use deser::{Deserialize, Serialize};
5//!
6//! #[derive(Debug, PartialEq, Serialize, Deserialize)]
7//! struct Session {
8//! user_id: u64,
9//! roles: Vec<String>,
10//! }
11//!
12//! let session = Session { user_id: 42, roles: vec!["admin".into()] };
13//! let bytes = deser_pickle::to_vec(&session).unwrap();
14//! // what `pickle.dumps({"user_id": 42, "roles": ["admin"]}, 4)` reads back
15//! assert_eq!(deser_pickle::from_slice::<Session>(&bytes).unwrap(), session);
16//! ```
17//!
18//! **Pickles are programs.** Python runs them and imports and calls
19//! whatever they ask for, which is why unpickling untrusted data in Python
20//! is unsafe. This crate never runs code: it runs the pickle machine but
21//! instead of importing classes and calling them it records what would
22//! have been called (see [Objects](#objects)).
23//!
24//! # Data Model
25//!
26//! Python's values map onto the deser data model as follows:
27//!
28//! | Python | deser |
29//! |----------------------------------|-----------------------------------------------|
30//! | `None` | `Null` |
31//! | `bool` | `Bool` |
32//! | `int` | `U64`, `I64`, `u128`, `i128` or [`BigInt`](deser_core::ext::BigInt) |
33//! | `float` | `F64` |
34//! | `str` | `Str` |
35//! | `bytes` | `Bytes` |
36//! | `bytearray` | `Bytes` (with [`Kind::ByteArray`]) |
37//! | `str` of Python 2 | `Str` if valid UTF-8, `Bytes` otherwise |
38//! | `list` | sequences |
39//! | `tuple`, `set`, `frozenset` | sequences (with a [`Kind`]) |
40//! | `dict` | maps (keys can be any value) |
41//! | classes and functions | [`Global`] (the dotted path as fallback) |
42//! | other objects | their state with a [class](#objects) |
43//! | a value that contains itself | [`Reference`] (see [References](#references)) |
44//!
45//! Empty sequences and maps are both: an empty list deserializes into a
46//! struct (with defaults) and an empty dict into a `Vec`.
47//!
48//! Deserialization is strict where Python is lenient: data after the
49//! `STOP` opcode is an error (Python ignores it). Strings that contain
50//! surrogates (which Python allows) cannot be held by Rust strings and are
51//! an error. Python checks that the keys of dicts and the items of sets
52//! are hashable and merges equal ones, this crate passes them on as they
53//! are. Persistent ids, extension codes and out-of-band buffers (which
54//! need help from the code that unpickles) are not supported.
55//!
56//! # Objects
57//!
58//! Pickles create instances of classes by calling them (or `__new__`) with
59//! arguments, then set their state (`BUILD`, which calls `__setstate__`)
60//! and add items (for list and dict subclasses). Instead of calling them,
61//! this crate records the calls. An object is emitted as
62//!
63//! * its items, if items were added to it (a map for `__setitem__`, a
64//! sequence for `append` and `extend`),
65//! * else its state: a map if it's a dict (the instance dictionary) or a
66//! tuple of two dicts (the dictionary and the slots, which are merged),
67//! the state itself otherwise,
68//! * else its arguments: no arguments are an empty map (or the keyword
69//! arguments), one is the argument, more are a tuple.
70//!
71//! A plain class instance (including dataclasses) is a map of its
72//! attributes, an `OrderedDict` a map of its items, a `Decimal` its text
73//! and an enum member its value. The class is passed on out of band as
74//! event data together with the [`Form`] the object is created in from
75//! the value: [`take_class`] and [`take_form`] return them, [`set_class`]
76//! and [`set_form`] set them for serialization and [`Object`] captures
77//! them. Types that do not care about classes never see them:
78//!
79//! ```rust
80//! use deser_pickle::{Form, Global, Object};
81//!
82//! #[derive(Debug, deser::Deserialize, deser::Serialize)]
83//! struct User {
84//! name: String,
85//! }
86//!
87//! // `pickle.dumps(User(name="Jane"), 4)` with a class `User` of `app`
88//! let input = b"\x80\x04\x95%\x00\x00\x00\x00\x00\x00\x00\x8c\x03app\x94\x8c\x04User\x94\x93\x94)\x81\x94}\x94\x8c\x04name\x94\x8c\x04Jane\x94sb.";
89//! let user: User = deser_pickle::from_slice(input).unwrap();
90//! assert_eq!(user.name, "Jane");
91//!
92//! let user: Object<User> = deser_pickle::from_slice(input).unwrap();
93//! assert_eq!(user.class, Some(Global::new("app", "User")));
94//! assert_eq!(user.form, Some(Form::State));
95//!
96//! // written back as Python writes it: `User.__new__(User)` with the state
97//! assert_eq!(
98//! deser_pickle::to_vec(&user).unwrap(),
99//! b"\x80\x04\x8c\x03app\x8c\x04User\x93)\x81}(\x8c\x04name\x8c\x04Janeub."
100//! );
101//! ```
102//!
103//! Objects that need both arguments and state (like classes with
104//! `__getnewargs__`) are emitted as their state, their arguments are lost.
105//!
106//! The globals that stand for builtin types are understood: `set`,
107//! `frozenset`, `bytearray`, `bytes`, `_codecs.encode` (bytes of protocols
108//! 0 to 2) and `copyreg._reconstructor` (objects of protocols 0 and 1).
109//! Like Python, the names of Python 2 (such as `__builtin__.unicode`) are
110//! read as the ones of Python 3 (`builtins.str`) before protocol 3.
111//!
112//! # References
113//!
114//! A pickle is a graph: values can be reached more than once (the memo of
115//! the pickle refers back to them) and values can contain themselves (a
116//! list that contains itself, a child object that refers to its parent).
117//! The data model of deser is a tree:
118//!
119//! * A value that is reached more than once is emitted at every place.
120//! Every time its first event carries the same id as event data (see
121//! [`take_shared_id`]), which allows types to share them again.
122//! [`DeserializerConfig::set_max_shared_events`] limits how much is
123//! emitted for repeated values.
124//! * Where a value is reached again from within itself (a cycle) it cannot
125//! be emitted again. A [`Reference`] with its id is emitted instead,
126//! whose fallback is `null`: types which do not understand references see
127//! a missing value, an `Option` is `None`.
128//!
129//! ```rust
130//! #[derive(Debug, deser::Deserialize)]
131//! struct Node {
132//! name: String,
133//! parent: Option<Box<Node>>,
134//! children: Vec<Node>,
135//! }
136//!
137//! // a root with a child whose parent is the root (`tree.Node`)
138//! let input = b"\x80\x04\x95[\x00\x00\x00\x00\x00\x00\x00\x8c\x04tree\x94\x8c\x04Node\x94\x93\x94)\x81\x94}\x94(\x8c\x04name\x94\x8c\x04root\x94\x8c\x06parent\x94N\x8c\x08children\x94]\x94h\x02)\x81\x94}\x94(h\x05\x8c\x05child\x94h\x07h\x03h\x08]\x94ubaub.";
139//! let root: Node = deser_pickle::from_slice(input).unwrap();
140//! assert_eq!(root.children[0].name, "child");
141//! assert!(root.children[0].parent.is_none());
142//! ```
143//!
144//! The serializer writes values with an id once and refers to them after
145//! that, so values deserialized into types that keep the event data (like
146//! [`deser_value::Value`](https://docs.rs/deser-value)) are written back
147//! with their sharing and cycles. Tuples that contain themselves cannot be
148//! written.
149//!
150//! # Serialization
151//!
152//! The serializer writes protocol 4 by default (protocols 2 to 5 are
153//! supported, see [`SerializerConfig::set_protocol`]):
154//!
155//! * sequences are lists, unless they have a [`Kind`]: tuples, sets and
156//! frozensets. Sequences in keys of maps are tuples.
157//! * maps are dicts. Keys can be any value but maps.
158//! * bytes are `bytes` (or `bytearray`s with [`Kind::ByteArray`]).
159//! * values with a [class](#objects) are objects, created in their
160//! [`Form`]. Without a form, maps are the state of `cls.__new__(cls)`
161//! (like Python pickles a class instance), lists are appended to the new
162//! object (like a list subclass), tuples are the arguments of the class
163//! (`cls(*value)`) and other values the argument (`cls(value)`).
164//! * before protocol 3 the globals are written with the names of Python 2
165//! (like Python does).
166//! * [`Global`]s are globals, [`Reference`]s refer to the value of their id.
167//! * other extension types (such as UUIDs and decimals) are written as
168//! their fallback, usually a string.
169//!
170//! # Features
171//!
172//! * `io` (enabled by default): reading and writing streams of the
173//! standard library with [`from_reader`] and [`to_writer`] and the
174//! readers and writers of [`deser::io`](deser_core::io)
175//! ([`DeserializerConfig::reader`] and [`SerializerConfig::writer`]).
176//! Requires `std`. The stream serializer ([`Serializer`]) and
177//! deserializer ([`StreamDeserializer`]) do not need it.
178//! * `std` (enabled by default): uses the standard library. Without it
179//! this crate only needs `alloc` (see [`no_std`](https://docs.rs/deser/latest/deser/#no_std)).
180#![doc(html_logo_url = "https://raw.githubusercontent.com/mitsuhiko/deser/main/artwork/logo.svg")]
181#![cfg_attr(not(any(feature = "std", test)), no_std)]
182
183extern crate alloc;
184
185mod compat;
186mod de;
187mod emit;
188mod ser;
189mod stream;
190mod text;
191mod types;
192mod vm;
193
194pub use self::de::{Deserializer, DeserializerConfig, DeserializerConfigBuilder, Iter, from_slice};
195#[cfg(feature = "io")]
196pub use self::ser::to_writer;
197pub use self::ser::{Serializer, SerializerConfig, SerializerConfigBuilder, to_vec};
198pub use self::stream::StreamDeserializer;
199#[cfg(feature = "io")]
200pub use self::stream::from_reader;
201pub use self::types::{
202 Form, Global, Kind, Object, Reference, set_class, set_form, set_kind, set_shared_id,
203 take_class, take_form, take_kind, take_shared_id,
204};
205
206// the examples of the readme are tested
207#[cfg(doctest)]
208#[doc = include_str!("../README.md")]
209struct ReadmeDoctests;