1use core::{marker::Destruct, ops::Try};
2
3use array_trait::length::{self, LengthValue};
4
5use crate::{AsBulk, Bulk, InplaceBulk, IntoBulk, RandomAccessBulk, SplitBulk};
6
7pub mod option
8{
9 use array_trait::length::Length;
10
11 use crate::{CollectionAdapter, FromBulk, StaticBulk};
12
13 pub struct IntoBulk<T>
14 {
15 pub(super) option: Option<T>
16 }
17
18 pub struct Bulk<'a, T>
19 {
20 pub(super) option: &'a Option<T>
21 }
22
23 pub struct BulkMut<'a, T>
24 {
25 pub(super) option: &'a mut Option<T>
26 }
27
28 pub trait MaybeLength = Length<Max<[(); 1]> = [(); 1], Elem = ()>;
29
30 pub trait Maybe: CollectionAdapter<Elem = Self::Item> + crate::IntoBulk<IntoBulk: MaybeBulk> + FromBulk<Self>
31 {
32 type Not: Maybe<Not = Self>;
33 }
34 impl<T> Maybe for Option<T>
35 {
36 type Not = Option<T>;
37 }
38 impl<T> Maybe for [T; 0]
39 {
40 type Not = [T; 1];
41 }
42 impl<T> Maybe for [T; 1]
43 {
44 type Not = [T; 0];
45 }
46
47 pub const trait MaybeBulk: ~const crate::Bulk<MaxLength: MaybeLength, MinLength: MaybeLength>
48 {
49 type Maybe: Maybe;
50 }
51
52 impl<A, T> const MaybeBulk for T
53 where
54 T: ~const crate::Bulk<Item = A, MaxLength: MaybeLength, MinLength: MaybeLength>
55 {
56 default type Maybe = Option<A>;
57 }
58 impl<A, T, const N: usize> const MaybeBulk for T
59 where
60 T: ~const crate::Bulk<Item = A> + StaticBulk<Array<()> = [(); N], Array<A> = [A; N]>,
61 [A; N]: Maybe<Item = A>,
62 [(); N]: MaybeLength
63 {
64 type Maybe = [A; N];
65 }
66}
67
68macro_rules! impl_option {
69 (
70 impl $bulk:ident<$($a:lifetime,)? $t:ident>; for $item:ty; in $option:ty; $($mut:ident)?
71 {
72 fn first($self_first:ident) -> _
73 $first:block
74 }
75 ) => {
76 impl<$($a,)? $t> IntoIterator for option::$bulk<$($a,)? $t>
77 {
78 type IntoIter = <$option as IntoIterator>::IntoIter;
79 type Item = $item;
80
81 fn into_iter(self) -> Self::IntoIter
82 {
83 self.option.into_iter()
84 }
85 }
86 impl<$($a,)? $t> const IntoBulk for $option
87 {
88 type IntoBulk = option::$bulk<$($a,)? $t>;
89
90 fn into_bulk(self) -> Self::IntoBulk
91 {
92 option::$bulk {
93 option: self
94 }
95 }
96 }
97 impl<$($a,)? $t> const Bulk for option::$bulk<$($a,)? $t>
98 {
99 type MinLength = [(); 0];
100 type MaxLength = [(); 1];
101
102 fn len(&self) -> usize
103 {
104 self.option.is_some() as usize
105 }
106 fn is_empty(&self) -> bool
107 {
108 self.option.is_none()
109 }
110
111 fn for_each<F>(self, mut f: F)
112 where
113 Self: Sized,
114 F: ~const FnMut(Self::Item) + ~const Destruct
115 {
116 if let Some(x) = self.option
117 {
118 f(x)
119 }
120 }
121 fn try_for_each<F, R>(self, mut f: F) -> R
122 where
123 Self: Sized,
124 Self::Item: ~const Destruct,
125 F: ~const FnMut(Self::Item) -> R + ~const Destruct,
126 R: ~const Try<Output = (), Residual: ~const Destruct>
127 {
128 if let Some(x) = self.option
129 {
130 f(x)?
131 }
132 R::from_output(())
133 }
134
135 fn first($self_first) -> Option<Self::Item>
136 where
137 Self::Item: ~const Destruct,
138 Self: Sized
139 $first
140 fn last(self) -> Option<Self::Item>
141 where
142 Self::Item: ~const Destruct,
143 Self: Sized
144 {
145 self.first()
146 }
147 fn nth<L>(self, n: L) -> Option<Self::Item>
148 where
149 Self: Sized,
150 Self::Item: ~const Destruct,
151 L: LengthValue
152 {
153 if length::value::len(n) == 0
154 {
155 self.first()
156 }
157 else
158 {
159 None
160 }
161 }
162
163 fn reduce<F>(self, _f: F) -> Option<Self::Item>
164 where
165 Self: Sized,
166 Self::Item: ~const Destruct,
167 F: ~const FnMut(Self::Item, Self::Item) -> Self::Item + ~const Destruct
168 {
169 self.first()
170 }
171 }
172 impl<$($a,)? T> RandomAccessBulk for option::$bulk<$($a,)? $t>
173 {
174 type ItemPointee = T;
175 type EachRef<'b> = option::Bulk<'b, T>
176 where
177 Self::ItemPointee: 'b,
178 Self: 'b;
179
180 fn each_ref<'b>(bulk: &'b Self) -> Self::EachRef<'b>
181 where
182 Self::ItemPointee: 'b,
183 Self: 'b
184 {
185 (&bulk.option as &Option<T>).bulk()
186 }
187 }
188 impl_option!(@extra impl $bulk<$($a,)? $t>; for $item; in $option; $($mut)?);
189 };
190 (
191 @extra impl $bulk:ident<$($a:lifetime,)? $t:ident>; for $item:ty; in $option:ty; $mut:ident
192 ) => {
193 impl<$($a,)? T> InplaceBulk for option::$bulk<$($a,)? T>
194 {
195 type EachMut<'b> = option::BulkMut<'b, T>
196 where
197 Self::ItemPointee: 'b,
198 Self: 'b;
199
200 fn each_mut<'b>(bulk: &'b mut Self) -> Self::EachMut<'b>
201 where
202 Self::ItemPointee: 'b,
203 Self: 'b
204 {
205 (&mut bulk.option as &mut Option<T>).bulk_mut()
206 }
207 }
208 };
209 (
210 @extra impl $bulk:ident<$($a:lifetime,)? $t:ident>; for $item:ty; in $option:ty;
211 ) => {
212
213 };
214}
215impl<T, L> const SplitBulk<L> for option::IntoBulk<T>
216where
217 L: LengthValue
218{
219 type Left = Self;
220 type Right = Self;
221
222 fn split_at(bulk: Self, n: L) -> (Self::Left, Self::Right)
223 where
224 Self: Sized
225 {
226 let empty = Self {
227 option: None
228 };
229
230 if length::value::eq(n, [(); 0])
231 {
232 (empty, bulk)
233 }
234 else
235 {
236 (bulk, empty)
237 }
238 }
239}
240impl_option!(
241 impl IntoBulk<T>; for T; in Option<T>; mut
242 {
243 fn first(self) -> _
244 {
245 self.option
246 }
247 }
248);
249impl_option!(
250 impl Bulk<'a, T>; for &'a T; in &'a Option<T>;
251 {
252 fn first(self) -> _
253 {
254 self.option.as_ref()
255 }
256 }
257);
258impl_option!(
259 impl BulkMut<'a, T>; for &'a mut T; in &'a mut Option<T>; mut
260 {
261 fn first(self) -> _
262 {
263 self.option.as_mut()
264 }
265 }
266);