bin_proto/impls/
option.rs

1use bitstream_io::{BitRead, BitWrite, Endianness};
2
3use crate::{BitDecode, BitEncode, Error, Result, Untagged};
4
5impl<Tag, Ctx, T> BitDecode<Ctx, crate::Tag<Tag>> for Option<T>
6where
7    T: BitDecode<Ctx>,
8    Tag: TryInto<bool>,
9{
10    fn decode<R, E>(read: &mut R, ctx: &mut Ctx, tag: crate::Tag<Tag>) -> Result<Self>
11    where
12        R: BitRead,
13        E: Endianness,
14    {
15        if tag.0.try_into().map_err(|_| Error::TagConvert)? {
16            let value = T::decode::<_, E>(read, ctx, ())?;
17            Ok(Some(value))
18        } else {
19            Ok(None)
20        }
21    }
22}
23
24impl<Ctx, T> BitEncode<Ctx, Untagged> for Option<T>
25where
26    T: BitEncode<Ctx>,
27{
28    fn encode<W, E>(&self, write: &mut W, ctx: &mut Ctx, _: Untagged) -> Result<()>
29    where
30        W: BitWrite,
31        E: Endianness,
32    {
33        if let Some(ref value) = *self {
34            value.encode::<_, E>(write, ctx, ())?;
35        }
36        Ok(())
37    }
38}
39
40#[cfg(feature = "prepend-tags")]
41impl<Ctx, T> BitEncode<Ctx> for Option<T>
42where
43    T: BitEncode<Ctx>,
44{
45    fn encode<W, E>(&self, write: &mut W, ctx: &mut Ctx, (): ()) -> Result<()>
46    where
47        W: BitWrite,
48        E: Endianness,
49    {
50        self.is_some().encode::<_, E>(write, ctx, ())?;
51        self.encode::<_, E>(write, ctx, Untagged)
52    }
53}
54
55#[cfg(feature = "prepend-tags")]
56impl<Ctx, T> BitDecode<Ctx> for Option<T>
57where
58    T: BitDecode<Ctx>,
59{
60    fn decode<R, E>(read: &mut R, ctx: &mut Ctx, (): ()) -> Result<Self>
61    where
62        R: BitRead,
63        E: Endianness,
64    {
65        let tag = bool::decode::<_, E>(read, ctx, ())?;
66        Self::decode::<_, E>(read, ctx, crate::Tag(tag))
67    }
68}
69
70#[cfg(test)]
71mod none {
72    use crate::Tag;
73
74    use super::*;
75
76    test_codec!(Option<u8>| Untagged, Tag(false); None => []);
77}
78
79#[cfg(test)]
80mod some {
81    use crate::Tag;
82
83    use super::*;
84
85    test_codec!(Option<u8>| Untagged, Tag(true); Some(1) => [0x01]);
86}
87
88#[cfg(feature = "prepend-tags")]
89test_roundtrip!(Option::<i32>);