1use core::marker::PhantomData;
6use super::nibble::Nibble;
7
8pub trait HashStream: 'static {
14 type Head: Nibble;
15 type Tail: HashStream;
16}
17
18pub trait GetTail<D> {
20 type Out: HashStream;
21}
22
23impl<H: HashStream> GetTail<Z> for H {
24 type Out = Self;
25}
26
27impl<H: HashStream, D> GetTail<S<D>> for H
28where
29 H::Tail: GetTail<D>,
30{
31 type Out = <H::Tail as GetTail<D>>::Out;
32}
33
34pub struct ConstStream<N>(PhantomData<N>);
40
41impl<N: Nibble + 'static> HashStream for ConstStream<N> {
42 type Head = N;
43 type Tail = ConstStream<N>;
44}
45
46pub struct AltStream<A, B>(PhantomData<(A, B)>);
48
49impl<A: Nibble + 'static, B: Nibble + 'static> HashStream for AltStream<A, B> {
50 type Head = A;
51 type Tail = AltStream<B, A>;
52}
53
54pub struct Cons<H, T>(PhantomData<(H, T)>);
56
57impl<H: Nibble + 'static, T: HashStream> HashStream for Cons<H, T> {
58 type Head = H;
59 type Tail = T;
60}
61
62pub trait Peano {}
68
69pub struct Z;
71impl Peano for Z {}
72
73pub struct S<N>(PhantomData<N>);
75impl<N: Peano> Peano for S<N> {}
76
77macros::peano!(64);
79
80pub type DefaultMaxDepth = D16;
82
83use super::bool::{Bool, Present, Absent};
88
89pub trait StreamEq<Other: HashStream, Limit> {
91 type Out: Bool;
92}
93
94impl<A: HashStream, B: HashStream> StreamEq<B, Z> for A {
95 type Out = Present;
96}
97
98impl<A, B, L> StreamEq<B, S<L>> for A
99where
100 A: HashStream,
101 B: HashStream,
102 A::Head: super::nibble::NibbleEq<B::Head>,
103 <A::Head as super::nibble::NibbleEq<B::Head>>::Out: StreamEqDispatch<A::Tail, B::Tail, L>,
104{
105 type Out = <<A::Head as super::nibble::NibbleEq<B::Head>>::Out as StreamEqDispatch<A::Tail, B::Tail, L>>::Out;
106}
107
108pub trait StreamEqDispatch<TailA, TailB, Limit> {
109 type Out: Bool;
110}
111
112impl<TailA, TailB, L> StreamEqDispatch<TailA, TailB, L> for Absent {
113 type Out = Absent;
114}
115
116impl<TailA, TailB, L> StreamEqDispatch<TailA, TailB, L> for Present
117where
118 TailA: HashStream + StreamEq<TailB, L>,
119 TailB: HashStream,
120{
121 type Out = <TailA as StreamEq<TailB, L>>::Out;
122}
123
124use super::nibble::{X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, XA, XB, XC, XD, XE, XF};
157
158pub trait SelectNibble<const N: u8> {
160 type Out: Nibble;
161}
162
163macro_rules! impl_select_nibble {
164 ($($val:literal => $nib:ident),* $(,)?) => {
165 $(
166 impl SelectNibble<$val> for () {
167 type Out = $nib;
168 }
169 )*
170 };
171}
172
173impl_select_nibble!(
174 0 => X0, 1 => X1, 2 => X2, 3 => X3,
175 4 => X4, 5 => X5, 6 => X6, 7 => X7,
176 8 => X8, 9 => X9, 10 => XA, 11 => XB,
177 12 => XC, 13 => XD, 14 => XE, 15 => XF,
178);
179
180pub struct HashStream16<
183 const N0: u8, const N1: u8, const N2: u8, const N3: u8,
184 const N4: u8, const N5: u8, const N6: u8, const N7: u8,
185 const N8: u8, const N9: u8, const N10: u8, const N11: u8,
186 const N12: u8, const N13: u8, const N14: u8, const N15: u8,
187>(PhantomData<()>);
188
189impl<
190 const N0: u8, const N1: u8, const N2: u8, const N3: u8,
191 const N4: u8, const N5: u8, const N6: u8, const N7: u8,
192 const N8: u8, const N9: u8, const N10: u8, const N11: u8,
193 const N12: u8, const N13: u8, const N14: u8, const N15: u8,
194> HashStream for HashStream16<N0, N1, N2, N3, N4, N5, N6, N7, N8, N9, N10, N11, N12, N13, N14, N15>
195where
196 (): SelectNibble<N0> + SelectNibble<N1> + SelectNibble<N2> + SelectNibble<N3>
197 + SelectNibble<N4> + SelectNibble<N5> + SelectNibble<N6> + SelectNibble<N7>
198 + SelectNibble<N8> + SelectNibble<N9> + SelectNibble<N10> + SelectNibble<N11>
199 + SelectNibble<N12> + SelectNibble<N13> + SelectNibble<N14> + SelectNibble<N15>,
200{
201 type Head = <() as SelectNibble<N0>>::Out;
202 type Tail = HashStream16<N1, N2, N3, N4, N5, N6, N7, N8, N9, N10, N11, N12, N13, N14, N15, N0>;
203}
204
205