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#[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 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)] 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 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;