bitcode/
lib.rs

1#![allow(clippy::items_after_test_module, clippy::blocks_in_if_conditions)]
2#![warn(clippy::semicolon_if_nothing_returned)]
3#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
4#![cfg_attr(test, feature(test))]
5#![cfg_attr(not(feature = "std"), no_std)]
6#![doc = include_str!("../README.md")]
7
8#[macro_use]
9extern crate alloc;
10
11// Fixes derive macro in tests/doc tests.
12#[cfg(test)]
13extern crate self as bitcode;
14#[cfg(test)]
15extern crate test;
16
17mod bool;
18mod buffer;
19mod coder;
20mod consume;
21mod derive;
22mod error;
23mod ext;
24mod f32;
25mod fast;
26mod histogram;
27mod int;
28mod length;
29mod nightly;
30mod pack;
31mod pack_ints;
32mod str;
33mod u8_char;
34
35pub use crate::buffer::Buffer;
36pub use crate::derive::*;
37pub use crate::error::Error;
38
39#[cfg(feature = "derive")]
40pub use bitcode_derive::{Decode, Encode};
41
42#[cfg(feature = "serde")]
43mod serde;
44#[cfg(feature = "serde")]
45pub use crate::serde::*;
46
47#[cfg(test)]
48mod benches;
49#[cfg(test)]
50mod benches_borrowed;
51
52#[cfg(test)]
53use alloc::vec::Vec;
54
55#[cfg(test)]
56fn random_data<T>(n: usize) -> Vec<T>
57where
58    rand::distributions::Standard: rand::distributions::Distribution<T>,
59{
60    let n = limit_bench_miri(n);
61    use rand::prelude::*;
62    let mut rng = rand_chacha::ChaCha20Rng::from_seed(Default::default());
63    (0..n).map(|_| rng.gen()).collect()
64}
65#[cfg(test)]
66fn limit_bench_miri(n: usize) -> usize {
67    if cfg!(miri) {
68        (n / 100).max(10).min(1000)
69    } else {
70        n
71    }
72}
73#[cfg(test)]
74macro_rules! bench_encode_decode {
75    ($($name:ident: $t:ty),+) => {
76        paste::paste! {
77            $(
78                #[bench]
79                fn [<bench_ $name _encode>](b: &mut test::Bencher) {
80                    let data: $t = bench_data();
81                    let mut buffer = crate::Buffer::default();
82                    b.iter(|| {
83                        test::black_box(buffer.encode(test::black_box(&data)));
84                    })
85                }
86
87                #[bench]
88                fn [<bench_ $name _decode>](b: &mut test::Bencher) {
89                    let data: $t = bench_data();
90                    let encoded = crate::encode(&data);
91                    let mut buffer = crate::Buffer::default();
92
93                    // Help type inference.
94                    fn check_eof<'a, T: crate::Decode<'a>>(_: &T, incomplete: &'a [u8], padded: &'a [u8]) {
95                        let Err(e) = crate::decode::<T>(incomplete) else {
96                            panic!("no eof");
97                        };
98                        assert_eq!(e, crate::error::error("EOF"));
99
100                        let Err(e) = crate::decode::<T>(&padded) else {
101                            panic!("no expected eof");
102                        };
103                        assert_eq!(e, crate::error::error("Expected EOF"));
104                    }
105                    {
106                        let mut padded = encoded.to_vec();
107                        padded.push(0);
108                        check_eof(&data, &encoded[..encoded.len() - 1], &padded);
109                    }
110
111                    let mut f = || {
112                        #[cfg(miri)] // Make sure dangling pointers aren't read due to Buffer.
113                        let encoded = encoded.clone();
114
115                        let decoded: $t = buffer.decode(test::black_box(&encoded)).unwrap();
116                        debug_assert_eq!(data, decoded);
117                        test::black_box(decoded);
118                    };
119
120                    // Make sure f gets called at least twice (b.iter() calls once with miri).
121                    if cfg!(miri) {
122                        f();
123                        f();
124                    } else {
125                        b.iter(f);
126                    }
127                }
128            )+
129        }
130    }
131}
132#[cfg(test)]
133pub(crate) use bench_encode_decode;