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 {}