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