bitcode/coder.rs
1use crate::fast::{SliceImpl, Unaligned, VecImpl};
2use alloc::vec::Vec;
3use core::mem::MaybeUninit;
4use core::num::NonZeroUsize;
5
6pub type Result<T> = core::result::Result<T, crate::Error>;
7
8/// TODO pick different name because it aliases with [`crate::buffer::Buffer`].
9pub trait Buffer {
10 /// Convenience function for `collect_into`.
11 fn collect(&mut self) -> Vec<u8> {
12 let mut vec = vec![];
13 self.collect_into(&mut vec);
14 vec
15 }
16
17 /// Collects the buffer into a single `Vec<u8>`. This clears the buffer.
18 fn collect_into(&mut self, out: &mut Vec<u8>);
19
20 /// Reserves space for `additional` calls to `self.encode()`. Takes a [`NonZeroUsize`] to avoid
21 /// useless calls.
22 fn reserve(&mut self, additional: NonZeroUsize);
23}
24
25/// Iterators passed to [`Encoder::encode_vectored`] must have length <= this.
26pub const MAX_VECTORED_CHUNK: usize = 64;
27
28pub trait Encoder<T: ?Sized>: Buffer + Default + Send + Sync {
29 /// Returns a `&mut VecImpl<T>` if `T` is a type that can be encoded by copying.
30 #[inline(always)]
31 fn as_primitive(&mut self) -> Option<&mut VecImpl<T>>
32 where
33 T: Sized,
34 {
35 None
36 }
37
38 /// Encodes a single value. Can't error since anything can be encoded.
39 /// # Safety
40 /// Can only encode `self.reserve(additional)` items.
41 fn encode(&mut self, t: &T);
42
43 /// Calls [`Self::encode`] once for every item in `i`. Only use this with **FAST** iterators
44 /// since the iterator may be iterated multiple times.
45 /// # Safety
46 /// Can only encode `self.reserve(additional)` items.
47 ///
48 /// `i` must have an accurate `i.size_hint().1.unwrap()` that != 0 and is <= `MAX_VECTORED_CHUNK`.
49 /// Currently, the non-map iterators that uphold these requirements are:
50 /// - vec.rs
51 /// - option.rs
52 fn encode_vectored<'a>(&mut self, i: impl Iterator<Item = &'a T> + Clone)
53 where
54 T: 'a,
55 {
56 for t in i {
57 self.encode(t);
58 }
59 }
60}
61
62pub trait View<'a> {
63 /// Reads `length` items out of `input`, overwriting the view. If it returns `Ok`,
64 /// `self.decode()` can be called called `length` times.
65 fn populate(&mut self, input: &mut &'a [u8], length: usize) -> Result<()>;
66}
67
68/// One of [`Decoder::decode`] and [`Decoder::decode_in_place`] must be implemented or calling
69/// either one will result in infinite recursion and a stack overflow.
70pub trait Decoder<'a, T>: View<'a> + Default + Send + Sync {
71 /// Returns a `&mut SliceImpl<Unaligned<T>>` if `T` is a type that can be decoded by copying.
72 /// Uses `Unaligned<T>` so `IntDecoder` can borrow from input `[u8]`.
73 #[inline(always)]
74 fn as_primitive(&mut self) -> Option<&mut SliceImpl<Unaligned<T>>> {
75 None
76 }
77
78 /// Decodes a single value. Can't error since `View::populate` has already validated the input.
79 /// Prefer decode for primitives (since it's simpler) and decode_in_place for array/struct/tuple.
80 /// # Safety
81 /// Can only decode `self.populate(_, length)` items.
82 #[inline(always)]
83 fn decode(&mut self) -> T {
84 let mut out = MaybeUninit::uninit();
85 self.decode_in_place(&mut out);
86 unsafe { out.assume_init() }
87 }
88
89 /// [`Self::decode`] without redundant copies. Only downside is panics will leak the value.
90 /// The only panics out of our control are Hash/Ord/PartialEq for BinaryHeap/BTreeMap/HashMap.
91 /// E.g. if a user PartialEq panics we will leak some memory which is an acceptable tradeoff.
92 /// # Safety
93 /// Can only decode `self.populate(_, length)` items.
94 #[inline(always)]
95 fn decode_in_place(&mut self, out: &mut MaybeUninit<T>) {
96 out.write(self.decode());
97 }
98}
99
100#[doc(hidden)]
101#[macro_export]
102macro_rules! __private_uninit_field {
103 ($uninit:ident.$field:tt:$field_ty:ty) => {
104 unsafe {
105 &mut *(::core::ptr::addr_of_mut!((*$uninit.as_mut_ptr()).$field)
106 as *mut ::core::mem::MaybeUninit<$field_ty>)
107 }
108 };
109}
110pub use __private_uninit_field as uninit_field;