cu_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//! # Example
40//!
41//! ```rust
42//! # extern crate cu_bincode as bincode;
43//! let mut slice = [0u8; 100];
44//!
45//! // You can encode any type that implements `Encode`.
46//! // You can automatically implement this trait on custom types with the `derive` feature.
47//! let input = (
48//! 0u8,
49//! 10u32,
50//! 10000i128,
51//! 'a',
52//! [0u8, 1u8, 2u8, 3u8]
53//! );
54//!
55//! let length = bincode::encode_into_slice(
56//! input,
57//! &mut slice,
58//! bincode::config::standard()
59//! ).unwrap();
60//!
61//! let slice = &slice[..length];
62//! println!("Bytes written: {:?}", slice);
63//!
64//! // Decoding works the same as encoding.
65//! // The trait used is `Decode`, and can also be automatically implemented with the `derive` feature.
66//! let decoded: (u8, u32, i128, char, [u8; 4]) = bincode::decode_from_slice(slice, bincode::config::standard()).unwrap().0;
67//!
68//! assert_eq!(decoded, input);
69//! ```
70//!
71//! [`fs::File`]: std::fs::File
72//! [`net::TcpStream`]: std::net::TcpStream
73//!
74
75#![doc(html_root_url = "https://docs.rs/cu-bincode/2.2.0-beta")]
76#![crate_name = "cu_bincode"]
77#![crate_type = "rlib"]
78
79#[cfg(feature = "alloc")]
80extern crate alloc;
81#[cfg(any(feature = "std", test))]
82extern crate std;
83
84mod atomic;
85mod uleb128;
86
87pub use uleb128::Uleb128;
88mod features;
89pub(crate) mod utils;
90pub(crate) mod varint;
91
92use de::{Decoder, read::Reader};
93use enc::write::Writer;
94
95#[cfg(any(
96 feature = "alloc",
97 feature = "std",
98 feature = "derive",
99 feature = "serde"
100))]
101pub use features::*;
102
103pub mod value_decode;
104pub use value_decode::{ValueDecode, ValueDecodeSpec};
105
106pub mod config;
107#[macro_use]
108pub mod de;
109pub mod enc;
110pub mod error;
111
112pub use de::{BorrowDecode, Decode};
113pub use enc::Encode;
114
115use config::Config;
116
117/// Encode the given value into the given slice. Returns the amount of bytes that have been written.
118///
119/// See the [config] module for more information on configurations.
120///
121/// [config]: config/index.html
122pub fn encode_into_slice<E: enc::Encode, C: Config>(
123 val: E,
124 dst: &mut [u8],
125 config: C,
126) -> Result<usize, error::EncodeError> {
127 let writer = enc::write::SliceWriter::new(dst);
128 let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
129 val.encode(&mut encoder)?;
130 Ok(encoder.into_writer().bytes_written())
131}
132
133/// Encode the given value into a custom [Writer].
134///
135/// See the [config] module for more information on configurations.
136///
137/// [config]: config/index.html
138pub fn encode_into_writer<E: enc::Encode, W: Writer, C: Config>(
139 val: E,
140 writer: W,
141 config: C,
142) -> Result<(), error::EncodeError> {
143 let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
144 val.encode(&mut encoder)?;
145 Ok(())
146}
147
148/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read.
149///
150/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice].
151///
152/// See the [config] module for more information on configurations.
153///
154/// [config]: config/index.html
155pub fn decode_from_slice<D: de::Decode<()>, C: Config>(
156 src: &[u8],
157 config: C,
158) -> Result<(D, usize), error::DecodeError> {
159 decode_from_slice_with_context(src, config, ())
160}
161
162/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read.
163///
164/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice].
165///
166/// See the [config] module for more information on configurations.
167///
168/// [config]: config/index.html
169pub fn decode_from_slice_with_context<Context, D: de::Decode<Context>, C: Config>(
170 src: &[u8],
171 config: C,
172 context: Context,
173) -> Result<(D, usize), error::DecodeError> {
174 let reader = de::read::SliceReader::new(src);
175 let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
176 let result = D::decode(&mut decoder)?;
177 let bytes_read = src.len() - decoder.reader().slice.len();
178 Ok((result, bytes_read))
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/// See the [config] module for more information on configurations.
184///
185/// [config]: config/index.html
186pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a, ()>, C: Config>(
187 src: &'a [u8],
188 config: C,
189) -> Result<(D, usize), error::DecodeError> {
190 borrow_decode_from_slice_with_context(src, config, ())
191}
192
193/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read.
194///
195/// See the [config] module for more information on configurations.
196///
197/// [config]: config/index.html
198pub fn borrow_decode_from_slice_with_context<
199 'a,
200 Context,
201 D: de::BorrowDecode<'a, Context>,
202 C: Config,
203>(
204 src: &'a [u8],
205 config: C,
206 context: Context,
207) -> Result<(D, usize), error::DecodeError> {
208 let reader = de::read::SliceReader::new(src);
209 let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
210 let result = D::borrow_decode(&mut decoder)?;
211 let bytes_read = src.len() - decoder.reader().slice.len();
212 Ok((result, bytes_read))
213}
214
215/// Attempt to decode a given type `D` from the given [Reader].
216///
217/// See the [config] module for more information on configurations.
218///
219/// [config]: config/index.html
220pub fn decode_from_reader<D: de::Decode<()>, R: Reader, C: Config>(
221 reader: R,
222 config: C,
223) -> Result<D, error::DecodeError> {
224 let mut decoder = de::DecoderImpl::<_, C, ()>::new(reader, config, ());
225 D::decode(&mut decoder)
226}
227
228// TODO: Currently our doctests fail when trying to include the specs because the specs depend on `derive` and `alloc`.
229// But we want to have the specs in the docs always
230#[cfg(all(feature = "alloc", feature = "derive", doc))]
231pub mod spec {
232 #![doc = include_str!("../docs/spec.md")]
233}
234
235#[cfg(doc)]
236pub mod migration_guide {
237 #![doc = include_str!("../docs/migration_guide.md")]
238}
239
240// Test the examples in readme.md
241#[cfg(all(feature = "alloc", feature = "derive", doctest))]
242mod readme {
243 #![doc = include_str!("../README.md")]
244}