object_rainbow/impls/
option.rs1use 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}