1use core::{marker::PhantomData, ops::BitXor};
2
3use crate::{Network, Round};
4
5pub trait SymmetricNetwork:
8 Sized + IntoIterator<Item: Round<Self::T, L = Self::T>, IntoIter: DoubleEndedIterator>
9{
10 type T: BitXor<Output = Self::T>;
12 fn swap(block: (Self::T, Self::T)) -> (Self::T, Self::T) {
14 let (left, right) = block;
15 (right, left)
16 }
17}
18
19impl<I: SymmetricNetwork> Network for I {
20 type L = I::T;
21 type R = I::T;
22 fn forward(block: (Self::R, Self::L)) -> (Self::L, Self::R) {
23 I::swap(block)
24 }
25 fn backward(block: (Self::L, Self::R)) -> (Self::L, Self::R) {
26 I::swap(block)
27 }
28}
29
30pub struct Symmetric<I, T>(I, PhantomData<T>);
32
33impl<I: Clone, T> Clone for Symmetric<I, T> {
34 fn clone(&self) -> Self {
35 Self(self.0.clone(), PhantomData)
36 }
37}
38
39impl<I: Copy, T> Copy for Symmetric<I, T> {}
40
41impl<I, T: BitXor<Output = T>> Symmetric<I, T> {
42 pub fn new(rounds: I) -> Self {
44 Self(rounds, PhantomData)
45 }
46}
47
48impl<I: IntoIterator, T> IntoIterator for Symmetric<I, T> {
49 type Item = I::Item;
50 type IntoIter = I::IntoIter;
51 fn into_iter(self) -> Self::IntoIter {
52 self.0.into_iter()
53 }
54}
55
56impl<
57 T: BitXor<Output = T>,
58 I: IntoIterator<Item: Round<T, L = T>, IntoIter: DoubleEndedIterator>,
59 > SymmetricNetwork for Symmetric<I, T>
60{
61 type T = T;
62}
63
64mod private {
65 pub trait Sealed<T> {}
66}
67
68pub trait SymmetricExt<T: BitXor<Output = T>>:
70 Sized + IntoIterator<Item: Round<T, L = T>, IntoIter: DoubleEndedIterator> + private::Sealed<T>
71{
72 fn feistel_symmetric(self) -> Symmetric<Self, T> {
74 Symmetric::new(self)
75 }
76}
77
78impl<
79 T: BitXor<Output = T>,
80 I: IntoIterator<Item: Round<T, L = T>, IntoIter: DoubleEndedIterator>,
81 > private::Sealed<T> for I
82{
83}
84
85impl<
86 T: BitXor<Output = T>,
87 I: IntoIterator<Item: Round<T, L = T>, IntoIter: DoubleEndedIterator> + private::Sealed<T>,
88 > SymmetricExt<T> for I
89{
90}