1use super::{Alphabet, DecodeError, EncodeError, Engine};
58use std::io::{self, Read, Write};
59
60struct OutputQueue<const CAP: usize> {
61 buffer: [u8; CAP],
62 start: usize,
63 len: usize,
64}
65
66impl<const CAP: usize> OutputQueue<CAP> {
67 const fn new() -> Self {
68 Self {
69 buffer: [0; CAP],
70 start: 0,
71 len: 0,
72 }
73 }
74
75 const fn is_empty(&self) -> bool {
76 self.len == 0
77 }
78
79 const fn len(&self) -> usize {
80 self.len
81 }
82
83 const fn capacity(&self) -> usize {
84 self.len + self.available_capacity()
85 }
86
87 fn push_slice(&mut self, input: &[u8]) -> io::Result<()> {
88 if input.len() > self.available_capacity() {
89 return Err(io::Error::other(
90 "base64 stream output queue capacity exceeded",
91 ));
92 }
93
94 let mut read = 0;
95 while read < input.len() {
96 let write = (self.start + self.len) % CAP;
97 self.buffer[write] = input[read];
98 self.len += 1;
99 read += 1;
100 }
101
102 Ok(())
103 }
104
105 fn copy_front(&self, output: &mut [u8]) -> usize {
106 let count = core::cmp::min(self.len, output.len());
107 let first = core::cmp::min(count, CAP - self.start);
108 output[..first].copy_from_slice(&self.buffer[self.start..self.start + first]);
109
110 let second = count - first;
111 if second > 0 {
112 output[first..first + second].copy_from_slice(&self.buffer[..second]);
113 }
114
115 count
116 }
117
118 fn discard_front(&mut self, count: usize) {
119 let count = core::cmp::min(count, self.len);
120 let first = core::cmp::min(count, CAP - self.start);
121 crate::wipe_bytes(&mut self.buffer[self.start..self.start + first]);
122
123 let second = count - first;
124 if second > 0 {
125 crate::wipe_bytes(&mut self.buffer[..second]);
126 }
127
128 self.start = (self.start + count) % CAP;
129 self.len -= count;
130 if self.len == 0 {
131 self.start = 0;
132 }
133 }
134
135 fn pop_slice(&mut self, output: &mut [u8]) -> usize {
136 let count = self.copy_front(output);
137 self.discard_front(count);
138 count
139 }
140
141 fn clear_all(&mut self) {
142 crate::wipe_bytes(&mut self.buffer);
143 self.start = 0;
144 self.len = 0;
145 }
146
147 const fn available_capacity(&self) -> usize {
148 CAP - self.len
149 }
150}
151
152pub struct Encoder<W, A, const PAD: bool>
160where
161 A: Alphabet,
162{
163 inner: Option<W>,
164 engine: Engine<A, PAD>,
165 pending: [u8; 2],
166 pending_len: usize,
167 output: OutputQueue<1024>,
168 finalized: bool,
169}
170
171impl<W, A, const PAD: bool> Encoder<W, A, PAD>
172where
173 A: Alphabet,
174{
175 #[must_use]
177 pub const fn new(inner: W, engine: Engine<A, PAD>) -> Self {
178 Self {
179 inner: Some(inner),
180 engine,
181 pending: [0; 2],
182 pending_len: 0,
183 output: OutputQueue::new(),
184 finalized: false,
185 }
186 }
187
188 #[must_use]
190 pub fn get_ref(&self) -> &W {
191 self.inner_ref()
192 }
193
194 pub fn get_mut(&mut self) -> &mut W {
196 self.inner_mut()
197 }
198
199 #[must_use]
201 pub const fn engine(&self) -> Engine<A, PAD> {
202 self.engine
203 }
204
205 #[must_use]
207 pub const fn is_padded(&self) -> bool {
208 PAD
209 }
210
211 #[must_use]
214 pub const fn pending_len(&self) -> usize {
215 self.pending_len
216 }
217
218 #[must_use]
221 pub const fn has_pending_input(&self) -> bool {
222 self.pending_len != 0
223 }
224
225 #[must_use]
230 pub const fn pending_input_needed_len(&self) -> usize {
231 if self.has_pending_input() {
232 3 - self.pending_len
233 } else {
234 0
235 }
236 }
237
238 #[must_use]
241 pub const fn buffered_output_len(&self) -> usize {
242 self.output.len()
243 }
244
245 #[must_use]
248 pub const fn buffered_output_capacity(&self) -> usize {
249 self.output.capacity()
250 }
251
252 #[must_use]
255 pub const fn buffered_output_remaining_capacity(&self) -> usize {
256 self.output.available_capacity()
257 }
258
259 #[must_use]
262 pub const fn has_buffered_output(&self) -> bool {
263 !self.output.is_empty()
264 }
265
266 #[must_use]
270 pub const fn is_finalized(&self) -> bool {
271 self.finalized
272 }
273
274 #[must_use]
277 pub const fn can_into_inner(&self) -> bool {
278 !self.has_pending_input() && !self.has_buffered_output()
279 }
280
281 #[must_use]
285 pub fn into_inner(mut self) -> W {
286 self.take_inner()
287 }
288
289 #[allow(clippy::result_large_err)]
295 pub fn try_into_inner(mut self) -> Result<W, Self> {
296 if !self.can_into_inner() {
297 return Err(self);
298 }
299 Ok(self.take_inner())
300 }
301
302 fn inner_ref(&self) -> &W {
303 match &self.inner {
304 Some(inner) => inner,
305 None => unreachable!("stream encoder inner writer was already taken"),
306 }
307 }
308
309 fn inner_mut(&mut self) -> &mut W {
310 match &mut self.inner {
311 Some(inner) => inner,
312 None => unreachable!("stream encoder inner writer was already taken"),
313 }
314 }
315
316 fn take_inner(&mut self) -> W {
317 match self.inner.take() {
318 Some(inner) => inner,
319 None => unreachable!("stream encoder inner writer was already taken"),
320 }
321 }
322
323 fn clear_pending(&mut self) {
324 crate::wipe_bytes(&mut self.pending);
325 self.pending_len = 0;
326 }
327
328 fn clear_output(&mut self) {
329 self.output.clear_all();
330 }
331}
332
333impl<W, A, const PAD: bool> Drop for Encoder<W, A, PAD>
334where
335 A: Alphabet,
336{
337 fn drop(&mut self) {
338 self.clear_pending();
339 self.clear_output();
340 }
341}
342
343impl<W, A, const PAD: bool> core::fmt::Debug for Encoder<W, A, PAD>
344where
345 A: Alphabet,
346{
347 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
348 formatter
349 .debug_struct("Encoder")
350 .field("inner", &redacted_inner_state(self.inner.is_some()))
351 .field("engine", &self.engine)
352 .field("pending", &"<redacted>")
353 .field("pending_len", &self.pending_len)
354 .field("pending_input_needed_len", &self.pending_input_needed_len())
355 .field("buffered_output_len", &self.output.len())
356 .field("buffered_output_capacity", &self.output.capacity())
357 .field(
358 "buffered_output_remaining_capacity",
359 &self.output.available_capacity(),
360 )
361 .field("can_into_inner", &self.can_into_inner())
362 .field("finalized", &self.finalized)
363 .finish()
364 }
365}
366
367impl<W, A, const PAD: bool> Encoder<W, A, PAD>
368where
369 W: Write,
370 A: Alphabet,
371{
372 pub fn try_finish(&mut self) -> io::Result<()> {
382 if !self.finalized {
383 self.queue_pending_final()?;
384 self.finalized = true;
385 }
386 self.flush()
387 }
388
389 pub fn finish(mut self) -> io::Result<W> {
391 self.try_finish()?;
392 Ok(self.take_inner())
393 }
394
395 fn queue_pending_final(&mut self) -> io::Result<()> {
396 if self.pending_len == 0 {
397 return Ok(());
398 }
399
400 let mut pending = [0u8; 2];
401 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
402 let pending_len = self.pending_len;
403 let mut encoded = [0u8; 4];
404 let result = self.queue_encoded_temp(&pending[..pending_len], &mut encoded);
405 crate::wipe_bytes(&mut pending);
406 result?;
407 self.clear_pending();
408 Ok(())
409 }
410
411 fn queue_encoded_temp(&mut self, input: &[u8], encoded: &mut [u8]) -> io::Result<()> {
412 let written = match self.engine.encode_slice(input, encoded) {
413 Ok(written) => written,
414 Err(err) => {
415 crate::wipe_bytes(encoded);
416 return Err(encode_error_to_io(err));
417 }
418 };
419
420 let result = self.output.push_slice(&encoded[..written]);
421 crate::wipe_bytes(encoded);
422 result
423 }
424
425 fn drain_output(&mut self) -> io::Result<()> {
426 let mut chunk = [0u8; 1024];
427 while !self.output.is_empty() {
428 let pending = self.output.copy_front(&mut chunk);
429 let result = self.inner_mut().write(&chunk[..pending]);
430 crate::wipe_bytes(&mut chunk[..pending]);
431 match result {
432 Ok(0) => {
433 return Err(io::Error::new(
434 io::ErrorKind::WriteZero,
435 "base64 stream encoder could not drain buffered output",
436 ));
437 }
438 Ok(written) => {
439 if written > pending {
440 return Err(io::Error::new(
441 io::ErrorKind::InvalidData,
442 "wrapped writer reported more bytes than provided",
443 ));
444 }
445 self.output.discard_front(written);
446 }
447 Err(err) => return Err(err),
448 }
449 }
450
451 Ok(())
452 }
453}
454
455impl<W, A, const PAD: bool> Write for Encoder<W, A, PAD>
456where
457 W: Write,
458 A: Alphabet,
459{
460 fn write(&mut self, input: &[u8]) -> io::Result<usize> {
461 self.drain_output()?;
462 if self.finalized {
463 return Err(io::Error::new(
464 io::ErrorKind::InvalidInput,
465 "base64 stream encoder received input after finalization",
466 ));
467 }
468 if input.is_empty() {
469 return Ok(0);
470 }
471
472 let mut consumed = 0;
473 if self.pending_len > 0 {
474 let needed = 3 - self.pending_len;
475 if input.len() < needed {
476 self.pending[self.pending_len..self.pending_len + input.len()]
477 .copy_from_slice(input);
478 self.pending_len += input.len();
479 return Ok(input.len());
480 }
481
482 let mut chunk = [0u8; 3];
483 chunk[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
484 chunk[self.pending_len..].copy_from_slice(&input[..needed]);
485
486 let mut encoded = [0u8; 4];
487 let result = self.queue_encoded_temp(&chunk, &mut encoded);
488 crate::wipe_bytes(&mut chunk);
489 result?;
490 self.clear_pending();
491 consumed += needed;
492 }
493
494 let remaining = &input[consumed..];
495 let full_len = remaining.len() / 3 * 3;
496 if full_len > 0 {
497 let max_by_queue = self.output.available_capacity() / 4 * 3;
498 let mut take = core::cmp::min(full_len, core::cmp::min(768, max_by_queue));
499 take -= take % 3;
500
501 if take == 0 {
502 return Ok(consumed);
503 }
504
505 let mut encoded = [0u8; 1024];
506 self.queue_encoded_temp(&remaining[..take], &mut encoded)?;
507 consumed += take;
508
509 if take < full_len {
510 return Ok(consumed);
511 }
512 }
513
514 let tail = &input[consumed..];
515 self.pending[..tail.len()].copy_from_slice(tail);
516 self.pending_len = tail.len();
517 consumed += tail.len();
518
519 Ok(consumed)
520 }
521
522 fn flush(&mut self) -> io::Result<()> {
523 self.drain_output()?;
524 self.inner_mut().flush()
525 }
526}
527
528fn encode_error_to_io(err: EncodeError) -> io::Error {
529 io::Error::new(io::ErrorKind::InvalidInput, err)
530}
531
532pub struct Decoder<W, A, const PAD: bool>
548where
549 A: Alphabet,
550{
551 inner: Option<W>,
552 engine: Engine<A, PAD>,
553 pending: [u8; 4],
554 pending_len: usize,
555 output: OutputQueue<1024>,
556 finished: bool,
557 failed: bool,
558 finalized: bool,
559}
560
561impl<W, A, const PAD: bool> Decoder<W, A, PAD>
562where
563 A: Alphabet,
564{
565 #[must_use]
572 pub const fn new(inner: W, engine: Engine<A, PAD>) -> Self {
573 Self {
574 inner: Some(inner),
575 engine,
576 pending: [0; 4],
577 pending_len: 0,
578 output: OutputQueue::new(),
579 finished: false,
580 finalized: false,
581 failed: false,
582 }
583 }
584
585 #[must_use]
587 pub fn get_ref(&self) -> &W {
588 self.inner_ref()
589 }
590
591 pub fn get_mut(&mut self) -> &mut W {
593 self.inner_mut()
594 }
595
596 #[must_use]
598 pub const fn engine(&self) -> Engine<A, PAD> {
599 self.engine
600 }
601
602 #[must_use]
604 pub const fn is_padded(&self) -> bool {
605 PAD
606 }
607
608 #[must_use]
611 pub const fn pending_len(&self) -> usize {
612 self.pending_len
613 }
614
615 #[must_use]
618 pub const fn has_pending_input(&self) -> bool {
619 self.pending_len != 0
620 }
621
622 #[must_use]
627 pub const fn pending_input_needed_len(&self) -> usize {
628 if self.has_pending_input() {
629 4 - self.pending_len
630 } else {
631 0
632 }
633 }
634
635 #[must_use]
638 pub const fn buffered_output_len(&self) -> usize {
639 self.output.len()
640 }
641
642 #[must_use]
645 pub const fn buffered_output_capacity(&self) -> usize {
646 self.output.capacity()
647 }
648
649 #[must_use]
652 pub const fn buffered_output_remaining_capacity(&self) -> usize {
653 self.output.available_capacity()
654 }
655
656 #[must_use]
659 pub const fn has_buffered_output(&self) -> bool {
660 !self.output.is_empty()
661 }
662
663 #[must_use]
669 pub const fn has_terminal_padding(&self) -> bool {
670 self.finished
671 }
672
673 #[must_use]
677 pub const fn is_finalized(&self) -> bool {
678 self.finalized
679 }
680
681 #[must_use]
687 pub const fn is_failed(&self) -> bool {
688 self.failed
689 }
690
691 #[must_use]
694 pub const fn can_into_inner(&self) -> bool {
695 !self.is_failed() && !self.has_pending_input() && !self.has_buffered_output()
696 }
697
698 #[must_use]
702 pub fn into_inner(mut self) -> W {
703 self.take_inner()
704 }
705
706 #[allow(clippy::result_large_err)]
712 pub fn try_into_inner(mut self) -> Result<W, Self> {
713 if !self.can_into_inner() {
714 return Err(self);
715 }
716 Ok(self.take_inner())
717 }
718
719 fn inner_ref(&self) -> &W {
720 match &self.inner {
721 Some(inner) => inner,
722 None => unreachable!("stream decoder inner writer was already taken"),
723 }
724 }
725
726 fn inner_mut(&mut self) -> &mut W {
727 match &mut self.inner {
728 Some(inner) => inner,
729 None => unreachable!("stream decoder inner writer was already taken"),
730 }
731 }
732
733 fn take_inner(&mut self) -> W {
734 match self.inner.take() {
735 Some(inner) => inner,
736 None => unreachable!("stream decoder inner writer was already taken"),
737 }
738 }
739
740 fn clear_pending(&mut self) {
741 crate::wipe_bytes(&mut self.pending);
742 self.pending_len = 0;
743 }
744
745 fn clear_output(&mut self) {
746 self.output.clear_all();
747 }
748}
749
750impl<W, A, const PAD: bool> Drop for Decoder<W, A, PAD>
751where
752 A: Alphabet,
753{
754 fn drop(&mut self) {
755 self.clear_pending();
756 self.clear_output();
757 }
758}
759
760impl<W, A, const PAD: bool> core::fmt::Debug for Decoder<W, A, PAD>
761where
762 A: Alphabet,
763{
764 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
765 formatter
766 .debug_struct("Decoder")
767 .field("inner", &redacted_inner_state(self.inner.is_some()))
768 .field("engine", &self.engine)
769 .field("pending", &"<redacted>")
770 .field("pending_len", &self.pending_len)
771 .field("pending_input_needed_len", &self.pending_input_needed_len())
772 .field("buffered_output_len", &self.output.len())
773 .field("buffered_output_capacity", &self.output.capacity())
774 .field(
775 "buffered_output_remaining_capacity",
776 &self.output.available_capacity(),
777 )
778 .field("can_into_inner", &self.can_into_inner())
779 .field("terminal_padding", &self.finished)
780 .field("finalized", &self.finalized)
781 .field("failed", &self.failed)
782 .finish()
783 }
784}
785
786impl<W, A, const PAD: bool> Decoder<W, A, PAD>
787where
788 W: Write,
789 A: Alphabet,
790{
791 pub fn try_finish(&mut self) -> io::Result<()> {
801 if self.failed {
802 return Err(stream_decoder_failed_error());
803 }
804 if !self.finalized {
805 self.queue_pending_final()?;
806 self.finalized = true;
807 }
808 self.flush()
809 }
810
811 pub fn finish(mut self) -> io::Result<W> {
813 self.try_finish()?;
814 Ok(self.take_inner())
815 }
816
817 fn queue_pending_final(&mut self) -> io::Result<()> {
818 if self.pending_len == 0 {
819 return Ok(());
820 }
821
822 let mut pending = [0u8; 4];
823 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
824 let pending_len = self.pending_len;
825 let mut decoded = [0u8; 3];
826 let result = self.queue_decoded_temp(&pending[..pending_len], &mut decoded);
827 crate::wipe_bytes(&mut pending);
828 if let Err(err) = result {
829 self.clear_pending();
830 return Err(err);
831 }
832 self.clear_pending();
833 Ok(())
834 }
835
836 fn queue_full_quad(&mut self, mut input: [u8; 4]) -> io::Result<()> {
837 let mut decoded = [0u8; 3];
838 let result = self.queue_decoded_temp(&input, &mut decoded);
839 crate::wipe_bytes(&mut input);
840 let written = result?;
841 if written < 3 {
842 self.finished = true;
843 }
844 Ok(())
845 }
846
847 fn queue_decoded_temp(&mut self, input: &[u8], decoded: &mut [u8]) -> io::Result<usize> {
848 let written = match self.engine.decode_slice(input, decoded) {
849 Ok(written) => written,
850 Err(err) => {
851 crate::wipe_bytes(decoded);
852 self.failed = true;
853 return Err(decode_error_to_io(err));
854 }
855 };
856
857 let result = self.output.push_slice(&decoded[..written]);
858 crate::wipe_bytes(decoded);
859 result?;
860 Ok(written)
861 }
862
863 fn drain_output(&mut self) -> io::Result<()> {
864 let mut chunk = [0u8; 1024];
865 while !self.output.is_empty() {
866 let pending = self.output.copy_front(&mut chunk);
867 let result = self.inner_mut().write(&chunk[..pending]);
868 crate::wipe_bytes(&mut chunk[..pending]);
869 match result {
870 Ok(0) => {
871 return Err(io::Error::new(
872 io::ErrorKind::WriteZero,
873 "base64 stream decoder could not drain buffered output",
874 ));
875 }
876 Ok(written) => {
877 if written > pending {
878 return Err(io::Error::new(
879 io::ErrorKind::InvalidData,
880 "wrapped writer reported more bytes than provided",
881 ));
882 }
883 self.output.discard_front(written);
884 }
885 Err(err) => return Err(err),
886 }
887 }
888
889 Ok(())
890 }
891}
892
893impl<W, A, const PAD: bool> Write for Decoder<W, A, PAD>
894where
895 W: Write,
896 A: Alphabet,
897{
898 fn write(&mut self, input: &[u8]) -> io::Result<usize> {
899 if self.failed {
900 return Err(stream_decoder_failed_error());
901 }
902 if input.is_empty() {
903 self.drain_output()?;
904 return Ok(0);
905 }
906 self.drain_output()?;
907 if self.finalized {
908 return Err(io::Error::new(
909 io::ErrorKind::InvalidInput,
910 "base64 stream decoder received input after finalization",
911 ));
912 }
913 if self.finished {
914 self.failed = true;
915 return Err(trailing_input_after_padding_error());
916 }
917
918 let mut consumed = 0;
919 if self.pending_len > 0 {
920 let needed = 4 - self.pending_len;
921 if input.len() < needed {
922 self.pending[self.pending_len..self.pending_len + input.len()]
923 .copy_from_slice(input);
924 self.pending_len += input.len();
925 return Ok(input.len());
926 }
927
928 let mut quad = [0u8; 4];
929 quad[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
930 quad[self.pending_len..].copy_from_slice(&input[..needed]);
931 let result = self.queue_full_quad(quad);
932 crate::wipe_bytes(&mut quad);
933 if let Err(err) = result {
934 self.clear_pending();
935 return Err(err);
936 }
937 self.clear_pending();
938 consumed += needed;
939
940 if self.finished {
941 return Ok(consumed);
942 }
943 }
944
945 while input.len() - consumed >= 4 {
946 if self.output.available_capacity() < 3 {
947 return Ok(consumed);
948 }
949
950 let mut quad = [
951 input[consumed],
952 input[consumed + 1],
953 input[consumed + 2],
954 input[consumed + 3],
955 ];
956 let mut decoded = [0u8; 3];
957 let written = match self.engine.decode_slice(&quad, &mut decoded) {
958 Ok(written) => written,
959 Err(err) => {
960 crate::wipe_bytes(&mut quad);
961 crate::wipe_bytes(&mut decoded);
962 self.failed = true;
963 if consumed > 0 {
964 return Ok(consumed);
965 }
966
967 return Err(decode_error_to_io(err));
968 }
969 };
970
971 let result = self.output.push_slice(&decoded[..written]);
972 crate::wipe_bytes(&mut quad);
973 crate::wipe_bytes(&mut decoded);
974 result?;
975 consumed += 4;
976
977 if written < 3 {
978 self.finished = true;
979 return Ok(consumed);
980 }
981 }
982
983 let tail = &input[consumed..];
984 self.pending[..tail.len()].copy_from_slice(tail);
985 self.pending_len = tail.len();
986 consumed += tail.len();
987
988 Ok(consumed)
989 }
990
991 fn flush(&mut self) -> io::Result<()> {
992 if self.failed {
993 return Err(stream_decoder_failed_error());
994 }
995 self.drain_output()?;
996 self.inner_mut().flush()
997 }
998}
999
1000fn decode_error_to_io(err: DecodeError) -> io::Error {
1001 io::Error::new(io::ErrorKind::InvalidInput, err)
1002}
1003
1004fn trailing_input_after_padding_error() -> io::Error {
1005 io::Error::new(
1006 io::ErrorKind::InvalidInput,
1007 "base64 decoder received trailing input after padding",
1008 )
1009}
1010
1011fn stream_decoder_failed_error() -> io::Error {
1012 io::Error::new(
1013 io::ErrorKind::InvalidInput,
1014 "base64 stream decoder is failed after malformed input",
1015 )
1016}
1017
1018fn stream_encoder_failed_error() -> io::Error {
1019 io::Error::new(
1020 io::ErrorKind::InvalidInput,
1021 "base64 stream encoder is failed after internal error",
1022 )
1023}
1024
1025pub struct DecoderReader<R, A, const PAD: bool>
1040where
1041 A: Alphabet,
1042{
1043 inner: Option<R>,
1044 engine: Engine<A, PAD>,
1045 pending: [u8; 4],
1046 pending_len: usize,
1047 output: OutputQueue<3>,
1048 finished: bool,
1049 terminal_seen: bool,
1050 failed: bool,
1051}
1052
1053impl<R, A, const PAD: bool> DecoderReader<R, A, PAD>
1054where
1055 A: Alphabet,
1056{
1057 #[must_use]
1064 pub fn new(inner: R, engine: Engine<A, PAD>) -> Self {
1065 Self {
1066 inner: Some(inner),
1067 engine,
1068 pending: [0; 4],
1069 pending_len: 0,
1070 output: OutputQueue::new(),
1071 finished: false,
1072 terminal_seen: false,
1073 failed: false,
1074 }
1075 }
1076
1077 #[must_use]
1079 pub fn get_ref(&self) -> &R {
1080 self.inner_ref()
1081 }
1082
1083 pub fn get_mut(&mut self) -> &mut R {
1085 self.inner_mut()
1086 }
1087
1088 #[must_use]
1090 pub const fn engine(&self) -> Engine<A, PAD> {
1091 self.engine
1092 }
1093
1094 #[must_use]
1096 pub const fn is_padded(&self) -> bool {
1097 PAD
1098 }
1099
1100 #[must_use]
1103 pub const fn pending_len(&self) -> usize {
1104 self.pending_len
1105 }
1106
1107 #[must_use]
1110 pub const fn has_pending_input(&self) -> bool {
1111 self.pending_len != 0
1112 }
1113
1114 #[must_use]
1119 pub const fn pending_input_needed_len(&self) -> usize {
1120 if self.has_pending_input() {
1121 4 - self.pending_len
1122 } else {
1123 0
1124 }
1125 }
1126
1127 #[must_use]
1130 pub const fn buffered_output_len(&self) -> usize {
1131 self.output.len()
1132 }
1133
1134 #[must_use]
1137 pub const fn buffered_output_capacity(&self) -> usize {
1138 self.output.capacity()
1139 }
1140
1141 #[must_use]
1144 pub const fn buffered_output_remaining_capacity(&self) -> usize {
1145 self.output.available_capacity()
1146 }
1147
1148 #[must_use]
1151 pub const fn has_buffered_output(&self) -> bool {
1152 !self.output.is_empty()
1153 }
1154
1155 #[must_use]
1162 pub const fn has_terminal_padding(&self) -> bool {
1163 self.terminal_seen
1164 }
1165
1166 #[must_use]
1172 pub const fn has_finished_input(&self) -> bool {
1173 self.finished
1174 }
1175
1176 #[must_use]
1179 pub const fn is_finished(&self) -> bool {
1180 self.finished && self.output.is_empty()
1181 }
1182
1183 #[must_use]
1190 pub const fn is_failed(&self) -> bool {
1191 self.failed
1192 }
1193
1194 #[must_use]
1197 pub const fn can_into_inner(&self) -> bool {
1198 !self.is_failed() && self.is_finished()
1199 }
1200
1201 #[must_use]
1203 pub fn into_inner(mut self) -> R {
1204 self.take_inner()
1205 }
1206
1207 #[allow(clippy::result_large_err)]
1215 pub fn try_into_inner(mut self) -> Result<R, Self> {
1216 if !self.can_into_inner() {
1217 return Err(self);
1218 }
1219 Ok(self.take_inner())
1220 }
1221
1222 fn inner_ref(&self) -> &R {
1223 match &self.inner {
1224 Some(inner) => inner,
1225 None => unreachable!("stream decoder reader inner reader was already taken"),
1226 }
1227 }
1228
1229 fn inner_mut(&mut self) -> &mut R {
1230 match &mut self.inner {
1231 Some(inner) => inner,
1232 None => unreachable!("stream decoder reader inner reader was already taken"),
1233 }
1234 }
1235
1236 fn take_inner(&mut self) -> R {
1237 match self.inner.take() {
1238 Some(inner) => inner,
1239 None => unreachable!("stream decoder reader inner reader was already taken"),
1240 }
1241 }
1242
1243 fn clear_pending(&mut self) {
1244 crate::wipe_bytes(&mut self.pending);
1245 self.pending_len = 0;
1246 }
1247}
1248
1249impl<R, A, const PAD: bool> Drop for DecoderReader<R, A, PAD>
1250where
1251 A: Alphabet,
1252{
1253 fn drop(&mut self) {
1254 self.clear_pending();
1255 self.output.clear_all();
1256 }
1257}
1258
1259impl<R, A, const PAD: bool> core::fmt::Debug for DecoderReader<R, A, PAD>
1260where
1261 A: Alphabet,
1262{
1263 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1264 formatter
1265 .debug_struct("DecoderReader")
1266 .field("inner", &redacted_inner_state(self.inner.is_some()))
1267 .field("engine", &self.engine)
1268 .field("pending", &"<redacted>")
1269 .field("pending_len", &self.pending_len)
1270 .field("pending_input_needed_len", &self.pending_input_needed_len())
1271 .field("buffered_output_len", &self.output.len())
1272 .field("buffered_output_capacity", &self.output.capacity())
1273 .field(
1274 "buffered_output_remaining_capacity",
1275 &self.output.available_capacity(),
1276 )
1277 .field("can_into_inner", &self.can_into_inner())
1278 .field("finished", &self.finished)
1279 .field("terminal_padding", &self.terminal_seen)
1280 .field("failed", &self.failed)
1281 .finish()
1282 }
1283}
1284
1285impl<R, A, const PAD: bool> Read for DecoderReader<R, A, PAD>
1286where
1287 R: Read,
1288 A: Alphabet,
1289{
1290 fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
1291 if output.is_empty() {
1292 return Ok(0);
1293 }
1294 if self.failed {
1295 return Err(stream_decoder_failed_error());
1296 }
1297
1298 while self.output.is_empty() && !self.finished {
1299 self.fill_output()?;
1300 }
1301
1302 Ok(self.output.pop_slice(output))
1303 }
1304}
1305
1306impl<R, A, const PAD: bool> DecoderReader<R, A, PAD>
1307where
1308 R: Read,
1309 A: Alphabet,
1310{
1311 fn fill_output(&mut self) -> io::Result<()> {
1312 if self.failed {
1313 return Err(stream_decoder_failed_error());
1314 }
1315 if self.terminal_seen {
1316 self.finished = true;
1317 return Ok(());
1318 }
1319
1320 let mut input = [0u8; 4];
1321 let available = 4 - self.pending_len;
1322 let read = match self.inner_mut().read(&mut input[..available]) {
1323 Ok(read) => read,
1324 Err(err) => {
1325 crate::wipe_bytes(&mut input);
1326 return Err(err);
1327 }
1328 };
1329 if read == 0 {
1330 crate::wipe_bytes(&mut input);
1331 self.finished = true;
1332 self.push_final_pending()?;
1333 return Ok(());
1334 }
1335
1336 self.pending[self.pending_len..self.pending_len + read].copy_from_slice(&input[..read]);
1337 crate::wipe_bytes(&mut input);
1338 self.pending_len += read;
1339 if self.pending_len < 4 {
1340 return Ok(());
1341 }
1342
1343 let mut quad = self.pending;
1344 self.clear_pending();
1345 let result = self.push_decoded(&quad);
1346 crate::wipe_bytes(&mut quad);
1347 result?;
1348 if self.terminal_seen {
1349 self.finished = true;
1350 }
1351 Ok(())
1352 }
1353
1354 fn push_final_pending(&mut self) -> io::Result<()> {
1355 if self.pending_len == 0 {
1356 return Ok(());
1357 }
1358
1359 let mut pending = [0u8; 4];
1360 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
1361 let pending_len = self.pending_len;
1362 self.clear_pending();
1363 let result = self.push_decoded(&pending[..pending_len]);
1364 crate::wipe_bytes(&mut pending);
1365 result
1366 }
1367
1368 fn push_decoded(&mut self, input: &[u8]) -> io::Result<()> {
1369 let mut decoded = [0u8; 3];
1370 let written = match self.engine.decode_slice(input, &mut decoded) {
1371 Ok(written) => written,
1372 Err(err) => {
1373 crate::wipe_bytes(&mut decoded);
1374 self.failed = true;
1375 return Err(decode_error_to_io(err));
1376 }
1377 };
1378 let result = self.output.push_slice(&decoded[..written]);
1379 crate::wipe_bytes(&mut decoded);
1380 result?;
1381 if input.len() == 4 && written < 3 {
1382 self.terminal_seen = true;
1383 }
1384 Ok(())
1385 }
1386}
1387
1388pub struct EncoderReader<R, A, const PAD: bool>
1390where
1391 A: Alphabet,
1392{
1393 inner: Option<R>,
1394 engine: Engine<A, PAD>,
1395 pending: [u8; 2],
1396 pending_len: usize,
1397 output: OutputQueue<1024>,
1398 finished: bool,
1399 failed: bool,
1400}
1401
1402impl<R, A, const PAD: bool> EncoderReader<R, A, PAD>
1403where
1404 A: Alphabet,
1405{
1406 #[must_use]
1408 pub fn new(inner: R, engine: Engine<A, PAD>) -> Self {
1409 Self {
1410 inner: Some(inner),
1411 engine,
1412 pending: [0; 2],
1413 pending_len: 0,
1414 output: OutputQueue::new(),
1415 finished: false,
1416 failed: false,
1417 }
1418 }
1419
1420 #[must_use]
1422 pub fn get_ref(&self) -> &R {
1423 self.inner_ref()
1424 }
1425
1426 pub fn get_mut(&mut self) -> &mut R {
1428 self.inner_mut()
1429 }
1430
1431 #[must_use]
1433 pub const fn engine(&self) -> Engine<A, PAD> {
1434 self.engine
1435 }
1436
1437 #[must_use]
1439 pub const fn is_padded(&self) -> bool {
1440 PAD
1441 }
1442
1443 #[must_use]
1446 pub const fn pending_len(&self) -> usize {
1447 self.pending_len
1448 }
1449
1450 #[must_use]
1453 pub const fn has_pending_input(&self) -> bool {
1454 self.pending_len != 0
1455 }
1456
1457 #[must_use]
1462 pub const fn pending_input_needed_len(&self) -> usize {
1463 if self.has_pending_input() {
1464 3 - self.pending_len
1465 } else {
1466 0
1467 }
1468 }
1469
1470 #[must_use]
1473 pub const fn buffered_output_len(&self) -> usize {
1474 self.output.len()
1475 }
1476
1477 #[must_use]
1480 pub const fn buffered_output_capacity(&self) -> usize {
1481 self.output.capacity()
1482 }
1483
1484 #[must_use]
1487 pub const fn buffered_output_remaining_capacity(&self) -> usize {
1488 self.output.available_capacity()
1489 }
1490
1491 #[must_use]
1494 pub const fn has_buffered_output(&self) -> bool {
1495 !self.output.is_empty()
1496 }
1497
1498 #[must_use]
1504 pub const fn has_finished_input(&self) -> bool {
1505 self.finished
1506 }
1507
1508 #[must_use]
1511 pub const fn is_finished(&self) -> bool {
1512 self.finished && self.output.is_empty()
1513 }
1514
1515 #[must_use]
1518 pub const fn is_failed(&self) -> bool {
1519 self.failed
1520 }
1521
1522 #[must_use]
1525 pub const fn can_into_inner(&self) -> bool {
1526 self.is_finished() && !self.failed
1527 }
1528
1529 #[must_use]
1531 pub fn into_inner(mut self) -> R {
1532 self.take_inner()
1533 }
1534
1535 #[allow(clippy::result_large_err)]
1542 pub fn try_into_inner(mut self) -> Result<R, Self> {
1543 if !self.can_into_inner() {
1544 return Err(self);
1545 }
1546 Ok(self.take_inner())
1547 }
1548
1549 fn inner_ref(&self) -> &R {
1550 match &self.inner {
1551 Some(inner) => inner,
1552 None => unreachable!("stream encoder reader inner reader was already taken"),
1553 }
1554 }
1555
1556 fn inner_mut(&mut self) -> &mut R {
1557 match &mut self.inner {
1558 Some(inner) => inner,
1559 None => unreachable!("stream encoder reader inner reader was already taken"),
1560 }
1561 }
1562
1563 fn take_inner(&mut self) -> R {
1564 match self.inner.take() {
1565 Some(inner) => inner,
1566 None => unreachable!("stream encoder reader inner reader was already taken"),
1567 }
1568 }
1569
1570 fn clear_pending(&mut self) {
1571 crate::wipe_bytes(&mut self.pending);
1572 self.pending_len = 0;
1573 }
1574}
1575
1576impl<R, A, const PAD: bool> Drop for EncoderReader<R, A, PAD>
1577where
1578 A: Alphabet,
1579{
1580 fn drop(&mut self) {
1581 self.clear_pending();
1582 self.output.clear_all();
1583 }
1584}
1585
1586impl<R, A, const PAD: bool> core::fmt::Debug for EncoderReader<R, A, PAD>
1587where
1588 A: Alphabet,
1589{
1590 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1591 formatter
1592 .debug_struct("EncoderReader")
1593 .field("inner", &redacted_inner_state(self.inner.is_some()))
1594 .field("engine", &self.engine)
1595 .field("pending", &"<redacted>")
1596 .field("pending_len", &self.pending_len)
1597 .field("pending_input_needed_len", &self.pending_input_needed_len())
1598 .field("buffered_output_len", &self.output.len())
1599 .field("buffered_output_capacity", &self.output.capacity())
1600 .field(
1601 "buffered_output_remaining_capacity",
1602 &self.output.available_capacity(),
1603 )
1604 .field("can_into_inner", &self.can_into_inner())
1605 .field("finished", &self.finished)
1606 .field("failed", &self.failed)
1607 .finish()
1608 }
1609}
1610
1611impl<R, A, const PAD: bool> Read for EncoderReader<R, A, PAD>
1612where
1613 R: Read,
1614 A: Alphabet,
1615{
1616 fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
1617 if self.failed {
1618 return Err(stream_encoder_failed_error());
1619 }
1620
1621 if output.is_empty() {
1622 return Ok(0);
1623 }
1624
1625 while self.output.is_empty() && !self.finished {
1626 self.fill_output()?;
1627 }
1628
1629 Ok(self.output.pop_slice(output))
1630 }
1631}
1632
1633impl<R, A, const PAD: bool> EncoderReader<R, A, PAD>
1634where
1635 R: Read,
1636 A: Alphabet,
1637{
1638 fn fill_output(&mut self) -> io::Result<()> {
1639 let mut input = [0u8; 768];
1640 let read = match self.inner_mut().read(&mut input) {
1641 Ok(read) => read,
1642 Err(err) => {
1643 crate::wipe_bytes(&mut input);
1644 return Err(err);
1645 }
1646 };
1647 if read == 0 {
1648 crate::wipe_bytes(&mut input);
1649 self.finished = true;
1650 if let Err(err) = self.push_final_pending() {
1651 self.failed = true;
1652 return Err(err);
1653 }
1654 return Ok(());
1655 }
1656
1657 let mut consumed = 0;
1658 if self.pending_len > 0 {
1659 let needed = 3 - self.pending_len;
1660 if read < needed {
1661 self.pending[self.pending_len..self.pending_len + read]
1662 .copy_from_slice(&input[..read]);
1663 self.pending_len += read;
1664 crate::wipe_bytes(&mut input);
1665 return Ok(());
1666 }
1667
1668 let mut chunk = [0u8; 3];
1669 chunk[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
1670 chunk[self.pending_len..].copy_from_slice(&input[..needed]);
1671 let result = self.push_encoded(&chunk);
1672 crate::wipe_bytes(&mut chunk);
1673 if let Err(err) = result {
1674 crate::wipe_bytes(&mut input);
1675 self.failed = true;
1676 return Err(err);
1677 }
1678 self.clear_pending();
1679 consumed += needed;
1680 }
1681
1682 let remaining = &input[consumed..read];
1683 let full_len = remaining.len() / 3 * 3;
1684 let tail_len = remaining.len() - full_len;
1685 let mut tail = [0u8; 2];
1686 tail[..tail_len].copy_from_slice(&remaining[full_len..]);
1687 let result = if full_len > 0 {
1688 self.push_encoded(&remaining[..full_len])
1689 } else {
1690 Ok(())
1691 };
1692 crate::wipe_bytes(&mut input);
1693 if let Err(err) = result {
1694 crate::wipe_bytes(&mut tail);
1695 self.failed = true;
1696 return Err(err);
1697 }
1698 self.pending[..tail_len].copy_from_slice(&tail[..tail_len]);
1699 crate::wipe_bytes(&mut tail);
1700 self.pending_len = tail_len;
1701 Ok(())
1702 }
1703
1704 fn push_final_pending(&mut self) -> io::Result<()> {
1705 if self.pending_len == 0 {
1706 return Ok(());
1707 }
1708
1709 let mut pending = [0u8; 2];
1710 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
1711 let pending_len = self.pending_len;
1712 self.clear_pending();
1713 let result = self.push_encoded(&pending[..pending_len]);
1714 crate::wipe_bytes(&mut pending);
1715 result
1716 }
1717
1718 fn push_encoded(&mut self, input: &[u8]) -> io::Result<()> {
1719 let mut encoded = [0u8; 1024];
1720 let written = match self.engine.encode_slice(input, &mut encoded) {
1721 Ok(written) => written,
1722 Err(err) => {
1723 crate::wipe_bytes(&mut encoded);
1724 return Err(encode_error_to_io(err));
1725 }
1726 };
1727 let result = self.output.push_slice(&encoded[..written]);
1728 crate::wipe_bytes(&mut encoded);
1729 result
1730 }
1731}
1732
1733const fn redacted_inner_state(present: bool) -> &'static str {
1734 if present { "<present>" } else { "<taken>" }
1735}