1use crate::RollFunction;
4
5use super::FarfalleConfig;
6use crypto_permutation::io::{check_write_size, CryptoReader, Reader, WriteTooLargeError, Writer};
7use crypto_permutation::{Permutation, PermutationState};
8
9pub struct FarfalleOutputGenerator<C: FarfalleConfig> {
11 config: C,
13 key: C::State,
15 state: C::State,
18 output_buffer: C::State,
20 buffered: usize,
22}
23
24impl<C: FarfalleConfig> FarfalleOutputGenerator<C> {
25 pub(super) fn new(key: C::State, state: C::State, config: C) -> Self {
29 Self {
30 config,
31 key,
32 state,
33 output_buffer: Default::default(),
34 buffered: 0,
35 }
36 }
37
38 fn roll_e_state(&mut self) {
40 self.config.roll_e().apply(&mut self.state);
41 }
42
43 fn next_out_block(&mut self) {
46 self.output_buffer = self.state.clone();
47 self.roll_e_state();
48 self.config.perm_e().apply(&mut self.output_buffer);
49 self.output_buffer ^= &self.key;
50 }
51}
52
53impl<C: FarfalleConfig> Reader for FarfalleOutputGenerator<C> {
54 fn capacity(&self) -> usize {
55 usize::MAX
56 }
57
58 fn skip(&mut self, mut n: usize) -> Result<(), WriteTooLargeError> {
59 if self.buffered != 0 {
60 let out_size = core::cmp::min(self.buffered, n);
61 n -= out_size;
62 self.buffered -= out_size;
63 }
64 let remainder = n % C::State::SIZE;
65 let n_blocks = (n - remainder) / C::State::SIZE;
66 for _ in 0..n_blocks {
67 self.next_out_block();
68 }
69 if remainder != 0 {
70 self.next_out_block();
71 self.buffered = C::State::SIZE - remainder;
72 }
73 Ok(())
74 }
75
76 fn write_to<W: Writer>(
77 &mut self,
78 writer: &mut W,
79 mut n: usize,
80 ) -> Result<(), WriteTooLargeError> {
81 check_write_size(n, writer.capacity())?;
82 if self.buffered != 0 {
83 let out_size = core::cmp::min(self.buffered, n);
84 let mut reader = self.output_buffer.reader();
85 reader.skip(C::State::SIZE - self.buffered)?;
86 reader.write_to(writer, out_size)?;
87 n -= out_size;
88 self.buffered -= out_size;
89 }
90 let remainder = n % C::State::SIZE;
91 let n_blocks = (n - remainder) / C::State::SIZE;
92 for _ in 0..n_blocks {
93 self.next_out_block();
94 let mut reader = self.output_buffer.reader();
95 reader.write_to(writer, C::State::SIZE)?;
96 }
97 if remainder != 0 {
98 self.next_out_block();
99 let mut reader = self.output_buffer.reader();
100 reader.write_to(writer, remainder)?;
101 self.buffered = C::State::SIZE - remainder;
102 }
103 Ok(())
104 }
105}
106
107impl<C: FarfalleConfig> CryptoReader for FarfalleOutputGenerator<C> {}