bitcode/
lib.rs

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
#![allow(clippy::items_after_test_module, clippy::blocks_in_if_conditions)]
#![warn(clippy::semicolon_if_nothing_returned)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![cfg_attr(test, feature(test))]
#![cfg_attr(not(feature = "std"), no_std)]
#![doc = include_str!("../README.md")]

#[macro_use]
extern crate alloc;

// Fixes derive macro in tests/doc tests.
#[cfg(test)]
extern crate self as bitcode;
#[cfg(test)]
extern crate test;

mod bool;
mod buffer;
mod coder;
mod consume;
mod derive;
mod error;
mod ext;
mod f32;
mod fast;
mod histogram;
mod int;
mod length;
mod nightly;
mod pack;
mod pack_ints;
mod str;
mod u8_char;

pub use crate::buffer::Buffer;
pub use crate::derive::*;
pub use crate::error::Error;

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

#[cfg(feature = "serde")]
mod serde;
#[cfg(feature = "serde")]
pub use crate::serde::*;

#[cfg(test)]
mod benches;
#[cfg(test)]
mod benches_borrowed;

#[cfg(test)]
use alloc::vec::Vec;

#[cfg(test)]
fn random_data<T>(n: usize) -> Vec<T>
where
    rand::distributions::Standard: rand::distributions::Distribution<T>,
{
    let n = limit_bench_miri(n);
    use rand::prelude::*;
    let mut rng = rand_chacha::ChaCha20Rng::from_seed(Default::default());
    (0..n).map(|_| rng.gen()).collect()
}
#[cfg(test)]
fn limit_bench_miri(n: usize) -> usize {
    if cfg!(miri) {
        (n / 100).max(10).min(1000)
    } else {
        n
    }
}
#[cfg(test)]
macro_rules! bench_encode_decode {
    ($($name:ident: $t:ty),+) => {
        paste::paste! {
            $(
                #[bench]
                fn [<bench_ $name _encode>](b: &mut test::Bencher) {
                    let data: $t = bench_data();
                    let mut buffer = crate::Buffer::default();
                    b.iter(|| {
                        test::black_box(buffer.encode(test::black_box(&data)));
                    })
                }

                #[bench]
                fn [<bench_ $name _decode>](b: &mut test::Bencher) {
                    let data: $t = bench_data();
                    let encoded = crate::encode(&data);
                    let mut buffer = crate::Buffer::default();

                    // Help type inference.
                    fn check_eof<'a, T: crate::Decode<'a>>(_: &T, incomplete: &'a [u8], padded: &'a [u8]) {
                        let Err(e) = crate::decode::<T>(incomplete) else {
                            panic!("no eof");
                        };
                        assert_eq!(e, crate::error::error("EOF"));

                        let Err(e) = crate::decode::<T>(&padded) else {
                            panic!("no expected eof");
                        };
                        assert_eq!(e, crate::error::error("Expected EOF"));
                    }
                    {
                        let mut padded = encoded.to_vec();
                        padded.push(0);
                        check_eof(&data, &encoded[..encoded.len() - 1], &padded);
                    }

                    let mut f = || {
                        #[cfg(miri)] // Make sure dangling pointers aren't read due to Buffer.
                        let encoded = encoded.clone();

                        let decoded: $t = buffer.decode(test::black_box(&encoded)).unwrap();
                        debug_assert_eq!(data, decoded);
                        test::black_box(decoded);
                    };

                    // Make sure f gets called at least twice (b.iter() calls once with miri).
                    if cfg!(miri) {
                        f();
                        f();
                    } else {
                        b.iter(f);
                    }
                }
            )+
        }
    }
}
#[cfg(test)]
pub(crate) use bench_encode_decode;