1use super::{
2 OutputQueue, decode_error_to_io, redacted_inner_state, stream_decoder_failed_error,
3 trailing_input_after_padding_error,
4};
5use crate::{Alphabet, Engine};
6use std::io::{self, Write};
7
8pub struct Decoder<W, A, const PAD: bool>
30where
31 A: Alphabet,
32{
33 inner: Option<W>,
34 engine: Engine<A, PAD>,
35 pending: [u8; 4],
36 pending_len: usize,
37 output: OutputQueue<1024>,
38 finished: bool,
39 failed: bool,
40 finalized: bool,
41}
42
43impl<W, A, const PAD: bool> Decoder<W, A, PAD>
44where
45 A: Alphabet,
46{
47 #[must_use]
54 pub const fn new(inner: W, engine: Engine<A, PAD>) -> Self {
55 Self {
56 inner: Some(inner),
57 engine,
58 pending: [0; 4],
59 pending_len: 0,
60 output: OutputQueue::new(),
61 finished: false,
62 finalized: false,
63 failed: false,
64 }
65 }
66
67 #[must_use]
69 pub fn get_ref(&self) -> &W {
70 self.inner_ref()
71 }
72
73 pub fn get_mut(&mut self) -> &mut W {
75 self.inner_mut()
76 }
77
78 #[must_use]
80 pub const fn engine(&self) -> Engine<A, PAD> {
81 self.engine
82 }
83
84 #[must_use]
86 pub const fn is_padded(&self) -> bool {
87 PAD
88 }
89
90 #[must_use]
93 pub const fn pending_len(&self) -> usize {
94 self.pending_len
95 }
96
97 #[must_use]
100 pub const fn has_pending_input(&self) -> bool {
101 self.pending_len != 0
102 }
103
104 #[must_use]
109 pub const fn pending_input_needed_len(&self) -> usize {
110 if self.has_pending_input() {
111 4 - self.pending_len
112 } else {
113 0
114 }
115 }
116
117 #[must_use]
120 pub const fn buffered_output_len(&self) -> usize {
121 self.output.len()
122 }
123
124 #[must_use]
127 pub const fn buffered_output_capacity(&self) -> usize {
128 self.output.capacity()
129 }
130
131 #[must_use]
134 pub const fn buffered_output_remaining_capacity(&self) -> usize {
135 self.output.available_capacity()
136 }
137
138 #[must_use]
141 pub const fn has_buffered_output(&self) -> bool {
142 !self.output.is_empty()
143 }
144
145 #[must_use]
151 pub const fn has_terminal_padding(&self) -> bool {
152 self.finished
153 }
154
155 #[must_use]
159 pub const fn is_finalized(&self) -> bool {
160 self.finalized
161 }
162
163 #[must_use]
169 pub const fn is_failed(&self) -> bool {
170 self.failed
171 }
172
173 #[must_use]
176 pub const fn can_into_inner(&self) -> bool {
177 !self.is_failed() && !self.has_pending_input() && !self.has_buffered_output()
178 }
179
180 #[must_use]
184 pub fn into_inner(mut self) -> W {
185 self.take_inner()
186 }
187
188 #[allow(clippy::result_large_err)]
194 pub fn try_into_inner(mut self) -> Result<W, Self> {
195 if !self.can_into_inner() {
196 return Err(self);
197 }
198 Ok(self.take_inner())
199 }
200
201 fn inner_ref(&self) -> &W {
202 match &self.inner {
203 Some(inner) => inner,
204 None => unreachable!("stream decoder inner writer was already taken"),
205 }
206 }
207
208 fn inner_mut(&mut self) -> &mut W {
209 match &mut self.inner {
210 Some(inner) => inner,
211 None => unreachable!("stream decoder inner writer was already taken"),
212 }
213 }
214
215 fn take_inner(&mut self) -> W {
216 match self.inner.take() {
217 Some(inner) => inner,
218 None => unreachable!("stream decoder inner writer was already taken"),
219 }
220 }
221
222 fn clear_pending(&mut self) {
223 crate::wipe_bytes(&mut self.pending);
224 self.pending_len = 0;
225 }
226
227 fn clear_output(&mut self) {
228 self.output.clear_all();
229 }
230}
231
232impl<W, A, const PAD: bool> Drop for Decoder<W, A, PAD>
233where
234 A: Alphabet,
235{
236 fn drop(&mut self) {
237 self.clear_pending();
238 self.clear_output();
239 }
240}
241
242impl<W, A, const PAD: bool> core::fmt::Debug for Decoder<W, A, PAD>
243where
244 A: Alphabet,
245{
246 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
247 formatter
248 .debug_struct("Decoder")
249 .field("inner", &redacted_inner_state(self.inner.is_some()))
250 .field("engine", &self.engine)
251 .field("pending", &"<redacted>")
252 .field("pending_len", &self.pending_len)
253 .field("pending_input_needed_len", &self.pending_input_needed_len())
254 .field("buffered_output_len", &self.output.len())
255 .field("buffered_output_capacity", &self.output.capacity())
256 .field(
257 "buffered_output_remaining_capacity",
258 &self.output.available_capacity(),
259 )
260 .field("can_into_inner", &self.can_into_inner())
261 .field("terminal_padding", &self.finished)
262 .field("finalized", &self.finalized)
263 .field("failed", &self.failed)
264 .finish()
265 }
266}
267
268impl<W, A, const PAD: bool> Decoder<W, A, PAD>
269where
270 W: Write,
271 A: Alphabet,
272{
273 pub fn try_finish(&mut self) -> io::Result<()> {
283 if self.failed {
284 return Err(stream_decoder_failed_error());
285 }
286 if !self.finalized {
287 self.queue_pending_final()?;
288 self.finalized = true;
289 }
290 self.flush()
291 }
292
293 pub fn finish(mut self) -> io::Result<W> {
295 self.try_finish()?;
296 Ok(self.take_inner())
297 }
298
299 fn queue_pending_final(&mut self) -> io::Result<()> {
300 if self.pending_len == 0 {
301 return Ok(());
302 }
303
304 let mut pending = [0u8; 4];
305 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
306 let pending_len = self.pending_len;
307 let mut decoded = [0u8; 3];
308 let result = self.queue_decoded_temp(&pending[..pending_len], &mut decoded);
309 crate::wipe_bytes(&mut pending);
310 if let Err(err) = result {
311 self.clear_pending();
312 return Err(err);
313 }
314 self.clear_pending();
315 Ok(())
316 }
317
318 fn queue_full_quad(&mut self, mut input: [u8; 4]) -> io::Result<()> {
319 let mut decoded = [0u8; 3];
320 let result = self.queue_decoded_temp(&input, &mut decoded);
321 crate::wipe_bytes(&mut input);
322 let written = result?;
323 if written < 3 {
324 self.finished = true;
325 }
326 Ok(())
327 }
328
329 fn queue_decoded_temp(&mut self, input: &[u8], decoded: &mut [u8]) -> io::Result<usize> {
330 let written = match self.engine.decode_slice(input, decoded) {
331 Ok(written) => written,
332 Err(err) => {
333 crate::wipe_bytes(decoded);
334 self.failed = true;
335 return Err(decode_error_to_io(err));
336 }
337 };
338
339 let result = self.output.push_slice(&decoded[..written]);
340 crate::wipe_bytes(decoded);
341 if result.is_err() {
342 self.failed = true;
343 }
344 result?;
345 Ok(written)
346 }
347
348 fn drain_output(&mut self) -> io::Result<()> {
349 let mut chunk = [0u8; 1024];
350 while !self.output.is_empty() {
351 let pending = self.output.copy_front(&mut chunk);
352 let result = self.inner_mut().write(&chunk[..pending]);
353 crate::wipe_bytes(&mut chunk[..pending]);
354 match result {
355 Ok(0) => {
356 return Err(io::Error::new(
357 io::ErrorKind::WriteZero,
358 "base64 stream decoder could not drain buffered output",
359 ));
360 }
361 Ok(written) => {
362 if written > pending {
363 self.failed = true;
364 return Err(io::Error::new(
365 io::ErrorKind::InvalidData,
366 "wrapped writer reported more bytes than provided",
367 ));
368 }
369 self.output.discard_front(written);
370 }
371 Err(err) => return Err(err),
372 }
373 }
374
375 Ok(())
376 }
377}
378
379impl<W, A, const PAD: bool> Write for Decoder<W, A, PAD>
380where
381 W: Write,
382 A: Alphabet,
383{
384 fn write(&mut self, input: &[u8]) -> io::Result<usize> {
385 if self.failed {
386 return Err(stream_decoder_failed_error());
387 }
388 if input.is_empty() {
389 self.drain_output()?;
390 return Ok(0);
391 }
392 self.drain_output()?;
393 if self.finalized {
394 return Err(io::Error::new(
395 io::ErrorKind::InvalidInput,
396 "base64 stream decoder received input after finalization",
397 ));
398 }
399 if self.finished {
400 self.failed = true;
401 return Err(trailing_input_after_padding_error());
402 }
403
404 let mut consumed = 0;
405 if self.pending_len > 0 {
406 let needed = 4 - self.pending_len;
407 if input.len() < needed {
408 self.pending[self.pending_len..self.pending_len + input.len()]
409 .copy_from_slice(input);
410 self.pending_len += input.len();
411 return Ok(input.len());
412 }
413
414 let mut quad = [0u8; 4];
415 quad[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
416 quad[self.pending_len..].copy_from_slice(&input[..needed]);
417 let result = self.queue_full_quad(quad);
418 crate::wipe_bytes(&mut quad);
419 if let Err(err) = result {
420 self.clear_pending();
421 return Err(err);
422 }
423 self.clear_pending();
424 consumed += needed;
425
426 if self.finished {
427 return Ok(consumed);
428 }
429 }
430
431 while input.len() - consumed >= 4 {
432 if self.output.available_capacity() < 3 {
433 return Ok(consumed);
434 }
435
436 let mut quad = [
437 input[consumed],
438 input[consumed + 1],
439 input[consumed + 2],
440 input[consumed + 3],
441 ];
442 let mut decoded = [0u8; 3];
443 let written = match self.engine.decode_slice(&quad, &mut decoded) {
444 Ok(written) => written,
445 Err(err) => {
446 crate::wipe_bytes(&mut quad);
447 crate::wipe_bytes(&mut decoded);
448 self.failed = true;
449 if consumed > 0 {
450 return Ok(consumed);
451 }
452
453 return Err(decode_error_to_io(err));
454 }
455 };
456
457 let result = self.output.push_slice(&decoded[..written]);
458 crate::wipe_bytes(&mut quad);
459 crate::wipe_bytes(&mut decoded);
460 result?;
461 consumed += 4;
462
463 if written < 3 {
464 self.finished = true;
465 return Ok(consumed);
466 }
467 }
468
469 let tail = &input[consumed..];
470 self.pending[..tail.len()].copy_from_slice(tail);
471 self.pending_len = tail.len();
472 consumed += tail.len();
473
474 Ok(consumed)
475 }
476
477 fn flush(&mut self) -> io::Result<()> {
478 if self.failed {
479 return Err(stream_decoder_failed_error());
480 }
481 self.drain_output()?;
482 self.inner_mut().flush()
483 }
484}