1use super::{
2 DecoderDriver, OutputQueue, 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>
37where
38 A: Alphabet,
39{
40 inner: Option<W>,
41 engine: Engine<A, PAD>,
42 driver: DecoderDriver,
43 output: OutputQueue<1024>,
44 finished: bool,
45 failed: bool,
46 finalized: bool,
47}
48
49impl<W, A, const PAD: bool> Decoder<W, A, PAD>
50where
51 A: Alphabet,
52{
53 #[must_use]
60 pub const fn new(inner: W, engine: Engine<A, PAD>) -> Self {
61 Self {
62 inner: Some(inner),
63 engine,
64 driver: DecoderDriver::new::<A, PAD>(),
65 output: OutputQueue::new(),
66 finished: false,
67 finalized: false,
68 failed: false,
69 }
70 }
71
72 #[must_use]
74 pub fn get_ref(&self) -> &W {
75 self.inner_ref()
76 }
77
78 pub fn get_mut(&mut self) -> &mut W {
80 self.inner_mut()
81 }
82
83 #[must_use]
85 pub const fn engine(&self) -> Engine<A, PAD> {
86 self.engine
87 }
88
89 #[must_use]
91 pub const fn is_padded(&self) -> bool {
92 PAD
93 }
94
95 #[must_use]
98 pub const fn pending_len(&self) -> usize {
99 self.driver.pending_input_len()
100 }
101
102 #[must_use]
105 pub const fn has_pending_input(&self) -> bool {
106 self.pending_len() != 0
107 }
108
109 #[must_use]
114 pub const fn pending_input_needed_len(&self) -> usize {
115 if self.has_pending_input() {
116 4 - self.pending_len()
117 } else {
118 0
119 }
120 }
121
122 #[must_use]
125 pub const fn buffered_output_len(&self) -> usize {
126 self.output.len()
127 }
128
129 #[must_use]
132 pub const fn buffered_output_capacity(&self) -> usize {
133 self.output.capacity()
134 }
135
136 #[must_use]
139 pub const fn buffered_output_remaining_capacity(&self) -> usize {
140 self.output.available_capacity()
141 }
142
143 #[must_use]
146 pub const fn has_buffered_output(&self) -> bool {
147 !self.output.is_empty()
148 }
149
150 #[must_use]
156 pub const fn has_terminal_padding(&self) -> bool {
157 self.finished
158 }
159
160 #[must_use]
164 pub const fn is_finalized(&self) -> bool {
165 self.finalized
166 }
167
168 #[must_use]
174 pub const fn is_failed(&self) -> bool {
175 self.failed
176 }
177
178 #[must_use]
181 pub const fn can_into_inner(&self) -> bool {
182 !self.is_failed() && !self.has_pending_input() && !self.has_buffered_output()
183 }
184
185 #[must_use]
189 pub fn into_inner(mut self) -> W {
190 self.take_inner()
191 }
192
193 #[allow(clippy::result_large_err)]
199 pub fn try_into_inner(mut self) -> Result<W, Self> {
200 if !self.can_into_inner() {
201 return Err(self);
202 }
203 Ok(self.take_inner())
204 }
205
206 fn inner_ref(&self) -> &W {
207 match &self.inner {
208 Some(inner) => inner,
209 None => unreachable!("stream decoder inner writer was already taken"),
210 }
211 }
212
213 fn inner_mut(&mut self) -> &mut W {
214 match &mut self.inner {
215 Some(inner) => inner,
216 None => unreachable!("stream decoder inner writer was already taken"),
217 }
218 }
219
220 fn take_inner(&mut self) -> W {
221 match self.inner.take() {
222 Some(inner) => inner,
223 None => unreachable!("stream decoder inner writer was already taken"),
224 }
225 }
226
227 fn clear_pending(&mut self) {
228 self.driver.wipe();
229 }
230
231 fn clear_output(&mut self) {
232 self.output.clear_all();
233 }
234}
235
236impl<W, A, const PAD: bool> Drop for Decoder<W, A, PAD>
237where
238 A: Alphabet,
239{
240 fn drop(&mut self) {
241 self.clear_pending();
242 self.clear_output();
243 }
244}
245
246impl<W, A, const PAD: bool> core::fmt::Debug for Decoder<W, A, PAD>
247where
248 A: Alphabet,
249{
250 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
251 formatter
252 .debug_struct("Decoder")
253 .field("inner", &redacted_inner_state(self.inner.is_some()))
254 .field("engine", &self.engine)
255 .field("driver", &"<redacted>")
256 .field("pending", &"<redacted>")
257 .field("pending_len", &self.pending_len())
258 .field("pending_input_needed_len", &self.pending_input_needed_len())
259 .field("buffered_output_len", &self.output.len())
260 .field("buffered_output_capacity", &self.output.capacity())
261 .field(
262 "buffered_output_remaining_capacity",
263 &self.output.available_capacity(),
264 )
265 .field("can_into_inner", &self.can_into_inner())
266 .field("terminal_padding", &self.finished)
267 .field("finalized", &self.finalized)
268 .field("failed", &self.failed)
269 .finish()
270 }
271}
272
273impl<W, A, const PAD: bool> Decoder<W, A, PAD>
274where
275 W: Write,
276 A: Alphabet,
277{
278 pub fn try_finish(&mut self) -> io::Result<()> {
288 if self.failed {
289 return Err(stream_decoder_failed_error());
290 }
291 if !self.finalized {
292 self.queue_pending_final()?;
293 self.finalized = true;
294 }
295 self.flush()
296 }
297
298 pub fn finish(mut self) -> io::Result<W> {
300 self.try_finish()?;
301 Ok(self.take_inner())
302 }
303
304 fn queue_pending_final(&mut self) -> io::Result<()> {
305 let mut decoded = [0u8; 3];
306 let step = match self.driver.finish(&mut decoded) {
307 Ok(step) => step,
308 Err(err) => {
309 crate::wipe_bytes(&mut decoded);
310 self.failed = true;
311 self.clear_pending();
312 return Err(err);
313 }
314 };
315 let produced = step.progress().output_produced();
316 let result = self.output.push_slice(&decoded[..produced]);
317 crate::wipe_bytes(&mut decoded);
318 if result.is_err() {
319 self.failed = true;
320 }
321 result
322 }
323
324 fn queue_update(&mut self, input: &[u8]) -> io::Result<usize> {
325 let mut decoded = [0u8; 3];
326 let step = match self.driver.update(input, &mut decoded) {
327 Ok(step) => step,
328 Err(err) => {
329 crate::wipe_bytes(&mut decoded);
330 self.failed = true;
331 self.clear_pending();
332 return Err(err);
333 }
334 };
335 let progress = step.progress();
336 let result = self
337 .output
338 .push_slice(&decoded[..progress.output_produced()]);
339 crate::wipe_bytes(&mut decoded);
340 if result.is_err() {
341 self.failed = true;
342 }
343 result?;
344 self.finished = self.driver.has_terminal_padding();
345 Ok(progress.input_consumed())
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 while consumed < input.len() {
406 let pending = self.pending_len();
407 let take = (4 - pending).min(input.len() - consumed);
408 if pending + take == 4 && self.output.available_capacity() < 3 {
409 break;
410 }
411 match self.queue_update(&input[consumed..consumed + take]) {
412 Ok(accepted) => consumed += accepted,
413 Err(_) if consumed != 0 => return Ok(consumed),
414 Err(err) => return Err(err),
415 }
416 if self.finished || take < 4 - pending {
417 break;
418 }
419 }
420 Ok(consumed)
421 }
422
423 fn flush(&mut self) -> io::Result<()> {
424 if self.failed {
425 return Err(stream_decoder_failed_error());
426 }
427 self.drain_output()?;
428 self.inner_mut().flush()
429 }
430}