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