Skip to main content

bulks/
impl_option.rs

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);