tree_buf/internal/types/
nullable.rs

1use crate::prelude::*;
2
3#[cfg(feature = "encode")]
4impl<T: Encodable> Encodable for Option<T> {
5    type EncoderArray = NullableEncoder<T::EncoderArray>;
6    fn encode_root<O: EncodeOptions>(&self, stream: &mut EncoderStream<'_, O>) -> RootTypeId {
7        if let Some(value) = self {
8            T::encode_root(value, stream)
9        } else {
10            RootTypeId::Void
11        }
12    }
13}
14
15#[cfg(feature = "decode")]
16impl<T: Decodable> Decodable for Option<T> {
17    type DecoderArray = Option<NullableDecoder<T::DecoderArray>>;
18    fn decode(sticks: DynRootBranch<'_>, options: &impl DecodeOptions) -> DecodeResult<Self> {
19        profile_method!(decode);
20        match sticks {
21            DynRootBranch::Void => Ok(None),
22            _ => Ok(Some(T::decode(sticks, options)?)),
23        }
24    }
25}
26
27#[cfg(feature = "encode")]
28#[derive(Default)]
29pub struct NullableEncoder<V> {
30    opt: <bool as Encodable>::EncoderArray,
31    value: Option<V>,
32}
33
34#[cfg(feature = "encode")]
35impl<T: Encodable> EncoderArray<Option<T>> for NullableEncoder<T::EncoderArray> {
36    fn buffer_one<'a, 'b: 'a>(&'a mut self, value: &'b Option<T>) {
37        self.opt.buffer_one(&value.is_some());
38        if let Some(value) = value {
39            self.value.get_or_insert_with(T::EncoderArray::default).buffer_one(value);
40        }
41    }
42    fn flush<O: EncodeOptions>(self, stream: &mut EncoderStream<'_, O>) -> ArrayTypeId {
43        profile_method!(flush);
44        let Self { opt, value } = self;
45        if let Some(value) = value {
46            stream.encode_with_id(|stream| opt.flush(stream));
47            stream.encode_with_id(|stream| value.flush(stream));
48            ArrayTypeId::Nullable
49        } else {
50            ArrayTypeId::Void
51        }
52    }
53}
54
55#[cfg(feature = "decode")]
56pub struct NullableDecoder<T> {
57    opts: <bool as Decodable>::DecoderArray,
58    values: T,
59}
60
61#[cfg(feature = "decode")]
62impl<T: DecoderArray> DecoderArray for Option<NullableDecoder<T>> {
63    type Decode = Option<T::Decode>;
64    type Error = T::Error;
65    fn new(sticks: DynArrayBranch<'_>, options: &impl DecodeOptions) -> DecodeResult<Self> {
66        profile_method!(new);
67
68        match sticks {
69            DynArrayBranch::Nullable { opt, values } => {
70                let (opts, values) = parallel(|| <bool as Decodable>::DecoderArray::new(*opt, options), || T::new(*values, options), options);
71                let opts = opts?;
72                let values = values?;
73                Ok(Some(NullableDecoder { opts, values }))
74            }
75            DynArrayBranch::Void => Ok(None),
76            _ => Err(DecodeError::SchemaMismatch),
77        }
78    }
79    fn decode_next(&mut self) -> Result<Self::Decode, Self::Error> {
80        Ok(if let Some(inner) = self {
81            if inner.opts.decode_next_infallible() {
82                Some(inner.values.decode_next()?)
83            } else {
84                None
85            }
86        } else {
87            None
88        })
89    }
90}