bincode_next/lib.rs
1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4//! Bincode-next is a crate for encoding and decoding using a tiny binary
5//! serialization strategy. Using it, you can easily go from having
6//! an object in memory, quickly serialize it to bytes, and then
7//! deserialize it back just as fast!
8//!
9//! If you're coming from bincode 1, check out our [migration guide](migration_guide/index.html)
10//!
11//! # Serde
12//!
13//! 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.
14//!
15//! # Features
16//!
17//! |Name |Default?|Affects MSRV?|Supported types for Encode/Decode|Enabled methods |Other|
18//! |------|--------|-------------|-----------------------------------------|-----------------------------------------------------------------|-----|
19//! |std | Yes | No |`HashMap` and `HashSet`|`decode_from_std_read` and `encode_into_std_write`|
20//! |alloc | Yes | No |All common containers in alloc, like `Vec`, `String`, `Box`|`encode_to_vec`|
21//! |atomic| Yes | No |All `Atomic*` integer types, e.g. `AtomicUsize`, and `AtomicBool`||
22//! |derive| Yes | No |||Enables the `BorrowDecode`, `Decode` and `Encode` derive macros|
23//! |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|
24//!
25//! # Which functions to use
26//!
27//! Bincode has a couple of pairs of functions that are used in different situations.
28//!
29//! |Situation|Encode|Decode|
30//! |---|---|---
31//! |You're working with [`fs::File`] or [`net::TcpStream`]|[`encode_into_std_write`]|[`decode_from_std_read`]|
32//! |you're working with in-memory buffers|[`encode_to_vec`]|[`decode_from_slice`]|
33//! |You want to use a custom [Reader] and [Writer]|[`encode_into_writer`]|[`decode_from_reader`]|
34//! |You're working with pre-allocated buffers or on embedded targets|[`encode_into_slice`]|[`decode_from_slice`]|
35//!
36//! **Note:** If you're using `serde`, use `bincode::serde::...` instead of `bincode::...`
37//!
38//! # Example
39//!
40//! ```rust
41//! let mut slice = [0u8; 100];
42//!
43//! // You can encode any type that implements `Encode`.
44//! // You can automatically implement this trait on custom types with the `derive` feature.
45//! let input = (
46//! 0u8,
47//! 10u32,
48//! 10000i128,
49//! 'a',
50//! [0u8, 1u8, 2u8, 3u8]
51//! );
52//!
53//! let length = bincode::encode_into_slice(
54//! input,
55//! &mut slice,
56//! bincode::config::standard()
57//! ).unwrap();
58//!
59//! let slice = &slice[..length];
60//! println!("Bytes written: {:?}", slice);
61//!
62//! // Decoding works the same as encoding.
63//! // The trait used is `Decode`, and can also be automatically implemented with the `derive` feature.
64//! let decoded: (u8, u32, i128, char, [u8; 4]) = bincode::decode_from_slice(slice, bincode::config::standard()).unwrap().0;
65//!
66//! assert_eq!(decoded, input);
67//! ```
68//!
69//! [`fs::File`]: std::fs::File
70//! [`net::TcpStream`]: std::net::TcpStream
71//!
72
73// =========================================================================
74// RUST LINT CONFIGURATION: bincode-next
75// =========================================================================
76
77// -------------------------------------------------------------------------
78// LEVEL 1: CRITICAL ERRORS (Deny)
79// -------------------------------------------------------------------------
80#![deny(
81 // Rust Compiler Errors
82 dead_code,
83 unreachable_code,
84 improper_ctypes_definitions,
85 future_incompatible,
86 nonstandard_style,
87 rust_2018_idioms,
88 clippy::perf,
89 clippy::correctness,
90 clippy::suspicious,
91 clippy::unwrap_used,
92 clippy::expect_used,
93 clippy::indexing_slicing,
94 clippy::arithmetic_side_effects,
95 clippy::missing_safety_doc,
96 clippy::same_item_push,
97 clippy::implicit_clone,
98 clippy::all,
99 clippy::pedantic,
100 warnings,
101 missing_docs,
102 clippy::nursery,
103 clippy::single_call_fn,
104)]
105// -------------------------------------------------------------------------
106// LEVEL 2: STYLE WARNINGS (Warn)
107// -------------------------------------------------------------------------
108#![warn(
109 unsafe_code,
110 clippy::dbg_macro,
111 clippy::todo,
112 clippy::unnecessary_safety_comment
113)]
114// -------------------------------------------------------------------------
115// LEVEL 3: ALLOW/IGNORABLE (Allow)
116// -------------------------------------------------------------------------
117#![allow(
118 clippy::restriction,
119 unused_doc_comments,
120 clippy::empty_line_after_doc_comments
121)]
122#![crate_name = "bincode_next"]
123#![crate_type = "rlib"]
124
125#[cfg(feature = "alloc")]
126extern crate alloc;
127#[cfg(any(feature = "std", test))]
128extern crate std;
129
130mod atomic;
131mod features;
132pub(crate) mod utils;
133pub(crate) mod varint;
134
135use de::{read::Reader, Decoder};
136use enc::write::Writer;
137
138#[cfg(any(
139 feature = "alloc",
140 feature = "std",
141 feature = "derive",
142 feature = "serde"
143))]
144pub use features::*;
145
146pub mod config;
147#[macro_use]
148pub mod de;
149pub mod enc;
150pub mod error;
151
152pub use de::{BorrowDecode, Decode};
153pub use enc::Encode;
154
155use config::Config;
156
157/// Encode the given value into the given slice. Returns the amount of bytes that have been written.
158///
159/// See the [config] module for more information on configurations.
160///
161/// [config]: config/index.html
162pub fn encode_into_slice<E: enc::Encode, C: Config>(
163 val: E,
164 dst: &mut [u8],
165 config: C,
166) -> Result<usize, error::EncodeError> {
167 let writer = enc::write::SliceWriter::new(dst);
168 let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
169 val.encode(&mut encoder)?;
170 Ok(encoder.into_writer().bytes_written())
171}
172
173/// Encode the given value into a custom [Writer].
174///
175/// See the [config] module for more information on configurations.
176///
177/// [config]: config/index.html
178pub fn encode_into_writer<E: enc::Encode, W: Writer, C: Config>(
179 val: E,
180 writer: W,
181 config: C,
182) -> Result<(), error::EncodeError> {
183 let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
184 val.encode(&mut encoder)?;
185 Ok(())
186}
187
188/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read.
189///
190/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice].
191///
192/// See the [config] module for more information on configurations.
193///
194/// [config]: config/index.html
195pub fn decode_from_slice<D: de::Decode<()>, C: Config>(
196 src: &[u8],
197 config: C,
198) -> Result<(D, usize), error::DecodeError> {
199 decode_from_slice_with_context(src, config, ())
200}
201
202/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read.
203///
204/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice].
205///
206/// See the [config] module for more information on configurations.
207///
208/// [config]: config/index.html
209pub fn decode_from_slice_with_context<Context, D: de::Decode<Context>, C: Config>(
210 src: &[u8],
211 config: C,
212 context: Context,
213) -> Result<(D, usize), error::DecodeError> {
214 let reader = de::read::SliceReader::new(src);
215 let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
216 let result = D::decode(&mut decoder)?;
217 let bytes_read = src.len() - decoder.reader().slice.len();
218 Ok((result, bytes_read))
219}
220
221/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read.
222///
223/// See the [config] module for more information on configurations.
224///
225/// [config]: config/index.html
226pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a, ()>, C: Config>(
227 src: &'a [u8],
228 config: C,
229) -> Result<(D, usize), error::DecodeError> {
230 borrow_decode_from_slice_with_context(src, config, ())
231}
232
233/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read.
234///
235/// See the [config] module for more information on configurations.
236///
237/// [config]: config/index.html
238pub fn borrow_decode_from_slice_with_context<
239 'a,
240 Context,
241 D: de::BorrowDecode<'a, Context>,
242 C: Config,
243>(
244 src: &'a [u8],
245 config: C,
246 context: Context,
247) -> Result<(D, usize), error::DecodeError> {
248 let reader = de::read::SliceReader::new(src);
249 let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
250 let result = D::borrow_decode(&mut decoder)?;
251 let bytes_read = src.len() - decoder.reader().slice.len();
252 Ok((result, bytes_read))
253}
254
255/// Attempt to decode a given type `D` from the given [Reader].
256///
257/// See the [config] module for more information on configurations.
258///
259/// [config]: config/index.html
260pub fn decode_from_reader<D: de::Decode<()>, R: Reader, C: Config>(
261 reader: R,
262 config: C,
263) -> Result<D, error::DecodeError> {
264 let mut decoder = de::DecoderImpl::<_, C, ()>::new(reader, config, ());
265 D::decode(&mut decoder)
266}
267
268// TODO: Currently our doctests fail when trying to include the specs because the specs depend on `derive` and `alloc`.
269// But we want to have the specs in the docs always
270#[cfg(all(feature = "alloc", feature = "derive", doc))]
271pub mod spec {
272 #![doc = include_str!("../docs/spec.md")]
273}
274
275#[cfg(doc)]
276pub mod migration_guide {
277 #![doc = include_str!("../docs/migration_guide.md")]
278}
279
280// Test the examples in readme.md
281#[cfg(all(feature = "alloc", feature = "derive", doctest))]
282mod readme {
283 #![doc = include_str!("../readme.md")]
284}