object_rainbow/impls/
option.rs

1use std::ops::Add;
2
3use generic_array::{ArrayLength, GenericArray};
4use typenum::{B0, B1, Bit};
5
6use crate::*;
7
8impl<T: ToOutput + MaybeHasNiche<MnArray: MnArray<MaybeNiche = N>>, N: Niche<NeedsTag = B>, B: Bit>
9    ToOutput for Option<T>
10{
11    fn to_output(&self, output: &mut dyn Output) {
12        match self {
13            Some(value) => {
14                if B::BOOL {
15                    output.write(&[0]);
16                }
17                value.to_output(output);
18            }
19            None => {
20                if B::BOOL {
21                    output.write(&[1]);
22                }
23                output.write(N::niche().as_slice());
24            }
25        }
26    }
27}
28
29impl<T: Topological> Topological for Option<T> {
30    fn accept_points(&self, visitor: &mut impl PointVisitor) {
31        self.iter_accept_points(visitor);
32    }
33}
34
35impl<T: Tagged> Tagged for Option<T> {
36    const TAGS: Tags = T::TAGS;
37}
38
39impl<
40    T: MaybeHasNiche<MnArray: MnArray<MaybeNiche: Niche<NeedsTag = B, N: Add<B, Output = N>>>>,
41    B: Bit,
42    N: Unsigned,
43> Size for Option<T>
44{
45    type Size = N;
46}
47
48pub struct OptionNiche<N>(N);
49
50impl<N: ArrayLength> Niche for OptionNiche<N> {
51    type NeedsTag = B0;
52    type N = N;
53    fn niche() -> GenericArray<u8, Self::N> {
54        let mut niche = GenericArray::default();
55        niche[0] = 2;
56        niche
57    }
58}
59
60pub trait OptionNicheWrapper: Bit {
61    type Wrap<N: ArrayLength>: MaybeNiche;
62}
63
64impl OptionNicheWrapper for B0 {
65    type Wrap<N: ArrayLength> = NoNiche<ZeroNoNiche<N>>;
66}
67
68impl OptionNicheWrapper for B1 {
69    type Wrap<N: ArrayLength> = SomeNiche<OptionNiche<N>>;
70}
71
72impl<
73    T: MaybeHasNiche<
74        MnArray: MnArray<MaybeNiche: Niche<NeedsTag = B, N: Add<B, Output: ArrayLength>>>,
75    >,
76    B: OptionNicheWrapper,
77> MaybeHasNiche for Option<T>
78{
79    type MnArray = B::Wrap<<Self as Size>::Size>;
80}
81
82impl<
83    T: ParseInline<I> + MaybeHasNiche<MnArray: MnArray<MaybeNiche = N>>,
84    N: Niche<NeedsTag = B>,
85    B: Bit,
86    I: ParseInput,
87> Parse<I> for Option<T>
88{
89    fn parse(input: I) -> crate::Result<Self> {
90        ParseInline::parse_as_inline(input)
91    }
92}
93
94impl<
95    T: ParseInline<I> + MaybeHasNiche<MnArray: MnArray<MaybeNiche = N>>,
96    N: Niche<NeedsTag = B>,
97    B: Bit,
98    I: ParseInput,
99> ParseInline<I> for Option<T>
100{
101    fn parse_inline(input: &mut I) -> crate::Result<Self> {
102        if B::BOOL {
103            if input.parse_inline()? {
104                Ok(None)
105            } else {
106                Ok(Some(input.parse_inline()?))
107            }
108        } else {
109            input.parse_compare(N::N::USIZE, &N::niche())
110        }
111    }
112}
113
114impl<T: Inline + MaybeHasNiche<MnArray: MnArray<MaybeNiche = N>>, N: Niche<NeedsTag = B>, B: Bit>
115    Object for Option<T>
116{
117}
118
119impl<T: Inline + MaybeHasNiche<MnArray: MnArray<MaybeNiche = N>>, N: Niche<NeedsTag = B>, B: Bit>
120    Inline for Option<T>
121{
122}
123
124impl<
125    T: ReflessInline + MaybeHasNiche<MnArray: MnArray<MaybeNiche = N>>,
126    N: Niche<NeedsTag = B>,
127    B: Bit,
128> ReflessObject for Option<T>
129{
130}
131
132impl<
133    T: ReflessInline + MaybeHasNiche<MnArray: MnArray<MaybeNiche = N>>,
134    N: Niche<NeedsTag = B>,
135    B: Bit,
136> ReflessInline for Option<T>
137{
138}
139
140impl Equivalent<bool> for Option<()> {
141    fn into_equivalent(self) -> bool {
142        self.is_none()
143    }
144
145    fn from_equivalent(object: bool) -> Self {
146        (!object).then_some(())
147    }
148}
149
150#[test]
151fn equivalent() {
152    assert_eq!(
153        false.output::<Vec<u8>>(),
154        Option::from_equivalent(false).output::<Vec<u8>>(),
155    );
156    assert_eq!(
157        true.output::<Vec<u8>>(),
158        Option::from_equivalent(true).output::<Vec<u8>>(),
159    );
160}