object_rainbow/
niche.rs

1use std::ops::Add;
2
3use generic_array::{ArrayLength, GenericArray, functional::FunctionalSequence, sequence::Concat};
4use typenum::{ATerm, B0, B1, Bit, Sum, TArr, U0, Unsigned};
5
6use crate::{
7    Enum, Size, SizeExt, ToOutput,
8    enumkind::{EnumKind, UsizeTag},
9};
10
11pub trait MaybeHasNiche {
12    type MnArray;
13}
14
15pub struct NoNiche<V>(V);
16pub struct NoNiche2<A, B>(A, B);
17pub struct AndNiche<V, T>(V, T);
18pub struct NicheAnd<T, V>(T, V);
19pub struct SomeNiche<T>(T);
20
21pub trait Niche {
22    type NeedsTag: Bit;
23    type N: ArrayLength;
24    fn niche() -> GenericArray<u8, Self::N>;
25    type Next;
26}
27
28pub trait MaybeNiche {
29    type N: Unsigned;
30}
31
32pub trait AsTailOf<U: MaybeNiche>: MaybeNiche {
33    type WithHead: MaybeNiche;
34}
35
36pub trait AsHeadOf<U: MaybeNiche>: MaybeNiche {
37    type WithTail: MaybeNiche;
38}
39
40impl<V: Niche<NeedsTag = B1>> Niche for NoNiche<V> {
41    type NeedsTag = B1;
42    type N = V::N;
43    fn niche() -> GenericArray<u8, Self::N> {
44        V::niche()
45    }
46    type Next = Self;
47}
48
49impl<V: Niche<NeedsTag = B1>> MaybeNiche for NoNiche<V> {
50    type N = V::N;
51}
52
53impl<U: MaybeNiche<N: Add<V::N, Output: Unsigned>>, V: Niche<NeedsTag = B1>> AsTailOf<U>
54    for NoNiche<V>
55{
56    type WithHead = NoNiche2<U, Self>;
57}
58
59impl<V: Niche<NeedsTag = B1>, U: AsTailOf<Self>> AsHeadOf<U> for NoNiche<V> {
60    type WithTail = U::WithHead;
61}
62
63impl<A: Niche<N: Add<B::N, Output: ArrayLength>>, B: Niche> Niche for NoNiche2<A, B> {
64    type NeedsTag = B1;
65    type N = Sum<A::N, B::N>;
66    fn niche() -> GenericArray<u8, Self::N> {
67        Concat::concat(A::niche(), B::niche())
68    }
69    type Next = NoNiche<Self>;
70}
71
72impl<A: MaybeNiche<N: Add<B::N, Output: Unsigned>>, B: MaybeNiche> MaybeNiche for NoNiche2<A, B> {
73    type N = Sum<A::N, B::N>;
74}
75
76impl<
77    U: MaybeNiche<N: Add<Sum<A::N, B::N>, Output: Unsigned>>,
78    A: MaybeNiche<N: Add<B::N, Output: Unsigned>>,
79    B: MaybeNiche,
80> AsTailOf<U> for NoNiche2<A, B>
81{
82    type WithHead = NoNiche2<U, Self>;
83}
84
85impl<A: MaybeNiche<N: Add<B::N, Output: Unsigned>>, B: MaybeNiche, U: AsTailOf<Self>> AsHeadOf<U>
86    for NoNiche2<A, B>
87{
88    type WithTail = U::WithHead;
89}
90
91impl<
92    V: Niche<N = N, NeedsTag: NicheAuto>,
93    N: ArrayLength + Add<T::N, Output: ArrayLength>,
94    T: Niche,
95> Niche for AndNiche<V, T>
96{
97    type NeedsTag = T::NeedsTag;
98    type N = Sum<N, T::N>;
99    fn niche() -> GenericArray<u8, Self::N> {
100        Concat::concat(V::niche(), T::niche())
101    }
102    type Next = AndNiche<AutoNiche<V>, T::Next>;
103}
104
105impl<V: MaybeNiche<N = N>, N: Unsigned, T: MaybeNiche> MaybeNiche for AndNiche<V, T>
106where
107    N: Add<T::N, Output: Unsigned>,
108{
109    type N = Sum<N, T::N>;
110}
111
112impl<
113    U: MaybeNiche<N: Add<Sum<N, T::N>, Output: Unsigned>>,
114    V: MaybeNiche<N = N>,
115    N: Unsigned,
116    T: MaybeNiche,
117> AsTailOf<U> for AndNiche<V, T>
118where
119    N: Add<T::N, Output: Unsigned>,
120{
121    type WithHead = AndNiche<U, Self>;
122}
123
124impl<V: MaybeNiche<N = N>, N: Unsigned, T: MaybeNiche, U: MaybeNiche> AsHeadOf<U> for AndNiche<V, T>
125where
126    N: Add<T::N, Output: Unsigned>,
127    Sum<N, T::N>: Add<U::N, Output: Unsigned>,
128{
129    type WithTail = NicheAnd<Self, U>;
130}
131
132impl<T: Niche<N: Add<N, Output: ArrayLength>>, V: Niche<N = N, NeedsTag: NicheAuto>, N: ArrayLength>
133    Niche for NicheAnd<T, V>
134{
135    type NeedsTag = T::NeedsTag;
136    type N = Sum<T::N, N>;
137    fn niche() -> GenericArray<u8, Self::N> {
138        Concat::concat(T::niche(), V::niche())
139    }
140    type Next = NicheAnd<T::Next, AutoNiche<V>>;
141}
142
143impl<T: MaybeNiche<N: Add<N, Output: Unsigned>>, V: MaybeNiche<N = N>, N: Unsigned> MaybeNiche
144    for NicheAnd<T, V>
145{
146    type N = Sum<T::N, N>;
147}
148
149impl<
150    U: MaybeNiche<N: Add<Sum<T::N, N>, Output: Unsigned>>,
151    T: MaybeNiche<N: Add<N, Output: Unsigned>>,
152    V: MaybeNiche<N = N>,
153    N: Unsigned,
154> AsTailOf<U> for NicheAnd<T, V>
155{
156    type WithHead = AndNiche<U, Self>;
157}
158
159impl<T: MaybeNiche<N: Add<N, Output: Unsigned>>, V: MaybeNiche<N = N>, N: Unsigned, U: MaybeNiche>
160    AsHeadOf<U> for NicheAnd<T, V>
161where
162    Sum<T::N, N>: Add<U::N, Output: Unsigned>,
163{
164    type WithTail = NicheAnd<Self, U>;
165}
166
167impl<T: Niche<NeedsTag = B0>> Niche for SomeNiche<T> {
168    type NeedsTag = T::NeedsTag;
169    type N = T::N;
170    fn niche() -> GenericArray<u8, Self::N> {
171        T::niche()
172    }
173    type Next = T::Next;
174}
175
176impl<T: Niche<NeedsTag = B0>> MaybeNiche for SomeNiche<T> {
177    type N = T::N;
178}
179
180impl<U: MaybeNiche<N: Add<T::N, Output: Unsigned>>, T: Niche<NeedsTag = B0>> AsTailOf<U>
181    for SomeNiche<T>
182{
183    type WithHead = AndNiche<U, Self>;
184}
185
186impl<T: Niche<N: Add<U::N, Output: Unsigned>, NeedsTag = B0>, U: MaybeNiche> AsHeadOf<U>
187    for SomeNiche<T>
188{
189    type WithTail = NicheAnd<Self, U>;
190}
191
192pub trait MnArray {
193    type MaybeNiche: MaybeNiche;
194}
195
196impl MnArray for ATerm {
197    type MaybeNiche = NoNiche<ZeroNoNiche<U0>>;
198}
199
200impl<T: MaybeNiche> MnArray for T {
201    type MaybeNiche = T;
202}
203
204impl<T: AsHeadOf<R::MaybeNiche>, R: MnArray> MnArray for TArr<T, R> {
205    type MaybeNiche = T::WithTail;
206}
207
208pub struct ZeroNoNiche<N>(N);
209
210impl<N: ArrayLength> Niche for ZeroNoNiche<N> {
211    type NeedsTag = B1;
212    type N = N;
213    fn niche() -> GenericArray<u8, Self::N> {
214        GenericArray::default()
215    }
216    type Next = NoNiche<Self>;
217}
218
219pub struct ZeroNiche<N, Next = NoNiche<ZeroNoNiche<N>>>(N, Next);
220
221impl<N: ArrayLength, Next> Niche for ZeroNiche<N, Next> {
222    type NeedsTag = B0;
223    type N = N;
224    fn niche() -> GenericArray<u8, Self::N> {
225        GenericArray::default()
226    }
227    type Next = Next;
228}
229
230pub struct OneNiche<N>(N);
231
232impl<N: ArrayLength> Niche for OneNiche<N> {
233    type NeedsTag = B0;
234    type N = N;
235    fn niche() -> GenericArray<u8, Self::N> {
236        GenericArray::default().map(|()| 0xff)
237    }
238    type Next = NoNiche<ZeroNoNiche<N>>;
239}
240
241pub trait NicheOr: MaybeNiche {
242    type NicheOr<U: NicheOr<N = Self::N>>: NicheOr<N = Self::N>;
243    fn index(index: usize) -> usize;
244}
245
246impl<V: Niche<NeedsTag = B1>> NicheOr for NoNiche<V> {
247    type NicheOr<U: NicheOr<N = Self::N>> = U;
248    fn index(index: usize) -> usize {
249        index + 1
250    }
251}
252
253impl<A: MaybeNiche<N: Add<B::N, Output: Unsigned>>, B: MaybeNiche> NicheOr for NoNiche2<A, B> {
254    type NicheOr<U: NicheOr<N = Self::N>> = U;
255    fn index(index: usize) -> usize {
256        index + 1
257    }
258}
259
260impl<V: MaybeNiche<N = N>, N: Unsigned + Add<T::N, Output: Unsigned>, T: MaybeNiche> NicheOr
261    for AndNiche<V, T>
262{
263    type NicheOr<U: NicheOr<N = Self::N>> = Self;
264    fn index(_: usize) -> usize {
265        0
266    }
267}
268
269impl<T: MaybeNiche<N: Add<N, Output: Unsigned>>, V: MaybeNiche<N = N>, N: Unsigned> NicheOr
270    for NicheAnd<T, V>
271{
272    type NicheOr<U: NicheOr<N = Self::N>> = Self;
273    fn index(_: usize) -> usize {
274        0
275    }
276}
277
278impl<T: Niche<NeedsTag = B0>> NicheOr for SomeNiche<T> {
279    type NicheOr<U: NicheOr<N = Self::N>> = Self;
280    fn index(_: usize) -> usize {
281        0
282    }
283}
284
285pub trait NicheFoldOr {
286    type Or: NicheOr;
287    fn index() -> usize;
288}
289
290impl<T: MnArray<MaybeNiche: NicheOr>> NicheFoldOr for TArr<T, ATerm> {
291    type Or = T::MaybeNiche;
292    fn index() -> usize {
293        0
294    }
295}
296
297impl<T: NicheOr, A: NicheFoldOr<Or: MaybeNiche<N = T::N>>> NicheFoldOr for TArr<T, A> {
298    type Or = T::NicheOr<A::Or>;
299    fn index() -> usize {
300        T::index(A::index())
301    }
302}
303
304pub struct NicheFoldOrArray<T>(T);
305
306impl<T: NicheFoldOr> MnArray for NicheFoldOrArray<T> {
307    type MaybeNiche = T::Or;
308}
309
310pub struct EnumNiche<E, const X: usize>(E);
311
312impl<
313    E: Enum<Kind = K>,
314    K: EnumKind<Tag = T>,
315    T: UsizeTag + ToOutput + Size<Size = N> + MaybeHasNiche<MnArray: MnArray<MaybeNiche = V>>,
316    V: Niche<N = N>,
317    N: ArrayLength,
318    const X: usize,
319> Niche for EnumNiche<E, X>
320{
321    type NeedsTag = V::NeedsTag;
322    type N = N;
323    fn niche() -> GenericArray<u8, Self::N> {
324        if V::NeedsTag::BOOL {
325            T::from_usize(X).to_array()
326        } else {
327            V::niche()
328        }
329    }
330    type Next = NoNiche<ZeroNoNiche<N>>;
331}
332
333pub trait NicheAuto: Bit {
334    type Auto<T: Niche<NeedsTag = Self>>: MaybeNiche<N = T::N>;
335}
336
337impl NicheAuto for B0 {
338    type Auto<T: Niche<NeedsTag = Self>> = SomeNiche<T>;
339}
340
341impl NicheAuto for B1 {
342    type Auto<T: Niche<NeedsTag = Self>> = NoNiche<T>;
343}
344
345pub type AutoNiche<T> = <<T as Niche>::NeedsTag as NicheAuto>::Auto<T>;
346
347pub type AutoEnumNiche<E, const X: usize> = AutoNiche<EnumNiche<E, X>>;
348
349pub struct HackNiche<const X: usize>;
350
351impl<const X: usize> Niche for HackNiche<X> {
352    type NeedsTag = B1;
353    type N = U0;
354    fn niche() -> GenericArray<u8, Self::N> {
355        GenericArray::default()
356    }
357    type Next = NoNiche<Self>;
358}