tree_buf/internal/
encoder_decoder.rs

1use crate::prelude::*;
2
3// REMEMBER: The reason this is not a trait is because of partial borrows.
4// If this is a trait, you can't borrow both bytes and lens at the same time.
5#[cfg(feature = "encode")]
6pub struct EncoderStream<'a, O> {
7    pub bytes: &'a mut Vec<u8>,
8    pub lens: &'a mut Vec<usize>,
9    pub options: &'a O,
10}
11
12#[cfg(feature = "encode")]
13impl<'a, O: EncodeOptions> EncoderStream<'a, O> {
14    pub fn new(bytes: &'a mut Vec<u8>, lens: &'a mut Vec<usize>, options: &'a O) -> Self {
15        Self { bytes, lens, options }
16    }
17
18    pub fn encode_with_id<T: TypeId>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
19        let type_index = self.bytes.len();
20        self.bytes.push(0);
21        let id = f(self);
22        debug_assert!(id != T::void() || (self.bytes.len() == type_index + 1), "Expecting Void to encode no bytes to stream");
23        self.bytes[type_index] = id.into();
24        id
25    }
26    pub fn encode_with_len<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
27        let start = self.bytes.len();
28        let result = f(self);
29        self.lens.push(self.bytes.len() - start);
30        result
31    }
32}
33
34#[cfg(feature = "encode")]
35pub trait Encodable: Sized {
36    type EncoderArray: EncoderArray<Self>;
37    // At the root level, there is no need to buffer/flush, just encode. By not buffering, we may
38    // significantly decrease total memory usage when there are multiple arrays at the root level,
39    // by not requiring that both be fully buffered simultaneously.
40    #[must_use]
41    fn encode_root<O: EncodeOptions>(&self, stream: &mut EncoderStream<'_, O>) -> RootTypeId;
42}
43
44#[cfg(feature = "decode")]
45pub trait Decodable: Sized {
46    type DecoderArray: DecoderArray<Decode = Self>;
47    fn decode(sticks: DynRootBranch<'_>, options: &impl DecodeOptions) -> DecodeResult<Self>;
48}
49
50// TODO: Introduce a separate "Scratch" type to make eg: EncoderArray re-usable.
51// The scratch type would be passed to encode, so it needs to be for Encodable (root)
52// Since not all root types have array children, some of these structs will be empty.
53// To some degree it is possible to know about re-use for fields of the same type, reducing
54// allocations further.
55
56#[cfg(feature = "encode")]
57pub trait EncoderArray<T>: Default {
58    fn buffer_one<'a, 'b: 'a>(&'a mut self, value: &'b T);
59    fn buffer_many<'a, 'b: 'a>(&'a mut self, values: &'b [T]) {
60        profile_method!(buffer_many);
61        for elem in values {
62            self.buffer_one(elem);
63        }
64    }
65    fn encode_all<O: EncodeOptions>(values: &[T], stream: &mut EncoderStream<'_, O>) -> ArrayTypeId {
66        profile_method!(encode_all);
67        let mut s = Self::default();
68        s.buffer_many(values);
69        s.flush(stream)
70    }
71    fn flush<O: EncodeOptions>(self, stream: &mut EncoderStream<'_, O>) -> ArrayTypeId;
72}
73
74pub trait PrimitiveEncoderArray<T>: EncoderArray<T> {
75    fn fast_size_for_all<O: EncodeOptions>(_values: &[T], _options: &O) -> usize;
76}
77
78#[cfg(feature = "decode")]
79pub trait DecoderArray: Sized + Send {
80    type Error: CoercibleWith<DecodeError> + CoercibleWith<Never>;
81    type Decode;
82    // TODO: It would be nice to be able to keep reference to the original byte array, especially for decoding strings.
83    // I think that may require GAT though the way things are setup so come back to this later.
84    fn new(sticks: DynArrayBranch<'_>, options: &impl DecodeOptions) -> DecodeResult<Self>;
85    fn decode_next(&mut self) -> Result<Self::Decode, Self::Error>;
86}
87
88pub trait InfallibleDecoderArray: Sized {
89    type Decode;
90    /// This isn't actually infallable, it's just named this to not conflict.
91    fn new_infallible(sticks: DynArrayBranch<'_>, options: &impl DecodeOptions) -> DecodeResult<Self>;
92    fn decode_next_infallible(&mut self) -> Self::Decode;
93}
94
95/// This trait exists to first reduce a little bit of boilerplate for the common
96/// case of not having fallibility, but also to automatically inline at least the Ok
97/// wrapping portion of the code to aid the optimizer in knowing that the Error path
98/// is impossible. Putting the inline here instead of on a decode_next of a DecoderArray
99/// implementation allows for not necessarily inlining what may be a larger method.
100/// It may not be necessary, but why not.
101impl<T: InfallibleDecoderArray + Send> DecoderArray for T {
102    type Decode = <Self as InfallibleDecoderArray>::Decode;
103    type Error = Never;
104
105    #[inline(always)]
106    fn new(sticks: DynArrayBranch<'_>, options: &impl DecodeOptions) -> DecodeResult<Self> {
107        InfallibleDecoderArray::new_infallible(sticks, options)
108    }
109
110    #[inline(always)]
111    fn decode_next(&mut self) -> Result<Self::Decode, Self::Error> {
112        Ok(InfallibleDecoderArray::decode_next_infallible(self))
113    }
114}