bincode/lib.rs
1#![no_std]
2#![warn(missing_docs, unused_lifetimes)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5//! Bincode is a crate for encoding and decoding using a tiny binary
6//! serialization strategy. Using it, you can easily go from having
7//! an object in memory, quickly serialize it to bytes, and then
8//! deserialize it back just as fast!
9//!
10//! If you're coming from bincode 1, check out our [migration guide](migration_guide/index.html)
11//!
12//! # Serde
13//!
14//! Starting from bincode 2, serde is now an optional dependency. If you want to use serde, please enable the `serde` feature. See [Features](#features) for more information.
15//!
16//! # Features
17//!
18//! |Name |Default?|Affects MSRV?|Supported types for Encode/Decode|Enabled methods |Other|
19//! |------|--------|-------------|-----------------------------------------|-----------------------------------------------------------------|-----|
20//! |std | Yes | No |`HashMap` and `HashSet`|`decode_from_std_read` and `encode_into_std_write`|
21//! |alloc | Yes | No |All common containers in alloc, like `Vec`, `String`, `Box`|`encode_to_vec`|
22//! |atomic| Yes | No |All `Atomic*` integer types, e.g. `AtomicUsize`, and `AtomicBool`||
23//! |derive| Yes | No |||Enables the `BorrowDecode`, `Decode` and `Encode` derive macros|
24//! |serde | No | Yes (MSRV reliant on serde)|`Compat` and `BorrowCompat`, which will work for all types that implement serde's traits|serde-specific encode/decode functions in the [serde] module|Note: There are several [known issues](serde/index.html#known-issues) when using serde and bincode|
25//!
26//! # Which functions to use
27//!
28//! Bincode has a couple of pairs of functions that are used in different situations.
29//!
30//! |Situation|Encode|Decode|
31//! |---|---|---
32//! |You're working with [`fs::File`] or [`net::TcpStream`]|[`encode_into_std_write`]|[`decode_from_std_read`]|
33//! |you're working with in-memory buffers|[`encode_to_vec`]|[`decode_from_slice`]|
34//! |You want to use a custom [Reader] and [Writer]|[`encode_into_writer`]|[`decode_from_reader`]|
35//! |You're working with pre-allocated buffers or on embedded targets|[`encode_into_slice`]|[`decode_from_slice`]|
36//!
37//! **Note:** If you're using `serde`, use `bincode::serde::...` instead of `bincode::...`
38//!
39//! # Untrusted input
40//!
41//! The `*_untrusted` decoding functions opt into collection allocation safeguards.
42//! Ordinary decoding functions retain upstream 2.0.1 behavior. Untrusted functions
43//! require the independent [`DecodeUntrusted`]/[`BorrowDecodeUntrusted`] traits.
44//! Derive only `DecodeUntrusted` for client types that should not support ordinary
45//! decoding, or derive both traits when both APIs are intended. Nested values
46//! dispatch through the corresponding untrusted trait. These implementations own
47//! guarded allocation; ordinary `Decode` is independent of the decoder capability.
48//! Manual implementations must also call the untrusted traits for nested values.
49//! Both paths retain the same configuration and wire format.
50//!
51//! ```
52//! #[derive(bincode::DecodeUntrusted)]
53//! struct Message { value: u8 }
54//! let (message, consumed): (Message, _) = bincode::decode_from_slice_untrusted(
55//! &[42], bincode::config::standard(),
56//! ).unwrap();
57//! assert_eq!(message.value, 42);
58//! assert_eq!(consumed, 1);
59//! ```
60//!
61//! With Serde, custom implementations explicitly implement
62//! `serde::DeserializeUntrusted` for their entire deserialization graph. Serde
63//! constructors expose constrained `decode`/`decode_seed` methods in this mode.
64//!
65//! Untrusted native vector and hash collection implementations allocate storage after
66//! entries decode. Byte vectors first verify the available payload, or read bounded
67//! chunks when the reader cannot expose it. Failed reservations in these containers
68//! return [`error::DecodeError::LimitExceeded`]. Serde adapters omit collection size
69//! hints that could otherwise cause visitors to allocate from an unchecked length.
70//!
71//! These safeguards are not a general memory, recursion, or CPU budget. Custom
72//! decoders and Serde visitors remain responsible for their own resource use;
73//! types that consume no bytes can still decode from arbitrarily large counts.
74//! Existing configured limits retain their meaning, including `with_no_limit()`.
75//! Failed untrusted byte-vector reads may consume earlier chunks and report a
76//! missing-byte estimate for the failing chunk. Successful values and consumed
77//! lengths are unchanged; hash collection iteration order is unspecified.
78//!
79//! # Example
80//!
81//! ```rust
82//! let mut slice = [0u8; 100];
83//!
84//! // You can encode any type that implements `Encode`.
85//! // You can automatically implement this trait on custom types with the `derive` feature.
86//! let input = (
87//! 0u8,
88//! 10u32,
89//! 10000i128,
90//! 'a',
91//! [0u8, 1u8, 2u8, 3u8]
92//! );
93//!
94//! let length = bincode::encode_into_slice(
95//! input,
96//! &mut slice,
97//! bincode::config::standard()
98//! ).unwrap();
99//!
100//! let slice = &slice[..length];
101//! println!("Bytes written: {:?}", slice);
102//!
103//! // Decoding works the same as encoding.
104//! // The trait used is `Decode`, and can also be automatically implemented with the `derive` feature.
105//! let decoded: (u8, u32, i128, char, [u8; 4]) = bincode::decode_from_slice(slice, bincode::config::standard()).unwrap().0;
106//!
107//! assert_eq!(decoded, input);
108//! ```
109//!
110//! [`fs::File`]: std::fs::File
111//! [`net::TcpStream`]: std::net::TcpStream
112//!
113
114#![doc(html_root_url = "https://docs.rs/bincode/2.0.1")]
115#![crate_name = "bincode"]
116#![crate_type = "rlib"]
117
118#[cfg(feature = "alloc")]
119extern crate alloc;
120#[cfg(any(feature = "std", test))]
121extern crate std;
122
123mod atomic;
124mod features;
125pub(crate) mod utils;
126pub(crate) mod varint;
127
128use de::{read::Reader, Decoder};
129use enc::write::Writer;
130
131#[cfg(any(
132 feature = "alloc",
133 feature = "std",
134 feature = "derive",
135 feature = "serde"
136))]
137pub use features::*;
138
139pub mod config;
140#[macro_use]
141pub mod de;
142pub mod enc;
143pub mod error;
144
145pub use de::{BorrowDecode, BorrowDecodeUntrusted, Decode, DecodeUntrusted};
146pub use enc::Encode;
147
148use config::Config;
149
150/// Encode the given value into the given slice. Returns the amount of bytes that have been written.
151///
152/// See the [config] module for more information on configurations.
153///
154/// [config]: config/index.html
155pub fn encode_into_slice<E: enc::Encode, C: Config>(
156 val: E,
157 dst: &mut [u8],
158 config: C,
159) -> Result<usize, error::EncodeError> {
160 let writer = enc::write::SliceWriter::new(dst);
161 let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
162 val.encode(&mut encoder)?;
163 Ok(encoder.into_writer().bytes_written())
164}
165
166/// Encode the given value into a custom [Writer].
167///
168/// See the [config] module for more information on configurations.
169///
170/// [config]: config/index.html
171pub fn encode_into_writer<E: enc::Encode, W: Writer, C: Config>(
172 val: E,
173 writer: W,
174 config: C,
175) -> Result<(), error::EncodeError> {
176 let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
177 val.encode(&mut encoder)?;
178 Ok(())
179}
180
181/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read.
182///
183/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice].
184///
185/// See the [config] module for more information on configurations.
186///
187/// [config]: config/index.html
188pub fn decode_from_slice<D: de::Decode<()>, C: Config>(
189 src: &[u8],
190 config: C,
191) -> Result<(D, usize), error::DecodeError> {
192 decode_from_slice_with_context(src, config, ())
193}
194
195/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read.
196///
197/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice].
198///
199/// See the [config] module for more information on configurations.
200///
201/// [config]: config/index.html
202pub fn decode_from_slice_with_context<Context, D: de::Decode<Context>, C: Config>(
203 src: &[u8],
204 config: C,
205 context: Context,
206) -> Result<(D, usize), error::DecodeError> {
207 let reader = de::read::SliceReader::new(src);
208 let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
209 let result = D::decode(&mut decoder)?;
210 let bytes_read = src.len() - decoder.reader().slice.len();
211 Ok((result, bytes_read))
212}
213
214/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read.
215///
216/// See the [config] module for more information on configurations.
217///
218/// [config]: config/index.html
219pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a, ()>, C: Config>(
220 src: &'a [u8],
221 config: C,
222) -> Result<(D, usize), error::DecodeError> {
223 borrow_decode_from_slice_with_context(src, config, ())
224}
225
226/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read.
227///
228/// See the [config] module for more information on configurations.
229///
230/// [config]: config/index.html
231pub fn borrow_decode_from_slice_with_context<
232 'a,
233 Context,
234 D: de::BorrowDecode<'a, Context>,
235 C: Config,
236>(
237 src: &'a [u8],
238 config: C,
239 context: Context,
240) -> Result<(D, usize), error::DecodeError> {
241 let reader = de::read::SliceReader::new(src);
242 let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
243 let result = D::borrow_decode(&mut decoder)?;
244 let bytes_read = src.len() - decoder.reader().slice.len();
245 Ok((result, bytes_read))
246}
247
248/// Attempt to decode a given type `D` from the given [Reader].
249///
250/// See the [config] module for more information on configurations.
251///
252/// [config]: config/index.html
253pub fn decode_from_reader<D: de::Decode<()>, R: Reader, C: Config>(
254 reader: R,
255 config: C,
256) -> Result<D, error::DecodeError> {
257 let mut decoder = de::DecoderImpl::<_, C, ()>::new(reader, config, ());
258 D::decode(&mut decoder)
259}
260
261/// Decode from a slice with the [untrusted collection safeguards](crate#untrusted-input).
262/// Returns the decoded value and the number of bytes consumed.
263pub fn decode_from_slice_untrusted<D: de::DecodeUntrusted<()>, C: Config>(
264 src: &[u8],
265 config: C,
266) -> Result<(D, usize), error::DecodeError> {
267 decode_from_slice_untrusted_with_context(src, config, ())
268}
269
270/// Decode from a slice with a context and the [untrusted collection safeguards](crate#untrusted-input).
271/// Returns the decoded value and the number of bytes consumed.
272pub fn decode_from_slice_untrusted_with_context<
273 Context,
274 D: de::DecodeUntrusted<Context>,
275 C: Config,
276>(
277 src: &[u8],
278 config: C,
279 context: Context,
280) -> Result<(D, usize), error::DecodeError> {
281 let reader = de::read::SliceReader::new(src);
282 let mut decoder = de::DecoderImpl::new_untrusted(reader, config, context);
283 let result = D::decode_untrusted(&mut decoder)?;
284 let bytes_read = src.len() - decoder.reader().slice.len();
285 Ok((result, bytes_read))
286}
287
288/// Borrow-decode from a slice with the [untrusted collection safeguards](crate#untrusted-input).
289/// Returns the decoded value and the number of bytes consumed.
290pub fn borrow_decode_from_slice_untrusted<'a, D: de::BorrowDecodeUntrusted<'a, ()>, C: Config>(
291 src: &'a [u8],
292 config: C,
293) -> Result<(D, usize), error::DecodeError> {
294 borrow_decode_from_slice_untrusted_with_context(src, config, ())
295}
296
297/// Borrow-decode with a context and the [untrusted collection safeguards](crate#untrusted-input).
298/// Returns the decoded value and the number of bytes consumed.
299pub fn borrow_decode_from_slice_untrusted_with_context<
300 'a,
301 Context,
302 D: de::BorrowDecodeUntrusted<'a, Context>,
303 C: Config,
304>(
305 src: &'a [u8],
306 config: C,
307 context: Context,
308) -> Result<(D, usize), error::DecodeError> {
309 let reader = de::read::SliceReader::new(src);
310 let mut decoder = de::DecoderImpl::new_untrusted(reader, config, context);
311 let result = D::borrow_decode_untrusted(&mut decoder)?;
312 let bytes_read = src.len() - decoder.reader().slice.len();
313 Ok((result, bytes_read))
314}
315
316/// Decode from a custom reader with the [untrusted collection safeguards](crate#untrusted-input).
317pub fn decode_from_reader_untrusted<D: de::DecodeUntrusted<()>, R: Reader, C: Config>(
318 reader: R,
319 config: C,
320) -> Result<D, error::DecodeError> {
321 let mut decoder = de::DecoderImpl::new_untrusted(reader, config, ());
322 D::decode_untrusted(&mut decoder)
323}
324
325// TODO: Currently our doctests fail when trying to include the specs because the specs depend on `derive` and `alloc`.
326// But we want to have the specs in the docs always
327#[cfg(all(feature = "alloc", feature = "derive", doc))]
328pub mod spec {
329 #![doc = include_str!("../docs/spec.md")]
330}
331
332#[cfg(doc)]
333pub mod migration_guide {
334 #![doc = include_str!("../docs/migration_guide.md")]
335}
336
337// Test the examples in readme.md
338#[cfg(all(feature = "alloc", feature = "derive", doctest))]
339mod readme {
340 #![doc = include_str!("../readme.md")]
341}