Skip to main content

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
11/// This *might* contain a valid [`Niche`].
12pub trait MaybeHasNiche {
13    /// Should implement [`MnArray`]. Not constraint explicitly, because that breaks things.
14    type MnArray;
15}
16
17/// Special [`Niche`] to force use of a tag without any padding.
18pub struct NicheForUnsized;
19
20impl Niche for NicheForUnsized {
21    type NeedsTag = B1;
22    type N = U0;
23    fn niche() -> GenericArray<u8, Self::N> {
24        Default::default()
25    }
26    type Next = Self;
27}
28
29/// [`MaybeNiche`] asserting that `V` is a fake niche.
30pub struct NoNiche<V>(V);
31/// [`MaybeNiche`] asserting that `A` and `B` are fake niches.
32pub struct NoNiche2<A, B>(A, B);
33/// [`MaybeNiche`] asserting that `T` is a true niche.
34pub struct AndNiche<V, T>(V, T);
35/// [`MaybeNiche`] asserting that `T` is a true niche.
36pub struct NicheAnd<T, V>(T, V);
37/// [`MaybeNiche`] asserting that `T` is a true niche.
38pub struct SomeNiche<T>(T);
39
40/// True or fake (placeholder) niche.
41pub trait Niche {
42    /// Whether this is a fake niche (true niches, i.e. those which don't need a tag, don't
43    /// represent a value).
44    type NeedsTag: Bit;
45    /// Length in bytes.
46    type N: ArrayLength;
47    /// Get the niche bytes.
48    fn niche() -> GenericArray<u8, Self::N>;
49    /// What we're left with once we occupy [`Self::niche`].
50    type Next;
51}
52
53/// Conditionally implements [`Niche`]. Used to simplify derivations (and make them possible at
54/// all).
55pub trait MaybeNiche {
56    /// Length in bytes.
57    type N: Unsigned;
58}
59
60pub trait AsTailOf<U: MaybeNiche>: MaybeNiche {
61    type WithHead: MaybeNiche;
62}
63
64pub trait AsHeadOf<U: MaybeNiche>: MaybeNiche {
65    type WithTail: MaybeNiche;
66}
67
68impl<V: Niche<NeedsTag = B1>> Niche for NoNiche<V> {
69    type NeedsTag = B1;
70    type N = V::N;
71    fn niche() -> GenericArray<u8, Self::N> {
72        V::niche()
73    }
74    type Next = Self;
75}
76
77impl<V: Niche<NeedsTag = B1>> MaybeNiche for NoNiche<V> {
78    type N = V::N;
79}
80
81impl<U: MaybeNiche<N: Add<V::N, Output: Unsigned>>, V: Niche<NeedsTag = B1>> AsTailOf<U>
82    for NoNiche<V>
83{
84    type WithHead = NoNiche2<U, Self>;
85}
86
87impl<V: Niche<NeedsTag = B1>, U: AsTailOf<Self>> AsHeadOf<U> for NoNiche<V> {
88    type WithTail = U::WithHead;
89}
90
91impl<A: Niche<N: Add<B::N, Output: ArrayLength>>, B: Niche> Niche for NoNiche2<A, B> {
92    type NeedsTag = B1;
93    type N = Sum<A::N, B::N>;
94    fn niche() -> GenericArray<u8, Self::N> {
95        Concat::concat(A::niche(), B::niche())
96    }
97    type Next = NoNiche<Self>;
98}
99
100impl<A: MaybeNiche<N: Add<B::N, Output: Unsigned>>, B: MaybeNiche> MaybeNiche for NoNiche2<A, B> {
101    type N = Sum<A::N, B::N>;
102}
103
104impl<
105    U: MaybeNiche<N: Add<Sum<A::N, B::N>, Output: Unsigned>>,
106    A: MaybeNiche<N: Add<B::N, Output: Unsigned>>,
107    B: MaybeNiche,
108> AsTailOf<U> for NoNiche2<A, B>
109{
110    type WithHead = NoNiche2<U, Self>;
111}
112
113impl<A: MaybeNiche<N: Add<B::N, Output: Unsigned>>, B: MaybeNiche, U: AsTailOf<Self>> AsHeadOf<U>
114    for NoNiche2<A, B>
115{
116    type WithTail = U::WithHead;
117}
118
119impl<
120    V: Niche<N = N, NeedsTag: NicheAuto>,
121    N: ArrayLength + Add<T::N, Output: ArrayLength>,
122    T: Niche,
123> Niche for AndNiche<V, T>
124{
125    type NeedsTag = T::NeedsTag;
126    type N = Sum<N, T::N>;
127    fn niche() -> GenericArray<u8, Self::N> {
128        Concat::concat(V::niche(), T::niche())
129    }
130    type Next = AndNiche<AutoNiche<V>, T::Next>;
131}
132
133impl<V: MaybeNiche<N = N>, N: Unsigned, T: MaybeNiche> MaybeNiche for AndNiche<V, T>
134where
135    N: Add<T::N, Output: Unsigned>,
136{
137    type N = Sum<N, T::N>;
138}
139
140impl<
141    U: MaybeNiche<N: Add<Sum<N, T::N>, Output: Unsigned>>,
142    V: MaybeNiche<N = N>,
143    N: Unsigned,
144    T: MaybeNiche,
145> AsTailOf<U> for AndNiche<V, T>
146where
147    N: Add<T::N, Output: Unsigned>,
148{
149    type WithHead = AndNiche<U, Self>;
150}
151
152impl<V: MaybeNiche<N = N>, N: Unsigned, T: MaybeNiche, U: MaybeNiche> AsHeadOf<U> for AndNiche<V, T>
153where
154    N: Add<T::N, Output: Unsigned>,
155    Sum<N, T::N>: Add<U::N, Output: Unsigned>,
156{
157    type WithTail = NicheAnd<Self, U>;
158}
159
160impl<T: Niche<N: Add<N, Output: ArrayLength>>, V: Niche<N = N, NeedsTag: NicheAuto>, N: ArrayLength>
161    Niche for NicheAnd<T, V>
162{
163    type NeedsTag = T::NeedsTag;
164    type N = Sum<T::N, N>;
165    fn niche() -> GenericArray<u8, Self::N> {
166        Concat::concat(T::niche(), V::niche())
167    }
168    type Next = NicheAnd<T::Next, AutoNiche<V>>;
169}
170
171impl<T: MaybeNiche<N: Add<N, Output: Unsigned>>, V: MaybeNiche<N = N>, N: Unsigned> MaybeNiche
172    for NicheAnd<T, V>
173{
174    type N = Sum<T::N, N>;
175}
176
177impl<
178    U: MaybeNiche<N: Add<Sum<T::N, N>, Output: Unsigned>>,
179    T: MaybeNiche<N: Add<N, Output: Unsigned>>,
180    V: MaybeNiche<N = N>,
181    N: Unsigned,
182> AsTailOf<U> for NicheAnd<T, V>
183{
184    type WithHead = AndNiche<U, Self>;
185}
186
187impl<T: MaybeNiche<N: Add<N, Output: Unsigned>>, V: MaybeNiche<N = N>, N: Unsigned, U: MaybeNiche>
188    AsHeadOf<U> for NicheAnd<T, V>
189where
190    Sum<T::N, N>: Add<U::N, Output: Unsigned>,
191{
192    type WithTail = NicheAnd<Self, U>;
193}
194
195impl<T: Niche<NeedsTag = B0>> Niche for SomeNiche<T> {
196    type NeedsTag = T::NeedsTag;
197    type N = T::N;
198    fn niche() -> GenericArray<u8, Self::N> {
199        T::niche()
200    }
201    type Next = T::Next;
202}
203
204impl<T: Niche<NeedsTag = B0>> MaybeNiche for SomeNiche<T> {
205    type N = T::N;
206}
207
208impl<U: MaybeNiche<N: Add<T::N, Output: Unsigned>>, T: Niche<NeedsTag = B0>> AsTailOf<U>
209    for SomeNiche<T>
210{
211    type WithHead = AndNiche<U, Self>;
212}
213
214impl<T: Niche<N: Add<U::N, Output: Unsigned>, NeedsTag = B0>, U: MaybeNiche> AsHeadOf<U>
215    for SomeNiche<T>
216{
217    type WithTail = NicheAnd<Self, U>;
218}
219
220/// Array ([`typenum`]-ish) that *might* be reducible down to a [`Niche`].
221pub trait MnArray {
222    /// Possibly, [`Niche`].
223    type MaybeNiche: MaybeNiche;
224}
225
226impl MnArray for ATerm {
227    type MaybeNiche = NoNiche<ZeroNoNiche<U0>>;
228}
229
230impl<T: MaybeNiche> MnArray for T {
231    type MaybeNiche = T;
232}
233
234impl<T: AsHeadOf<R::MaybeNiche>, R: MnArray> MnArray for TArr<T, R> {
235    type MaybeNiche = T::WithTail;
236}
237
238/// Already occupied/unusable byte representation filled with `0x00` bytes.
239pub struct ZeroNoNiche<N>(N);
240
241impl<N: ArrayLength> Niche for ZeroNoNiche<N> {
242    type NeedsTag = B1;
243    type N = N;
244    fn niche() -> GenericArray<u8, Self::N> {
245        GenericArray::default()
246    }
247    type Next = NoNiche<Self>;
248}
249
250/// Niche filled with `0x00` bytes.
251pub struct ZeroNiche<N, Next = NoNiche<ZeroNoNiche<N>>>(N, Next);
252
253impl<N: ArrayLength, Next> Niche for ZeroNiche<N, Next> {
254    type NeedsTag = B0;
255    type N = N;
256    fn niche() -> GenericArray<u8, Self::N> {
257        GenericArray::default()
258    }
259    type Next = Next;
260}
261
262/// Niche filled with `0xFF` bytes.
263pub struct OneNiche<N>(N);
264
265impl<N: ArrayLength> Niche for OneNiche<N> {
266    type NeedsTag = B0;
267    type N = N;
268    fn niche() -> GenericArray<u8, Self::N> {
269        GenericArray::default().map(|()| 0xff)
270    }
271    type Next = NoNiche<ZeroNoNiche<N>>;
272}
273
274#[doc(hidden)]
275pub trait NicheOr: MaybeNiche {
276    type NicheOr<U: NicheOr<N = Self::N>>: NicheOr<N = Self::N>;
277    fn index(index: usize) -> usize;
278}
279
280impl<V: Niche<NeedsTag = B1>> NicheOr for NoNiche<V> {
281    type NicheOr<U: NicheOr<N = Self::N>> = U;
282    fn index(index: usize) -> usize {
283        index + 1
284    }
285}
286
287impl<A: MaybeNiche<N: Add<B::N, Output: Unsigned>>, B: MaybeNiche> NicheOr for NoNiche2<A, B> {
288    type NicheOr<U: NicheOr<N = Self::N>> = U;
289    fn index(index: usize) -> usize {
290        index + 1
291    }
292}
293
294impl<V: MaybeNiche<N = N>, N: Unsigned + Add<T::N, Output: Unsigned>, T: MaybeNiche> NicheOr
295    for AndNiche<V, T>
296{
297    type NicheOr<U: NicheOr<N = Self::N>> = Self;
298    fn index(_: usize) -> usize {
299        0
300    }
301}
302
303impl<T: MaybeNiche<N: Add<N, Output: Unsigned>>, V: MaybeNiche<N = N>, N: Unsigned> NicheOr
304    for NicheAnd<T, V>
305{
306    type NicheOr<U: NicheOr<N = Self::N>> = Self;
307    fn index(_: usize) -> usize {
308        0
309    }
310}
311
312impl<T: Niche<NeedsTag = B0>> NicheOr for SomeNiche<T> {
313    type NicheOr<U: NicheOr<N = Self::N>> = Self;
314    fn index(_: usize) -> usize {
315        0
316    }
317}
318
319pub trait NicheFoldOr {
320    type Or: NicheOr;
321    fn index() -> usize;
322}
323
324impl<T: MnArray<MaybeNiche: NicheOr>> NicheFoldOr for TArr<T, ATerm> {
325    type Or = T::MaybeNiche;
326    fn index() -> usize {
327        0
328    }
329}
330
331impl<T: NicheOr, A: NicheFoldOr<Or: MaybeNiche<N = T::N>>> NicheFoldOr for TArr<T, A> {
332    type Or = T::NicheOr<A::Or>;
333    fn index() -> usize {
334        T::index(A::index())
335    }
336}
337
338#[doc(hidden)]
339pub struct NicheFoldOrArray<T>(T);
340
341impl<T: NicheFoldOr> MnArray for NicheFoldOrArray<T> {
342    type MaybeNiche = T::Or;
343}
344
345pub struct EnumNiche<E, const X: usize>(E);
346
347impl<
348    E: Enum<Kind = K>,
349    K: EnumKind<Tag = T>,
350    T: UsizeTag + ToOutput + Size<Size = N> + MaybeHasNiche<MnArray: MnArray<MaybeNiche = V>>,
351    V: Niche<N = N>,
352    N: ArrayLength,
353    const X: usize,
354> Niche for EnumNiche<E, X>
355{
356    type NeedsTag = V::NeedsTag;
357    type N = N;
358    fn niche() -> GenericArray<u8, Self::N> {
359        if V::NeedsTag::BOOL {
360            T::from_usize(X).to_array()
361        } else {
362            V::niche()
363        }
364    }
365    type Next = NoNiche<ZeroNoNiche<N>>;
366}
367
368pub trait NicheAuto: Bit {
369    type Auto<T: Niche<NeedsTag = Self>>: MaybeNiche<N = T::N>;
370}
371
372impl NicheAuto for B0 {
373    type Auto<T: Niche<NeedsTag = Self>> = SomeNiche<T>;
374}
375
376impl NicheAuto for B1 {
377    type Auto<T: Niche<NeedsTag = Self>> = NoNiche<T>;
378}
379
380#[doc(hidden)]
381pub type AutoNiche<T> = <<T as Niche>::NeedsTag as NicheAuto>::Auto<T>;
382
383#[doc(hidden)]
384pub type AutoEnumNiche<E, const X: usize> = AutoNiche<EnumNiche<E, X>>;
385
386#[doc(hidden)]
387pub struct HackNiche<const X: usize>;
388
389impl<const X: usize> Niche for HackNiche<X> {
390    type NeedsTag = B1;
391    type N = U0;
392    fn niche() -> GenericArray<u8, Self::N> {
393        GenericArray::default()
394    }
395    type Next = NoNiche<Self>;
396}