1use core::{
2 marker::PhantomData,
3 ops::{Add, BitXor, BitXorAssign, Sub},
4};
5
6use generic_array::{
7 sequence::{Concat, Split},
8 typenum::Sum,
9 ArrayLength, GenericArray,
10};
11
12use crate::{Network, Reverse, Round, XorArray};
13
14pub trait ArrayNetwork:
16 Network<L = XorArray<Self::T, Self::LN>, R = XorArray<Self::T, Self::RN>>
17{
18 type LN: ArrayLength
20 + Add<
21 Self::RN,
22 Output: ArrayLength
23 + Sub<Self::LN, Output = Self::RN>
24 + Sub<Self::RN, Output = Self::LN>,
25 >;
26 type RN: ArrayLength + Add<Self::LN, Output = <Self::LN as Add<Self::RN>>::Output>;
28 type T: BitXor;
30 fn array_encrypt(self, block: Block<Self>) -> Block<Self> {
32 let (left, right) = Split::split(block);
33 let (left, right) = (XorArray(left), XorArray(right));
34 let (left, right) = self.encrypt((left, right));
35 Concat::concat(left.0, right.0)
36 }
37 fn array_decrypt(self, block: Block<Self>) -> Block<Self> {
39 Reverse(self).array_encrypt(block)
40 }
41}
42
43type Block<I> =
44 GenericArray<<I as ArrayNetwork>::T, Sum<<I as ArrayNetwork>::LN, <I as ArrayNetwork>::RN>>;
45
46impl<
47 T: BitXor,
48 L: ArrayLength + Add<R, Output: ArrayLength + Sub<L, Output = R> + Sub<R, Output = L>>,
49 R: ArrayLength + Add<L, Output = <L as Add<R>>::Output>,
50 I: Network<L = XorArray<T, L>, R = XorArray<T, R>>,
51 > ArrayNetwork for I
52{
53 type LN = L;
54 type RN = R;
55 type T = T;
56}
57
58pub struct Array<I, T, R>(I, PhantomData<(T, R)>);
60
61impl<I: Clone, T, R> Clone for Array<I, T, R> {
62 fn clone(&self) -> Self {
63 Self(self.0.clone(), PhantomData)
64 }
65}
66
67impl<I: Copy, T, R> Copy for Array<I, T, R> {}
68
69impl<
70 T: BitXorAssign,
71 L: ArrayLength + Add<R, Output: ArrayLength + Sub<L, Output = R> + Sub<R, Output = L>>,
72 R: ArrayLength + Add<L, Output = <L as Add<R>>::Output>,
73 I: IntoIterator<
74 Item: Round<XorArray<T, R>, L = XorArray<T, L>>,
75 IntoIter: DoubleEndedIterator,
76 >,
77 > Array<I, T, R>
78{
79 pub fn new(rounds: I) -> Self {
81 Self(rounds, PhantomData)
82 }
83}
84
85impl<I: IntoIterator, T, R> IntoIterator for Array<I, T, R> {
86 type Item = I::Item;
87 type IntoIter = I::IntoIter;
88 fn into_iter(self) -> Self::IntoIter {
89 self.0.into_iter()
90 }
91}
92
93impl<
94 T: BitXorAssign,
95 L: ArrayLength + Add<R, Output: ArrayLength + Sub<L, Output = R> + Sub<R, Output = L>>,
96 R: ArrayLength + Add<L, Output = <L as Add<R>>::Output>,
97 I: IntoIterator<
98 Item: Round<XorArray<T, R>, L = XorArray<T, L>>,
99 IntoIter: DoubleEndedIterator,
100 >,
101 > Network for Array<I, T, R>
102{
103 type L = XorArray<T, L>;
104 type R = XorArray<T, R>;
105 fn forward(block: (Self::L, Self::R)) -> (Self::L, Self::R) {
106 let (left, right) = block;
107 let (left, right) = Split::split(Concat::concat(right.0, left.0));
108 let (left, right) = (XorArray(left), XorArray(right));
109 (left, right)
110 }
111 fn backward(block: (Self::L, Self::R)) -> (Self::L, Self::R) {
112 let (left, right) = block;
113 let (right, left) = Split::split(Concat::concat(left.0, right.0));
114 let (right, left) = (XorArray(right), XorArray(left));
115 (left, right)
116 }
117}
118
119mod private {
120 pub trait Sealed<T, R> {}
121}
122
123pub trait ArrayExt<
125 T: BitXorAssign,
126 R: ArrayLength
127 + Add<Self::L, Output: ArrayLength + Sub<R, Output = Self::L> + Sub<Self::L, Output = R>>,
128>:
129 Sized
130 + IntoIterator<
131 Item: Round<XorArray<T, R>, L = XorArray<T, Self::L>>,
132 IntoIter: DoubleEndedIterator,
133 > + private::Sealed<T, R>
134{
135 type L: ArrayLength + Add<R, Output = <R as Add<Self::L>>::Output>;
137
138 fn feistel_array(self) -> Array<Self, T, R> {
140 Array::new(self)
141 }
142}
143
144impl<
145 T: BitXorAssign,
146 L: ArrayLength + Add<R, Output = <R as Add<L>>::Output>,
147 R: ArrayLength + Add<L, Output: ArrayLength + Sub<R, Output = L> + Sub<L, Output = R>>,
148 I: IntoIterator<
149 Item: Round<XorArray<T, R>, L = XorArray<T, L>>,
150 IntoIter: DoubleEndedIterator,
151 >,
152 > private::Sealed<T, R> for I
153{
154}
155
156impl<
157 T: BitXorAssign,
158 L: ArrayLength + Add<R, Output = <R as Add<L>>::Output>,
159 R: ArrayLength + Add<L, Output: ArrayLength + Sub<R, Output = L> + Sub<L, Output = R>>,
160 I: IntoIterator<
161 Item: Round<XorArray<T, R>, L = XorArray<T, L>>,
162 IntoIter: DoubleEndedIterator,
163 >,
164 > ArrayExt<T, R> for I
165{
166 type L = L;
167}