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;