bitcode_lightyear_patch/
lib.rs

1#![allow(clippy::all)]
2// #![cfg_attr(test, feature(test))]
3// #![cfg_attr(doc, feature(doc_cfg))]
4#![forbid(unsafe_code)]
5#![allow(clippy::items_after_test_module)]
6
7//! Bitcode is a crate for encoding and decoding using a tinier
8//! binary serialization strategy. You can easily go from having
9//! an object in memory, quickly serialize it to bytes, and then
10//! deserialize it back just as fast!
11//!
12//! The format is not necessarily stable between versions. If you want
13//! a stable format, consider [bincode](https://docs.rs/bincode/latest/bincode/).
14//!
15//! ### Usage
16//!
17//! ```edition2021
18//! // The object that we will encode.
19//! let target: Vec<String> = vec!["a".to_owned(), "b".to_owned(), "c".to_owned()];
20//!
21//! let encoded: Vec<u8> = bitcode::encode(&target).unwrap();
22//! let decoded: Vec<String> = bitcode::decode(&encoded).unwrap();
23//! assert_eq!(target, decoded);
24//! ```
25//!
26//! ### Advanced Usage
27//!
28//! Bitcode has several hints that can be applied.
29//! Hints may have an effect on the encoded length.
30//! Most importantly hints will never cause errors if they don't hold true.
31//!
32//! ```edition2021
33//! // We mark enum variants that are more likely with a higher frequency.
34//! // This allows bitcode to use shorter encodings for them.
35//! #[derive(Copy, Clone, bitcode::Encode, bitcode::Decode)]
36//! enum Fruit {
37//!     #[bitcode_hint(frequency = 10)]
38//!     Apple,
39//!     #[bitcode_hint(frequency = 5)]
40//!     Banana,
41//!     // Unspecified frequencies are 1.
42//!     Blueberry,
43//!     Lime,
44//!     Lychee,
45//!     Watermelon,
46//! }
47//!
48//! // A cart full of 16 apples takes 2 bytes to encode (1 bit per Apple).
49//! let apple_cart: usize = bitcode::encode(&[Fruit::Apple; 16]).unwrap().len();
50//! assert_eq!(apple_cart, 2);
51//!
52//! // A cart full of 16 bananas takes 4 bytes to encode (2 bits per Banana).
53//! let banana_cart: usize = bitcode::encode(&[Fruit::Banana; 16]).unwrap().len();
54//! assert_eq!(banana_cart, 4);
55//!
56//! // A cart full of 16 blueberries takes 8 bytes to encode (4 bits per Blueberry).
57//! let blueberry_cart: usize = bitcode::encode(&[Fruit::Blueberry; 16]).unwrap().len();
58//! assert_eq!(blueberry_cart, 8);
59//! ```
60//!
61//! ```edition2021
62//! // We expect most user ages to be in the interval [10, 100), so we specify that as the expected
63//! // range. If we're right most of the time, users will take fewer bits to encode.
64//! #[derive(bitcode::Encode, bitcode::Decode)]
65//! struct User {
66//!     #[bitcode_hint(expected_range = "10..100")]
67//!     age: u32
68//! }
69//!
70//! // A user with an age inside the expected range takes up to a byte to encode.
71//! let expected_age: usize = bitcode::encode(&User { age: 42 }).unwrap().len();
72//! assert_eq!(expected_age, 1);
73//!
74//! // A user with an age outside the expected range takes more than 4 bytes to encode.
75//! let unexpected_age: usize = bitcode::encode(&User { age: 31415926 }).unwrap().len();
76//! assert!(unexpected_age > 4);
77//! ```
78//!
79//! ```edition2021
80//! // We expect that most posts won't have that many views or likes, but some can. By using gamma
81//! // encoding, posts with fewer views/likes will take fewer bits to encode.
82//! #[derive(bitcode::Encode, bitcode::Decode)]
83//! #[bitcode_hint(gamma)]
84//! struct Post {
85//!     views: u64,
86//!     likes: u64,
87//! }
88//!
89//! // An average post just takes 1 byte to encode.
90//! let average_post = bitcode::encode(&Post {
91//!     views: 4,
92//!     likes: 1,
93//! }).unwrap().len();
94//! assert_eq!(average_post, 1);
95//!
96//! // A popular post takes 11 bytes to encode, luckily these posts are rare.
97//! let popular_post = bitcode::encode(&Post {
98//!     views: 27182818,
99//!     likes: 161803,
100//! }).unwrap().len();
101//! assert_eq!(popular_post, 11)
102//! ```
103
104// https://doc.rust-lang.org/beta/unstable-book/library-features/test.html
105#[cfg(test)]
106extern crate test;
107
108// Fixes derive macro in tests/doc tests.
109#[cfg(test)]
110extern crate self as bitcode;
111
112pub use buffer::Buffer;
113pub use code::{Decode, Encode};
114use std::fmt::{self, Display, Formatter};
115
116#[cfg(feature = "derive")]
117pub use bitcode_derive::{Decode, Encode};
118
119#[cfg(any(test, feature = "serde"))]
120pub use crate::serde::{deserialize, serialize};
121
122pub mod buffer;
123mod code;
124mod code_impls;
125pub mod encoding;
126mod guard;
127mod nightly;
128pub mod read;
129mod register_buffer;
130pub mod word;
131pub mod word_buffer;
132pub mod write;
133
134#[doc(hidden)]
135pub mod __private;
136
137#[cfg(any(test, feature = "serde"))]
138pub mod serde;
139
140#[cfg(all(test, not(miri)))]
141mod benches;
142#[cfg(test)]
143mod bit_buffer;
144#[cfg(all(test, debug_assertions))]
145mod tests;
146
147/// Encodes a `T:` [`Encode`] into a [`Vec<u8>`].
148///
149/// Won't ever return `Err` unless using `#[bitcode(with_serde)]`.
150///
151/// **Warning:** The format is subject to change between versions.
152pub fn encode<T: ?Sized>(t: &T) -> Result<Vec<u8>>
153where
154    T: Encode,
155{
156    Ok(Buffer::new().encode(t)?.to_vec())
157}
158
159/// Decodes a [`&[u8]`][`prim@slice`] into an instance of `T:` [`Decode`].
160///
161/// **Warning:** The format is subject to change between versions.
162pub fn decode<T>(bytes: &[u8]) -> Result<T>
163where
164    T: Decode,
165{
166    Buffer::new().decode(bytes)
167}
168
169impl Buffer {
170    /// Encodes a `T:` [`Encode`] into a [`&[u8]`][`prim@slice`]. Can reuse the buffer's
171    /// allocations.
172    ///
173    /// Won't ever return `Err` unless using `#[bitcode(with_serde)]`.
174    ///
175    /// Even if you call `to_vec` on the [`&[u8]`][`prim@slice`], it's still more efficient than
176    /// [`encode`].
177    ///
178    /// **Warning:** The format is subject to change between versions.
179    pub fn encode<T: ?Sized>(&mut self, t: &T) -> Result<&[u8]>
180    where
181        T: Encode,
182    {
183        code::encode_internal(&mut self.0, t)
184    }
185
186    /// Decodes a [`&[u8]`][`prim@slice`] into an instance of `T:` [`Decode`]. Can reuse
187    /// the buffer's allocations.
188    ///
189    /// **Warning:** The format is subject to change between versions.
190    pub fn decode<T>(&mut self, bytes: &[u8]) -> Result<T>
191    where
192        T: Decode,
193    {
194        code::decode_internal(&mut self.0, bytes)
195    }
196}
197
198/// Decoding / (De)serialization errors.
199///
200/// # Debug mode
201///
202/// In debug mode, the error contains a reason.
203///
204/// # Release mode
205///
206/// In release mode, the error is a zero-sized type for efficiency.
207#[derive(Debug)]
208#[cfg_attr(test, derive(PartialEq))]
209pub struct Error(ErrorImpl);
210
211#[cfg(not(debug_assertions))]
212type ErrorImpl = ();
213
214#[cfg(debug_assertions)]
215type ErrorImpl = E;
216
217impl Error {
218    /// Replaces an invalid message. E.g. read_variant_index calls read_len but converts
219    /// `E::Invalid("length")` to `E::Invalid("variant index")`.
220    #[cfg(any(test, feature = "serde"))]
221    pub(crate) fn map_invalid(self, _s: &'static str) -> Self {
222        #[cfg(debug_assertions)]
223        return Self(match self.0 {
224            E::Invalid(_) => E::Invalid(_s),
225            _ => self.0,
226        });
227        #[cfg(not(debug_assertions))]
228        self
229    }
230
231    // Doesn't implement PartialEq because that would be part of the public api.
232    pub(crate) fn same(&self, other: &Self) -> bool {
233        self.0 == other.0
234    }
235}
236
237/// Inner error that can be converted to [`Error`] with [`E::e`].
238#[derive(Debug, PartialEq)]
239pub(crate) enum E {
240    #[allow(unused)] // Only used by serde feature.
241    Custom(String),
242    Eof,
243    ExpectedEof,
244    Invalid(&'static str),
245    #[allow(unused)] // Only used by serde feature.
246    NotSupported(&'static str),
247}
248
249impl E {
250    fn e(self) -> Error {
251        #[cfg(debug_assertions)]
252        return Error(self);
253        #[cfg(not(debug_assertions))]
254        Error(())
255    }
256}
257
258pub type Result<T> = std::result::Result<T, Error>;
259
260impl Display for Error {
261    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
262        #[cfg(debug_assertions)]
263        return Display::fmt(&self.0, f);
264        #[cfg(not(debug_assertions))]
265        f.write_str("bitcode error")
266    }
267}
268
269impl Display for E {
270    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
271        match self {
272            Self::Custom(s) => write!(f, "custom: {s}"),
273            Self::Eof => write!(f, "eof"),
274            Self::ExpectedEof => write!(f, "expected eof"),
275            Self::Invalid(s) => write!(f, "invalid {s}"),
276            Self::NotSupported(s) => write!(f, "{s} is not supported"),
277        }
278    }
279}
280
281impl std::error::Error for Error {}