1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
#![cfg_attr(test, feature(test))]
#![cfg_attr(doc, feature(doc_cfg))]
#![forbid(unsafe_code)]

//! Bitcode is a crate for encoding and decoding using a tinier
//! binary serialization strategy. You can easily go from having
//! an object in memory, quickly serialize it to bytes, and then
//! deserialize it back just as fast!
//!
//! The format is not necessarily stable between versions. If you want
//! a stable format, consider [bincode](https://docs.rs/bincode/latest/bincode/).
//!
//! ### Usage
//!
//! ```edition2021
//! // The object that we will encode.
//! let target: Vec<String> = vec!["a".to_owned(), "b".to_owned(), "c".to_owned()];
//!
//! let encoded: Vec<u8> = bitcode::encode(&target).unwrap();
//! let decoded: Vec<String> = bitcode::decode(&encoded).unwrap();
//! assert_eq!(target, decoded);
//! ```
//!
//! ### Advanced Usage
//!
//! Bitcode has several hints that can be applied.
//! Hints may have an effect on the encoded length.
//! Most importantly hints will never cause errors if they don't hold true.
//!
//! ```edition2021
//! // We mark enum variants that are more likely with a higher frequency.
//! // This allows bitcode to use shorter encodings for them.
//! #[derive(Copy, Clone, bitcode::Encode, bitcode::Decode)]
//! enum Fruit {
//!     #[bitcode_hint(frequency = 10)]
//!     Apple,
//!     #[bitcode_hint(frequency = 5)]
//!     Banana,
//!     // Unspecified frequencies are 1.
//!     Blueberry,
//!     Lime,
//!     Lychee,
//!     Watermelon,
//! }
//!
//! // A cart full of 16 apples takes 2 bytes to encode (1 bit per Apple).
//! let apple_cart: usize = bitcode::encode(&[Fruit::Apple; 16]).unwrap().len();
//! assert_eq!(apple_cart, 2);
//!
//! // A cart full of 16 bananas takes 4 bytes to encode (2 bits per Banana).
//! let banana_cart: usize = bitcode::encode(&[Fruit::Banana; 16]).unwrap().len();
//! assert_eq!(banana_cart, 4);
//!
//! // A cart full of 16 blueberries takes 8 bytes to encode (4 bits per Blueberry).
//! let blueberry_cart: usize = bitcode::encode(&[Fruit::Blueberry; 16]).unwrap().len();
//! assert_eq!(blueberry_cart, 8);
//! ```
//!
//! ```edition2021
//! // We expect most user ages to be in the interval [10, 100), so we specify that as the expected
//! // range. If we're right most of the time, users will take fewer bits to encode.
//! #[derive(bitcode::Encode, bitcode::Decode)]
//! struct User {
//!     #[bitcode_hint(expected_range = "10..100")]
//!     age: u32
//! }
//!
//! // A user with an age inside the expected range takes up to a byte to encode.
//! let expected_age: usize = bitcode::encode(&User { age: 42 }).unwrap().len();
//! assert_eq!(expected_age, 1);
//!
//! // A user with an age outside the expected range more than 4 bytes to encode.
//! let unexpected_age: usize = bitcode::encode(&User { age: 31415926 }).unwrap().len();
//! assert!(unexpected_age > 4);
//! ```
//!
//! ```edition2021
//! // We expect that most posts won't have that many views or likes, but some can. By using gamma
//! // encoding, posts with fewer views/likes will take fewer bits to encode.
//! #[derive(bitcode::Encode, bitcode::Decode)]
//! #[bitcode_hint(gamma)]
//! struct Post {
//!     views: u64,
//!     likes: u64,
//! }
//!
//! // An average post just takes 1 byte to encode.
//! let average_post = bitcode::encode(&Post {
//!     views: 4,
//!     likes: 1,
//! }).unwrap().len();
//! assert_eq!(average_post, 1);
//!
//! // A popular post takes 11 bytes to encode, luckily these posts are rare.
//! let popular_post = bitcode::encode(&Post {
//!     views: 27182818,
//!     likes: 161803,
//! }).unwrap().len();
//! assert_eq!(popular_post, 11)
//! ```

// Actually required see https://doc.rust-lang.org/beta/unstable-book/library-features/test.html
#[cfg(test)]
extern crate core;
#[cfg(test)]
extern crate test;

// Fixes derive macro in tests/doc tests.
extern crate self as bitcode;

pub use buffer::Buffer;
pub use code::{Decode, Encode};
use std::fmt::{self, Display, Formatter};

#[cfg(feature = "derive")]
pub use bitcode_derive::{Decode, Encode};

#[cfg(any(test, feature = "serde"))]
pub use crate::serde::{deserialize, serialize};

mod buffer;
mod code;
mod code_impls;
mod encoding;
mod guard;
mod nightly;
mod read;
mod register_buffer;
mod word;
mod word_buffer;
mod write;

#[cfg(feature = "derive")]
#[doc(hidden)]
pub mod __private;

#[cfg(any(test, feature = "serde"))]
mod serde;

#[cfg(all(test, not(miri)))]
mod benches;
#[cfg(test)]
mod bit_buffer;
#[cfg(all(test, debug_assertions))]
mod tests;

/// Encodes a `T:` [`Encode`] into a [`Vec<u8>`].
///
/// Won't ever return `Err` unless using `#[bitcode(with_serde)]`.
///
/// **Warning:** The format is subject to change between versions.
pub fn encode<T: ?Sized>(t: &T) -> Result<Vec<u8>>
where
    T: Encode,
{
    Ok(Buffer::new().encode(t)?.to_vec())
}

/// Decodes a [`&[u8]`][`prim@slice`] into an instance of `T:` [`Decode`].
///
/// **Warning:** The format is subject to change between versions.
pub fn decode<T>(bytes: &[u8]) -> Result<T>
where
    T: Decode,
{
    Buffer::new().decode(bytes)
}

impl Buffer {
    /// Encodes a `T:` [`Encode`] into a [`&[u8]`][`prim@slice`]. Can reuse the buffer's
    /// allocations.
    ///
    /// Won't ever return `Err` unless using `#[bitcode(with_serde)]`.
    ///
    /// Even if you call `to_vec` on the [`&[u8]`][`prim@slice`], it's still more efficient than
    /// [`encode`].
    ///
    /// **Warning:** The format is subject to change between versions.
    pub fn encode<T: ?Sized>(&mut self, t: &T) -> Result<&[u8]>
    where
        T: Encode,
    {
        code::encode_internal(&mut self.0, t)
    }

    /// Decodes a [`&[u8]`][`prim@slice`] into an instance of `T:` [`Decode`]. Can reuse
    /// the buffer's allocations.
    ///
    /// **Warning:** The format is subject to change between versions.
    pub fn decode<T>(&mut self, bytes: &[u8]) -> Result<T>
    where
        T: Decode,
    {
        code::decode_internal(&mut self.0, bytes)
    }
}

/// Decoding / (De)serialization errors.
///
/// # Debug mode
///
/// In debug mode, the error contains a reason.
///
/// # Release mode
///
/// In release mode, the error is a zero-sized type for efficiency.
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
pub struct Error(ErrorImpl);

#[cfg(not(debug_assertions))]
type ErrorImpl = ();

#[cfg(debug_assertions)]
type ErrorImpl = E;

impl Error {
    /// Replaces an invalid message. E.g. read_variant_index calls read_len but converts
    /// `E::Invalid("length")` to `E::Invalid("variant index")`.
    #[cfg(any(test, feature = "serde"))]
    pub(crate) fn map_invalid(self, _s: &'static str) -> Self {
        #[cfg(debug_assertions)]
        return Self(match self.0 {
            E::Invalid(_) => E::Invalid(_s),
            _ => self.0,
        });
        #[cfg(not(debug_assertions))]
        self
    }

    pub(crate) fn same(&self, other: &Self) -> bool {
        self.0 == other.0
    }
}

/// Inner error that can be converted to [`Error`] with [`E::e`].
#[derive(Debug, PartialEq)]
pub(crate) enum E {
    #[allow(unused)] // Only used by serde feature.
    Custom(String),
    Eof,
    ExpectedEof,
    Invalid(&'static str),
    #[allow(unused)] // Only used by serde feature.
    NotSupported(&'static str),
}

impl E {
    fn e(self) -> Error {
        #[cfg(debug_assertions)]
        return Error(self);
        #[cfg(not(debug_assertions))]
        Error(())
    }
}

type Result<T> = std::result::Result<T, Error>;

impl Display for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        #[cfg(debug_assertions)]
        return Display::fmt(&self.0, f);
        #[cfg(not(debug_assertions))]
        f.write_str("bitcode error")
    }
}

impl Display for E {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::Custom(s) => write!(f, "custom: {s}"),
            Self::Eof => write!(f, "eof"),
            Self::ExpectedEof => write!(f, "expected eof"),
            Self::Invalid(s) => write!(f, "invalid {s}"),
            Self::NotSupported(s) => write!(f, "{s} is not supported"),
        }
    }
}

impl std::error::Error for Error {}