base64_ng/stream/
encoder_reader.rs1use super::{OutputQueue, encode_error_to_io, redacted_inner_state, stream_encoder_failed_error};
2use crate::{Alphabet, Engine};
3use std::io::{self, Read};
4
5pub struct EncoderReader<R, A, const PAD: bool>
7where
8 A: Alphabet,
9{
10 inner: Option<R>,
11 engine: Engine<A, PAD>,
12 pending: [u8; 2],
13 pending_len: usize,
14 output: OutputQueue<1024>,
15 finished: bool,
16 failed: bool,
17}
18
19impl<R, A, const PAD: bool> EncoderReader<R, A, PAD>
20where
21 A: Alphabet,
22{
23 #[must_use]
25 pub fn new(inner: R, engine: Engine<A, PAD>) -> Self {
26 Self {
27 inner: Some(inner),
28 engine,
29 pending: [0; 2],
30 pending_len: 0,
31 output: OutputQueue::new(),
32 finished: false,
33 failed: false,
34 }
35 }
36
37 #[must_use]
39 pub fn get_ref(&self) -> &R {
40 self.inner_ref()
41 }
42
43 pub fn get_mut(&mut self) -> &mut R {
45 self.inner_mut()
46 }
47
48 #[must_use]
50 pub const fn engine(&self) -> Engine<A, PAD> {
51 self.engine
52 }
53
54 #[must_use]
56 pub const fn is_padded(&self) -> bool {
57 PAD
58 }
59
60 #[must_use]
63 pub const fn pending_len(&self) -> usize {
64 self.pending_len
65 }
66
67 #[must_use]
70 pub const fn has_pending_input(&self) -> bool {
71 self.pending_len != 0
72 }
73
74 #[must_use]
79 pub const fn pending_input_needed_len(&self) -> usize {
80 if self.has_pending_input() {
81 3 - self.pending_len
82 } else {
83 0
84 }
85 }
86
87 #[must_use]
90 pub const fn buffered_output_len(&self) -> usize {
91 self.output.len()
92 }
93
94 #[must_use]
97 pub const fn buffered_output_capacity(&self) -> usize {
98 self.output.capacity()
99 }
100
101 #[must_use]
104 pub const fn buffered_output_remaining_capacity(&self) -> usize {
105 self.output.available_capacity()
106 }
107
108 #[must_use]
111 pub const fn has_buffered_output(&self) -> bool {
112 !self.output.is_empty()
113 }
114
115 #[must_use]
121 pub const fn has_finished_input(&self) -> bool {
122 self.finished
123 }
124
125 #[must_use]
128 pub const fn is_finished(&self) -> bool {
129 self.finished && self.output.is_empty()
130 }
131
132 #[must_use]
135 pub const fn is_failed(&self) -> bool {
136 self.failed
137 }
138
139 #[must_use]
142 pub const fn can_into_inner(&self) -> bool {
143 self.is_finished() && !self.failed
144 }
145
146 #[must_use]
148 pub fn into_inner(mut self) -> R {
149 self.take_inner()
150 }
151
152 #[allow(clippy::result_large_err)]
159 pub fn try_into_inner(mut self) -> Result<R, Self> {
160 if !self.can_into_inner() {
161 return Err(self);
162 }
163 Ok(self.take_inner())
164 }
165
166 fn inner_ref(&self) -> &R {
167 match &self.inner {
168 Some(inner) => inner,
169 None => unreachable!("stream encoder reader inner reader was already taken"),
170 }
171 }
172
173 fn inner_mut(&mut self) -> &mut R {
174 match &mut self.inner {
175 Some(inner) => inner,
176 None => unreachable!("stream encoder reader inner reader was already taken"),
177 }
178 }
179
180 fn take_inner(&mut self) -> R {
181 match self.inner.take() {
182 Some(inner) => inner,
183 None => unreachable!("stream encoder reader inner reader was already taken"),
184 }
185 }
186
187 fn clear_pending(&mut self) {
188 crate::wipe_bytes(&mut self.pending);
189 self.pending_len = 0;
190 }
191}
192
193impl<R, A, const PAD: bool> Drop for EncoderReader<R, A, PAD>
194where
195 A: Alphabet,
196{
197 fn drop(&mut self) {
198 self.clear_pending();
199 self.output.clear_all();
200 }
201}
202
203impl<R, A, const PAD: bool> core::fmt::Debug for EncoderReader<R, A, PAD>
204where
205 A: Alphabet,
206{
207 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
208 formatter
209 .debug_struct("EncoderReader")
210 .field("inner", &redacted_inner_state(self.inner.is_some()))
211 .field("engine", &self.engine)
212 .field("pending", &"<redacted>")
213 .field("pending_len", &self.pending_len)
214 .field("pending_input_needed_len", &self.pending_input_needed_len())
215 .field("buffered_output_len", &self.output.len())
216 .field("buffered_output_capacity", &self.output.capacity())
217 .field(
218 "buffered_output_remaining_capacity",
219 &self.output.available_capacity(),
220 )
221 .field("can_into_inner", &self.can_into_inner())
222 .field("finished", &self.finished)
223 .field("failed", &self.failed)
224 .finish()
225 }
226}
227
228impl<R, A, const PAD: bool> Read for EncoderReader<R, A, PAD>
229where
230 R: Read,
231 A: Alphabet,
232{
233 fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
234 if self.failed {
235 return Err(stream_encoder_failed_error());
236 }
237
238 if output.is_empty() {
239 return Ok(0);
240 }
241
242 while self.output.is_empty() && !self.finished {
243 self.fill_output()?;
244 }
245
246 Ok(self.output.pop_slice(output))
247 }
248}
249
250impl<R, A, const PAD: bool> EncoderReader<R, A, PAD>
251where
252 R: Read,
253 A: Alphabet,
254{
255 fn fill_output(&mut self) -> io::Result<()> {
256 let mut input = [0u8; 768];
257 let read = match self.inner_mut().read(&mut input) {
258 Ok(read) => read,
259 Err(err) => {
260 crate::wipe_bytes(&mut input);
261 return Err(err);
262 }
263 };
264 if read == 0 {
265 crate::wipe_bytes(&mut input);
266 self.finished = true;
267 if let Err(err) = self.push_final_pending() {
268 self.failed = true;
269 return Err(err);
270 }
271 return Ok(());
272 }
273
274 let mut consumed = 0;
275 if self.pending_len > 0 {
276 let needed = 3 - self.pending_len;
277 if read < needed {
278 self.pending[self.pending_len..self.pending_len + read]
279 .copy_from_slice(&input[..read]);
280 self.pending_len += read;
281 crate::wipe_bytes(&mut input);
282 return Ok(());
283 }
284
285 let mut chunk = [0u8; 3];
286 chunk[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
287 chunk[self.pending_len..].copy_from_slice(&input[..needed]);
288 let result = self.push_encoded(&chunk);
289 crate::wipe_bytes(&mut chunk);
290 if let Err(err) = result {
291 crate::wipe_bytes(&mut input);
292 self.failed = true;
293 return Err(err);
294 }
295 self.clear_pending();
296 consumed += needed;
297 }
298
299 let remaining = &input[consumed..read];
300 let full_len = remaining.len() / 3 * 3;
301 let tail_len = remaining.len() - full_len;
302 let mut tail = [0u8; 2];
303 tail[..tail_len].copy_from_slice(&remaining[full_len..]);
304 let result = if full_len > 0 {
305 self.push_encoded(&remaining[..full_len])
306 } else {
307 Ok(())
308 };
309 crate::wipe_bytes(&mut input);
310 if let Err(err) = result {
311 crate::wipe_bytes(&mut tail);
312 self.failed = true;
313 return Err(err);
314 }
315 self.pending[..tail_len].copy_from_slice(&tail[..tail_len]);
316 crate::wipe_bytes(&mut tail);
317 self.pending_len = tail_len;
318 Ok(())
319 }
320
321 fn push_final_pending(&mut self) -> io::Result<()> {
322 if self.pending_len == 0 {
323 return Ok(());
324 }
325
326 let mut pending = [0u8; 2];
327 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
328 let pending_len = self.pending_len;
329 self.clear_pending();
330 let result = self.push_encoded(&pending[..pending_len]);
331 crate::wipe_bytes(&mut pending);
332 result
333 }
334
335 fn push_encoded(&mut self, input: &[u8]) -> io::Result<()> {
336 let mut encoded = [0u8; 1024];
337 let written = match self.engine.encode_slice(input, &mut encoded) {
338 Ok(written) => written,
339 Err(err) => {
340 crate::wipe_bytes(&mut encoded);
341 return Err(encode_error_to_io(err));
342 }
343 };
344 let result = self.output.push_slice(&encoded[..written]);
345 crate::wipe_bytes(&mut encoded);
346 result
347 }
348}