1use super::{Alphabet, DecodeError, EncodeError, Engine};
69use std::io::{self, Read, Write};
70
71struct OutputQueue<const CAP: usize> {
72 buffer: [u8; CAP],
73 start: usize,
74 len: usize,
75}
76
77impl<const CAP: usize> OutputQueue<CAP> {
78 const fn new() -> Self {
79 Self {
80 buffer: [0; CAP],
81 start: 0,
82 len: 0,
83 }
84 }
85
86 const fn is_empty(&self) -> bool {
87 self.len == 0
88 }
89
90 const fn len(&self) -> usize {
91 self.len
92 }
93
94 const fn capacity(&self) -> usize {
95 self.len + self.available_capacity()
96 }
97
98 fn push_slice(&mut self, input: &[u8]) -> io::Result<()> {
99 if input.len() > self.available_capacity() {
100 return Err(io::Error::other(
101 "base64 stream output queue capacity exceeded",
102 ));
103 }
104
105 let mut read = 0;
106 while read < input.len() {
107 let write = (self.start + self.len) % CAP;
108 self.buffer[write] = input[read];
109 self.len += 1;
110 read += 1;
111 }
112
113 Ok(())
114 }
115
116 fn copy_front(&self, output: &mut [u8]) -> usize {
117 let count = core::cmp::min(self.len, output.len());
118 let first = core::cmp::min(count, CAP - self.start);
119 output[..first].copy_from_slice(&self.buffer[self.start..self.start + first]);
120
121 let second = count - first;
122 if second > 0 {
123 output[first..first + second].copy_from_slice(&self.buffer[..second]);
124 }
125
126 count
127 }
128
129 fn discard_front(&mut self, count: usize) {
130 let count = core::cmp::min(count, self.len);
131 let first = core::cmp::min(count, CAP - self.start);
132 crate::wipe_bytes(&mut self.buffer[self.start..self.start + first]);
133
134 let second = count - first;
135 if second > 0 {
136 crate::wipe_bytes(&mut self.buffer[..second]);
137 }
138
139 self.start = (self.start + count) % CAP;
140 self.len -= count;
141 if self.len == 0 {
142 self.start = 0;
143 }
144 }
145
146 fn pop_slice(&mut self, output: &mut [u8]) -> usize {
147 let count = self.copy_front(output);
148 self.discard_front(count);
149 count
150 }
151
152 fn clear_all(&mut self) {
153 crate::wipe_bytes(&mut self.buffer);
154 self.start = 0;
155 self.len = 0;
156 }
157
158 const fn available_capacity(&self) -> usize {
159 CAP - self.len
160 }
161}
162
163pub struct Encoder<W, A, const PAD: bool>
171where
172 A: Alphabet,
173{
174 inner: Option<W>,
175 engine: Engine<A, PAD>,
176 pending: [u8; 2],
177 pending_len: usize,
178 output: OutputQueue<1024>,
179 finalized: bool,
180 failed: bool,
181}
182
183impl<W, A, const PAD: bool> Encoder<W, A, PAD>
184where
185 A: Alphabet,
186{
187 #[must_use]
189 pub const fn new(inner: W, engine: Engine<A, PAD>) -> Self {
190 Self {
191 inner: Some(inner),
192 engine,
193 pending: [0; 2],
194 pending_len: 0,
195 output: OutputQueue::new(),
196 finalized: false,
197 failed: false,
198 }
199 }
200
201 #[must_use]
203 pub fn get_ref(&self) -> &W {
204 self.inner_ref()
205 }
206
207 pub fn get_mut(&mut self) -> &mut W {
209 self.inner_mut()
210 }
211
212 #[must_use]
214 pub const fn engine(&self) -> Engine<A, PAD> {
215 self.engine
216 }
217
218 #[must_use]
220 pub const fn is_padded(&self) -> bool {
221 PAD
222 }
223
224 #[must_use]
227 pub const fn pending_len(&self) -> usize {
228 self.pending_len
229 }
230
231 #[must_use]
234 pub const fn has_pending_input(&self) -> bool {
235 self.pending_len != 0
236 }
237
238 #[must_use]
243 pub const fn pending_input_needed_len(&self) -> usize {
244 if self.has_pending_input() {
245 3 - self.pending_len
246 } else {
247 0
248 }
249 }
250
251 #[must_use]
254 pub const fn buffered_output_len(&self) -> usize {
255 self.output.len()
256 }
257
258 #[must_use]
261 pub const fn buffered_output_capacity(&self) -> usize {
262 self.output.capacity()
263 }
264
265 #[must_use]
268 pub const fn buffered_output_remaining_capacity(&self) -> usize {
269 self.output.available_capacity()
270 }
271
272 #[must_use]
275 pub const fn has_buffered_output(&self) -> bool {
276 !self.output.is_empty()
277 }
278
279 #[must_use]
283 pub const fn is_finalized(&self) -> bool {
284 self.finalized
285 }
286
287 #[must_use]
295 pub const fn is_failed(&self) -> bool {
296 self.failed
297 }
298
299 #[must_use]
302 pub const fn can_into_inner(&self) -> bool {
303 !self.is_failed() && !self.has_pending_input() && !self.has_buffered_output()
304 }
305
306 #[must_use]
310 pub fn into_inner(mut self) -> W {
311 self.take_inner()
312 }
313
314 #[allow(clippy::result_large_err)]
320 pub fn try_into_inner(mut self) -> Result<W, Self> {
321 if !self.can_into_inner() {
322 return Err(self);
323 }
324 Ok(self.take_inner())
325 }
326
327 fn inner_ref(&self) -> &W {
328 match &self.inner {
329 Some(inner) => inner,
330 None => unreachable!("stream encoder inner writer was already taken"),
331 }
332 }
333
334 fn inner_mut(&mut self) -> &mut W {
335 match &mut self.inner {
336 Some(inner) => inner,
337 None => unreachable!("stream encoder inner writer was already taken"),
338 }
339 }
340
341 fn take_inner(&mut self) -> W {
342 match self.inner.take() {
343 Some(inner) => inner,
344 None => unreachable!("stream encoder inner writer was already taken"),
345 }
346 }
347
348 fn clear_pending(&mut self) {
349 crate::wipe_bytes(&mut self.pending);
350 self.pending_len = 0;
351 }
352
353 fn clear_output(&mut self) {
354 self.output.clear_all();
355 }
356}
357
358impl<W, A, const PAD: bool> Drop for Encoder<W, A, PAD>
359where
360 A: Alphabet,
361{
362 fn drop(&mut self) {
363 self.clear_pending();
364 self.clear_output();
365 }
366}
367
368impl<W, A, const PAD: bool> core::fmt::Debug for Encoder<W, A, PAD>
369where
370 A: Alphabet,
371{
372 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
373 formatter
374 .debug_struct("Encoder")
375 .field("inner", &redacted_inner_state(self.inner.is_some()))
376 .field("engine", &self.engine)
377 .field("pending", &"<redacted>")
378 .field("pending_len", &self.pending_len)
379 .field("pending_input_needed_len", &self.pending_input_needed_len())
380 .field("buffered_output_len", &self.output.len())
381 .field("buffered_output_capacity", &self.output.capacity())
382 .field(
383 "buffered_output_remaining_capacity",
384 &self.output.available_capacity(),
385 )
386 .field("can_into_inner", &self.can_into_inner())
387 .field("finalized", &self.finalized)
388 .field("failed", &self.failed)
389 .finish()
390 }
391}
392
393impl<W, A, const PAD: bool> Encoder<W, A, PAD>
394where
395 W: Write,
396 A: Alphabet,
397{
398 pub fn try_finish(&mut self) -> io::Result<()> {
408 if self.failed {
409 return Err(stream_encoder_failed_error());
410 }
411 if !self.finalized {
412 self.queue_pending_final()?;
413 self.finalized = true;
414 }
415 self.flush()
416 }
417
418 pub fn finish(mut self) -> io::Result<W> {
420 self.try_finish()?;
421 Ok(self.take_inner())
422 }
423
424 fn queue_pending_final(&mut self) -> io::Result<()> {
425 if self.pending_len == 0 {
426 return Ok(());
427 }
428
429 let mut pending = [0u8; 2];
430 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
431 let pending_len = self.pending_len;
432 let mut encoded = [0u8; 4];
433 let result = self.queue_encoded_temp(&pending[..pending_len], &mut encoded);
434 crate::wipe_bytes(&mut pending);
435 result?;
436 self.clear_pending();
437 Ok(())
438 }
439
440 fn queue_encoded_temp(&mut self, input: &[u8], encoded: &mut [u8]) -> io::Result<()> {
441 let written = match self.engine.encode_slice(input, encoded) {
442 Ok(written) => written,
443 Err(err) => {
444 crate::wipe_bytes(encoded);
445 self.failed = true;
446 return Err(encode_error_to_io(err));
447 }
448 };
449
450 let result = self.output.push_slice(&encoded[..written]);
451 crate::wipe_bytes(encoded);
452 if result.is_err() {
453 self.failed = true;
454 }
455 result
456 }
457
458 fn drain_output(&mut self) -> io::Result<()> {
459 let mut chunk = [0u8; 1024];
460 while !self.output.is_empty() {
461 let pending = self.output.copy_front(&mut chunk);
462 let result = self.inner_mut().write(&chunk[..pending]);
463 crate::wipe_bytes(&mut chunk[..pending]);
464 match result {
465 Ok(0) => {
466 return Err(io::Error::new(
467 io::ErrorKind::WriteZero,
468 "base64 stream encoder could not drain buffered output",
469 ));
470 }
471 Ok(written) => {
472 if written > pending {
473 self.failed = true;
474 return Err(io::Error::new(
475 io::ErrorKind::InvalidData,
476 "wrapped writer reported more bytes than provided",
477 ));
478 }
479 self.output.discard_front(written);
480 }
481 Err(err) => return Err(err),
482 }
483 }
484
485 Ok(())
486 }
487}
488
489impl<W, A, const PAD: bool> Write for Encoder<W, A, PAD>
490where
491 W: Write,
492 A: Alphabet,
493{
494 fn write(&mut self, input: &[u8]) -> io::Result<usize> {
495 if self.failed {
496 return Err(stream_encoder_failed_error());
497 }
498 self.drain_output()?;
499 if self.finalized {
500 return Err(io::Error::new(
501 io::ErrorKind::InvalidInput,
502 "base64 stream encoder received input after finalization",
503 ));
504 }
505 if input.is_empty() {
506 return Ok(0);
507 }
508
509 let mut consumed = 0;
510 if self.pending_len > 0 {
511 let needed = 3 - self.pending_len;
512 if input.len() < needed {
513 self.pending[self.pending_len..self.pending_len + input.len()]
514 .copy_from_slice(input);
515 self.pending_len += input.len();
516 return Ok(input.len());
517 }
518
519 let mut chunk = [0u8; 3];
520 chunk[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
521 chunk[self.pending_len..].copy_from_slice(&input[..needed]);
522
523 let mut encoded = [0u8; 4];
524 let result = self.queue_encoded_temp(&chunk, &mut encoded);
525 crate::wipe_bytes(&mut chunk);
526 result?;
527 self.clear_pending();
528 consumed += needed;
529 }
530
531 let remaining = &input[consumed..];
532 let full_len = remaining.len() / 3 * 3;
533 if full_len > 0 {
534 let max_by_queue = self.output.available_capacity() / 4 * 3;
535 let mut take = core::cmp::min(full_len, core::cmp::min(768, max_by_queue));
536 take -= take % 3;
537
538 if take == 0 {
539 return Ok(consumed);
540 }
541
542 let mut encoded = [0u8; 1024];
543 self.queue_encoded_temp(&remaining[..take], &mut encoded)?;
544 consumed += take;
545
546 if take < full_len {
547 return Ok(consumed);
548 }
549 }
550
551 let tail = &input[consumed..];
552 self.pending[..tail.len()].copy_from_slice(tail);
553 self.pending_len = tail.len();
554 consumed += tail.len();
555
556 Ok(consumed)
557 }
558
559 fn flush(&mut self) -> io::Result<()> {
560 if self.failed {
561 return Err(stream_encoder_failed_error());
562 }
563 self.drain_output()?;
564 self.inner_mut().flush()
565 }
566}
567
568fn encode_error_to_io(err: EncodeError) -> io::Error {
569 io::Error::new(io::ErrorKind::InvalidInput, err)
570}
571
572pub struct Decoder<W, A, const PAD: bool>
588where
589 A: Alphabet,
590{
591 inner: Option<W>,
592 engine: Engine<A, PAD>,
593 pending: [u8; 4],
594 pending_len: usize,
595 output: OutputQueue<1024>,
596 finished: bool,
597 failed: bool,
598 finalized: bool,
599}
600
601impl<W, A, const PAD: bool> Decoder<W, A, PAD>
602where
603 A: Alphabet,
604{
605 #[must_use]
612 pub const fn new(inner: W, engine: Engine<A, PAD>) -> Self {
613 Self {
614 inner: Some(inner),
615 engine,
616 pending: [0; 4],
617 pending_len: 0,
618 output: OutputQueue::new(),
619 finished: false,
620 finalized: false,
621 failed: false,
622 }
623 }
624
625 #[must_use]
627 pub fn get_ref(&self) -> &W {
628 self.inner_ref()
629 }
630
631 pub fn get_mut(&mut self) -> &mut W {
633 self.inner_mut()
634 }
635
636 #[must_use]
638 pub const fn engine(&self) -> Engine<A, PAD> {
639 self.engine
640 }
641
642 #[must_use]
644 pub const fn is_padded(&self) -> bool {
645 PAD
646 }
647
648 #[must_use]
651 pub const fn pending_len(&self) -> usize {
652 self.pending_len
653 }
654
655 #[must_use]
658 pub const fn has_pending_input(&self) -> bool {
659 self.pending_len != 0
660 }
661
662 #[must_use]
667 pub const fn pending_input_needed_len(&self) -> usize {
668 if self.has_pending_input() {
669 4 - self.pending_len
670 } else {
671 0
672 }
673 }
674
675 #[must_use]
678 pub const fn buffered_output_len(&self) -> usize {
679 self.output.len()
680 }
681
682 #[must_use]
685 pub const fn buffered_output_capacity(&self) -> usize {
686 self.output.capacity()
687 }
688
689 #[must_use]
692 pub const fn buffered_output_remaining_capacity(&self) -> usize {
693 self.output.available_capacity()
694 }
695
696 #[must_use]
699 pub const fn has_buffered_output(&self) -> bool {
700 !self.output.is_empty()
701 }
702
703 #[must_use]
709 pub const fn has_terminal_padding(&self) -> bool {
710 self.finished
711 }
712
713 #[must_use]
717 pub const fn is_finalized(&self) -> bool {
718 self.finalized
719 }
720
721 #[must_use]
727 pub const fn is_failed(&self) -> bool {
728 self.failed
729 }
730
731 #[must_use]
734 pub const fn can_into_inner(&self) -> bool {
735 !self.is_failed() && !self.has_pending_input() && !self.has_buffered_output()
736 }
737
738 #[must_use]
742 pub fn into_inner(mut self) -> W {
743 self.take_inner()
744 }
745
746 #[allow(clippy::result_large_err)]
752 pub fn try_into_inner(mut self) -> Result<W, Self> {
753 if !self.can_into_inner() {
754 return Err(self);
755 }
756 Ok(self.take_inner())
757 }
758
759 fn inner_ref(&self) -> &W {
760 match &self.inner {
761 Some(inner) => inner,
762 None => unreachable!("stream decoder inner writer was already taken"),
763 }
764 }
765
766 fn inner_mut(&mut self) -> &mut W {
767 match &mut self.inner {
768 Some(inner) => inner,
769 None => unreachable!("stream decoder inner writer was already taken"),
770 }
771 }
772
773 fn take_inner(&mut self) -> W {
774 match self.inner.take() {
775 Some(inner) => inner,
776 None => unreachable!("stream decoder inner writer was already taken"),
777 }
778 }
779
780 fn clear_pending(&mut self) {
781 crate::wipe_bytes(&mut self.pending);
782 self.pending_len = 0;
783 }
784
785 fn clear_output(&mut self) {
786 self.output.clear_all();
787 }
788}
789
790impl<W, A, const PAD: bool> Drop for Decoder<W, A, PAD>
791where
792 A: Alphabet,
793{
794 fn drop(&mut self) {
795 self.clear_pending();
796 self.clear_output();
797 }
798}
799
800impl<W, A, const PAD: bool> core::fmt::Debug for Decoder<W, A, PAD>
801where
802 A: Alphabet,
803{
804 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
805 formatter
806 .debug_struct("Decoder")
807 .field("inner", &redacted_inner_state(self.inner.is_some()))
808 .field("engine", &self.engine)
809 .field("pending", &"<redacted>")
810 .field("pending_len", &self.pending_len)
811 .field("pending_input_needed_len", &self.pending_input_needed_len())
812 .field("buffered_output_len", &self.output.len())
813 .field("buffered_output_capacity", &self.output.capacity())
814 .field(
815 "buffered_output_remaining_capacity",
816 &self.output.available_capacity(),
817 )
818 .field("can_into_inner", &self.can_into_inner())
819 .field("terminal_padding", &self.finished)
820 .field("finalized", &self.finalized)
821 .field("failed", &self.failed)
822 .finish()
823 }
824}
825
826impl<W, A, const PAD: bool> Decoder<W, A, PAD>
827where
828 W: Write,
829 A: Alphabet,
830{
831 pub fn try_finish(&mut self) -> io::Result<()> {
841 if self.failed {
842 return Err(stream_decoder_failed_error());
843 }
844 if !self.finalized {
845 self.queue_pending_final()?;
846 self.finalized = true;
847 }
848 self.flush()
849 }
850
851 pub fn finish(mut self) -> io::Result<W> {
853 self.try_finish()?;
854 Ok(self.take_inner())
855 }
856
857 fn queue_pending_final(&mut self) -> io::Result<()> {
858 if self.pending_len == 0 {
859 return Ok(());
860 }
861
862 let mut pending = [0u8; 4];
863 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
864 let pending_len = self.pending_len;
865 let mut decoded = [0u8; 3];
866 let result = self.queue_decoded_temp(&pending[..pending_len], &mut decoded);
867 crate::wipe_bytes(&mut pending);
868 if let Err(err) = result {
869 self.clear_pending();
870 return Err(err);
871 }
872 self.clear_pending();
873 Ok(())
874 }
875
876 fn queue_full_quad(&mut self, mut input: [u8; 4]) -> io::Result<()> {
877 let mut decoded = [0u8; 3];
878 let result = self.queue_decoded_temp(&input, &mut decoded);
879 crate::wipe_bytes(&mut input);
880 let written = result?;
881 if written < 3 {
882 self.finished = true;
883 }
884 Ok(())
885 }
886
887 fn queue_decoded_temp(&mut self, input: &[u8], decoded: &mut [u8]) -> io::Result<usize> {
888 let written = match self.engine.decode_slice(input, decoded) {
889 Ok(written) => written,
890 Err(err) => {
891 crate::wipe_bytes(decoded);
892 self.failed = true;
893 return Err(decode_error_to_io(err));
894 }
895 };
896
897 let result = self.output.push_slice(&decoded[..written]);
898 crate::wipe_bytes(decoded);
899 result?;
900 Ok(written)
901 }
902
903 fn drain_output(&mut self) -> io::Result<()> {
904 let mut chunk = [0u8; 1024];
905 while !self.output.is_empty() {
906 let pending = self.output.copy_front(&mut chunk);
907 let result = self.inner_mut().write(&chunk[..pending]);
908 crate::wipe_bytes(&mut chunk[..pending]);
909 match result {
910 Ok(0) => {
911 return Err(io::Error::new(
912 io::ErrorKind::WriteZero,
913 "base64 stream decoder could not drain buffered output",
914 ));
915 }
916 Ok(written) => {
917 if written > pending {
918 self.failed = true;
919 return Err(io::Error::new(
920 io::ErrorKind::InvalidData,
921 "wrapped writer reported more bytes than provided",
922 ));
923 }
924 self.output.discard_front(written);
925 }
926 Err(err) => return Err(err),
927 }
928 }
929
930 Ok(())
931 }
932}
933
934impl<W, A, const PAD: bool> Write for Decoder<W, A, PAD>
935where
936 W: Write,
937 A: Alphabet,
938{
939 fn write(&mut self, input: &[u8]) -> io::Result<usize> {
940 if self.failed {
941 return Err(stream_decoder_failed_error());
942 }
943 if input.is_empty() {
944 self.drain_output()?;
945 return Ok(0);
946 }
947 self.drain_output()?;
948 if self.finalized {
949 return Err(io::Error::new(
950 io::ErrorKind::InvalidInput,
951 "base64 stream decoder received input after finalization",
952 ));
953 }
954 if self.finished {
955 self.failed = true;
956 return Err(trailing_input_after_padding_error());
957 }
958
959 let mut consumed = 0;
960 if self.pending_len > 0 {
961 let needed = 4 - self.pending_len;
962 if input.len() < needed {
963 self.pending[self.pending_len..self.pending_len + input.len()]
964 .copy_from_slice(input);
965 self.pending_len += input.len();
966 return Ok(input.len());
967 }
968
969 let mut quad = [0u8; 4];
970 quad[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
971 quad[self.pending_len..].copy_from_slice(&input[..needed]);
972 let result = self.queue_full_quad(quad);
973 crate::wipe_bytes(&mut quad);
974 if let Err(err) = result {
975 self.clear_pending();
976 return Err(err);
977 }
978 self.clear_pending();
979 consumed += needed;
980
981 if self.finished {
982 return Ok(consumed);
983 }
984 }
985
986 while input.len() - consumed >= 4 {
987 if self.output.available_capacity() < 3 {
988 return Ok(consumed);
989 }
990
991 let mut quad = [
992 input[consumed],
993 input[consumed + 1],
994 input[consumed + 2],
995 input[consumed + 3],
996 ];
997 let mut decoded = [0u8; 3];
998 let written = match self.engine.decode_slice(&quad, &mut decoded) {
999 Ok(written) => written,
1000 Err(err) => {
1001 crate::wipe_bytes(&mut quad);
1002 crate::wipe_bytes(&mut decoded);
1003 self.failed = true;
1004 if consumed > 0 {
1005 return Ok(consumed);
1006 }
1007
1008 return Err(decode_error_to_io(err));
1009 }
1010 };
1011
1012 let result = self.output.push_slice(&decoded[..written]);
1013 crate::wipe_bytes(&mut quad);
1014 crate::wipe_bytes(&mut decoded);
1015 result?;
1016 consumed += 4;
1017
1018 if written < 3 {
1019 self.finished = true;
1020 return Ok(consumed);
1021 }
1022 }
1023
1024 let tail = &input[consumed..];
1025 self.pending[..tail.len()].copy_from_slice(tail);
1026 self.pending_len = tail.len();
1027 consumed += tail.len();
1028
1029 Ok(consumed)
1030 }
1031
1032 fn flush(&mut self) -> io::Result<()> {
1033 if self.failed {
1034 return Err(stream_decoder_failed_error());
1035 }
1036 self.drain_output()?;
1037 self.inner_mut().flush()
1038 }
1039}
1040
1041fn decode_error_to_io(err: DecodeError) -> io::Error {
1042 io::Error::new(io::ErrorKind::InvalidInput, err)
1043}
1044
1045fn trailing_input_after_padding_error() -> io::Error {
1046 io::Error::new(
1047 io::ErrorKind::InvalidInput,
1048 "base64 decoder received trailing input after padding",
1049 )
1050}
1051
1052fn stream_decoder_failed_error() -> io::Error {
1053 io::Error::new(
1054 io::ErrorKind::InvalidInput,
1055 "base64 stream decoder is failed after malformed input",
1056 )
1057}
1058
1059fn stream_encoder_failed_error() -> io::Error {
1060 io::Error::new(
1061 io::ErrorKind::InvalidInput,
1062 "base64 stream encoder is failed after internal error",
1063 )
1064}
1065
1066pub struct DecoderReader<R, A, const PAD: bool>
1081where
1082 A: Alphabet,
1083{
1084 inner: Option<R>,
1085 engine: Engine<A, PAD>,
1086 pending: [u8; 4],
1087 pending_len: usize,
1088 output: OutputQueue<3>,
1089 finished: bool,
1090 terminal_seen: bool,
1091 failed: bool,
1092}
1093
1094impl<R, A, const PAD: bool> DecoderReader<R, A, PAD>
1095where
1096 A: Alphabet,
1097{
1098 #[must_use]
1105 pub fn new(inner: R, engine: Engine<A, PAD>) -> Self {
1106 Self {
1107 inner: Some(inner),
1108 engine,
1109 pending: [0; 4],
1110 pending_len: 0,
1111 output: OutputQueue::new(),
1112 finished: false,
1113 terminal_seen: false,
1114 failed: false,
1115 }
1116 }
1117
1118 #[must_use]
1120 pub fn get_ref(&self) -> &R {
1121 self.inner_ref()
1122 }
1123
1124 pub fn get_mut(&mut self) -> &mut R {
1126 self.inner_mut()
1127 }
1128
1129 #[must_use]
1131 pub const fn engine(&self) -> Engine<A, PAD> {
1132 self.engine
1133 }
1134
1135 #[must_use]
1137 pub const fn is_padded(&self) -> bool {
1138 PAD
1139 }
1140
1141 #[must_use]
1144 pub const fn pending_len(&self) -> usize {
1145 self.pending_len
1146 }
1147
1148 #[must_use]
1151 pub const fn has_pending_input(&self) -> bool {
1152 self.pending_len != 0
1153 }
1154
1155 #[must_use]
1160 pub const fn pending_input_needed_len(&self) -> usize {
1161 if self.has_pending_input() {
1162 4 - self.pending_len
1163 } else {
1164 0
1165 }
1166 }
1167
1168 #[must_use]
1171 pub const fn buffered_output_len(&self) -> usize {
1172 self.output.len()
1173 }
1174
1175 #[must_use]
1178 pub const fn buffered_output_capacity(&self) -> usize {
1179 self.output.capacity()
1180 }
1181
1182 #[must_use]
1185 pub const fn buffered_output_remaining_capacity(&self) -> usize {
1186 self.output.available_capacity()
1187 }
1188
1189 #[must_use]
1192 pub const fn has_buffered_output(&self) -> bool {
1193 !self.output.is_empty()
1194 }
1195
1196 #[must_use]
1203 pub const fn has_terminal_padding(&self) -> bool {
1204 self.terminal_seen
1205 }
1206
1207 #[must_use]
1213 pub const fn has_finished_input(&self) -> bool {
1214 self.finished
1215 }
1216
1217 #[must_use]
1220 pub const fn is_finished(&self) -> bool {
1221 self.finished && self.output.is_empty()
1222 }
1223
1224 #[must_use]
1231 pub const fn is_failed(&self) -> bool {
1232 self.failed
1233 }
1234
1235 #[must_use]
1238 pub const fn can_into_inner(&self) -> bool {
1239 !self.is_failed() && self.is_finished()
1240 }
1241
1242 #[must_use]
1244 pub fn into_inner(mut self) -> R {
1245 self.take_inner()
1246 }
1247
1248 #[allow(clippy::result_large_err)]
1256 pub fn try_into_inner(mut self) -> Result<R, Self> {
1257 if !self.can_into_inner() {
1258 return Err(self);
1259 }
1260 Ok(self.take_inner())
1261 }
1262
1263 fn inner_ref(&self) -> &R {
1264 match &self.inner {
1265 Some(inner) => inner,
1266 None => unreachable!("stream decoder reader inner reader was already taken"),
1267 }
1268 }
1269
1270 fn inner_mut(&mut self) -> &mut R {
1271 match &mut self.inner {
1272 Some(inner) => inner,
1273 None => unreachable!("stream decoder reader inner reader was already taken"),
1274 }
1275 }
1276
1277 fn take_inner(&mut self) -> R {
1278 match self.inner.take() {
1279 Some(inner) => inner,
1280 None => unreachable!("stream decoder reader inner reader was already taken"),
1281 }
1282 }
1283
1284 fn clear_pending(&mut self) {
1285 crate::wipe_bytes(&mut self.pending);
1286 self.pending_len = 0;
1287 }
1288}
1289
1290impl<R, A, const PAD: bool> Drop for DecoderReader<R, A, PAD>
1291where
1292 A: Alphabet,
1293{
1294 fn drop(&mut self) {
1295 self.clear_pending();
1296 self.output.clear_all();
1297 }
1298}
1299
1300impl<R, A, const PAD: bool> core::fmt::Debug for DecoderReader<R, A, PAD>
1301where
1302 A: Alphabet,
1303{
1304 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1305 formatter
1306 .debug_struct("DecoderReader")
1307 .field("inner", &redacted_inner_state(self.inner.is_some()))
1308 .field("engine", &self.engine)
1309 .field("pending", &"<redacted>")
1310 .field("pending_len", &self.pending_len)
1311 .field("pending_input_needed_len", &self.pending_input_needed_len())
1312 .field("buffered_output_len", &self.output.len())
1313 .field("buffered_output_capacity", &self.output.capacity())
1314 .field(
1315 "buffered_output_remaining_capacity",
1316 &self.output.available_capacity(),
1317 )
1318 .field("can_into_inner", &self.can_into_inner())
1319 .field("finished", &self.finished)
1320 .field("terminal_padding", &self.terminal_seen)
1321 .field("failed", &self.failed)
1322 .finish()
1323 }
1324}
1325
1326impl<R, A, const PAD: bool> Read for DecoderReader<R, A, PAD>
1327where
1328 R: Read,
1329 A: Alphabet,
1330{
1331 fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
1332 if output.is_empty() {
1333 return Ok(0);
1334 }
1335 if self.failed {
1336 return Err(stream_decoder_failed_error());
1337 }
1338
1339 while self.output.is_empty() && !self.finished {
1340 self.fill_output()?;
1341 }
1342
1343 Ok(self.output.pop_slice(output))
1344 }
1345}
1346
1347impl<R, A, const PAD: bool> DecoderReader<R, A, PAD>
1348where
1349 R: Read,
1350 A: Alphabet,
1351{
1352 fn fill_output(&mut self) -> io::Result<()> {
1353 if self.failed {
1354 return Err(stream_decoder_failed_error());
1355 }
1356 if self.terminal_seen {
1357 self.finished = true;
1358 return Ok(());
1359 }
1360
1361 let mut input = [0u8; 4];
1362 let available = 4 - self.pending_len;
1363 let read = match self.inner_mut().read(&mut input[..available]) {
1364 Ok(read) => read,
1365 Err(err) => {
1366 crate::wipe_bytes(&mut input);
1367 return Err(err);
1368 }
1369 };
1370 if read == 0 {
1371 crate::wipe_bytes(&mut input);
1372 self.finished = true;
1373 self.push_final_pending()?;
1374 return Ok(());
1375 }
1376
1377 self.pending[self.pending_len..self.pending_len + read].copy_from_slice(&input[..read]);
1378 crate::wipe_bytes(&mut input);
1379 self.pending_len += read;
1380 if self.pending_len < 4 {
1381 return Ok(());
1382 }
1383
1384 let mut quad = self.pending;
1385 self.clear_pending();
1386 let result = self.push_decoded(&quad);
1387 crate::wipe_bytes(&mut quad);
1388 result?;
1389 if self.terminal_seen {
1390 self.finished = true;
1391 }
1392 Ok(())
1393 }
1394
1395 fn push_final_pending(&mut self) -> io::Result<()> {
1396 if self.pending_len == 0 {
1397 return Ok(());
1398 }
1399
1400 let mut pending = [0u8; 4];
1401 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
1402 let pending_len = self.pending_len;
1403 self.clear_pending();
1404 let result = self.push_decoded(&pending[..pending_len]);
1405 crate::wipe_bytes(&mut pending);
1406 result
1407 }
1408
1409 fn push_decoded(&mut self, input: &[u8]) -> io::Result<()> {
1410 let mut decoded = [0u8; 3];
1411 let written = match self.engine.decode_slice(input, &mut decoded) {
1412 Ok(written) => written,
1413 Err(err) => {
1414 crate::wipe_bytes(&mut decoded);
1415 self.failed = true;
1416 return Err(decode_error_to_io(err));
1417 }
1418 };
1419 let result = self.output.push_slice(&decoded[..written]);
1420 crate::wipe_bytes(&mut decoded);
1421 result?;
1422 if input.len() == 4 && written < 3 {
1423 self.terminal_seen = true;
1424 }
1425 Ok(())
1426 }
1427}
1428
1429pub struct EncoderReader<R, A, const PAD: bool>
1431where
1432 A: Alphabet,
1433{
1434 inner: Option<R>,
1435 engine: Engine<A, PAD>,
1436 pending: [u8; 2],
1437 pending_len: usize,
1438 output: OutputQueue<1024>,
1439 finished: bool,
1440 failed: bool,
1441}
1442
1443impl<R, A, const PAD: bool> EncoderReader<R, A, PAD>
1444where
1445 A: Alphabet,
1446{
1447 #[must_use]
1449 pub fn new(inner: R, engine: Engine<A, PAD>) -> Self {
1450 Self {
1451 inner: Some(inner),
1452 engine,
1453 pending: [0; 2],
1454 pending_len: 0,
1455 output: OutputQueue::new(),
1456 finished: false,
1457 failed: false,
1458 }
1459 }
1460
1461 #[must_use]
1463 pub fn get_ref(&self) -> &R {
1464 self.inner_ref()
1465 }
1466
1467 pub fn get_mut(&mut self) -> &mut R {
1469 self.inner_mut()
1470 }
1471
1472 #[must_use]
1474 pub const fn engine(&self) -> Engine<A, PAD> {
1475 self.engine
1476 }
1477
1478 #[must_use]
1480 pub const fn is_padded(&self) -> bool {
1481 PAD
1482 }
1483
1484 #[must_use]
1487 pub const fn pending_len(&self) -> usize {
1488 self.pending_len
1489 }
1490
1491 #[must_use]
1494 pub const fn has_pending_input(&self) -> bool {
1495 self.pending_len != 0
1496 }
1497
1498 #[must_use]
1503 pub const fn pending_input_needed_len(&self) -> usize {
1504 if self.has_pending_input() {
1505 3 - self.pending_len
1506 } else {
1507 0
1508 }
1509 }
1510
1511 #[must_use]
1514 pub const fn buffered_output_len(&self) -> usize {
1515 self.output.len()
1516 }
1517
1518 #[must_use]
1521 pub const fn buffered_output_capacity(&self) -> usize {
1522 self.output.capacity()
1523 }
1524
1525 #[must_use]
1528 pub const fn buffered_output_remaining_capacity(&self) -> usize {
1529 self.output.available_capacity()
1530 }
1531
1532 #[must_use]
1535 pub const fn has_buffered_output(&self) -> bool {
1536 !self.output.is_empty()
1537 }
1538
1539 #[must_use]
1545 pub const fn has_finished_input(&self) -> bool {
1546 self.finished
1547 }
1548
1549 #[must_use]
1552 pub const fn is_finished(&self) -> bool {
1553 self.finished && self.output.is_empty()
1554 }
1555
1556 #[must_use]
1559 pub const fn is_failed(&self) -> bool {
1560 self.failed
1561 }
1562
1563 #[must_use]
1566 pub const fn can_into_inner(&self) -> bool {
1567 self.is_finished() && !self.failed
1568 }
1569
1570 #[must_use]
1572 pub fn into_inner(mut self) -> R {
1573 self.take_inner()
1574 }
1575
1576 #[allow(clippy::result_large_err)]
1583 pub fn try_into_inner(mut self) -> Result<R, Self> {
1584 if !self.can_into_inner() {
1585 return Err(self);
1586 }
1587 Ok(self.take_inner())
1588 }
1589
1590 fn inner_ref(&self) -> &R {
1591 match &self.inner {
1592 Some(inner) => inner,
1593 None => unreachable!("stream encoder reader inner reader was already taken"),
1594 }
1595 }
1596
1597 fn inner_mut(&mut self) -> &mut R {
1598 match &mut self.inner {
1599 Some(inner) => inner,
1600 None => unreachable!("stream encoder reader inner reader was already taken"),
1601 }
1602 }
1603
1604 fn take_inner(&mut self) -> R {
1605 match self.inner.take() {
1606 Some(inner) => inner,
1607 None => unreachable!("stream encoder reader inner reader was already taken"),
1608 }
1609 }
1610
1611 fn clear_pending(&mut self) {
1612 crate::wipe_bytes(&mut self.pending);
1613 self.pending_len = 0;
1614 }
1615}
1616
1617impl<R, A, const PAD: bool> Drop for EncoderReader<R, A, PAD>
1618where
1619 A: Alphabet,
1620{
1621 fn drop(&mut self) {
1622 self.clear_pending();
1623 self.output.clear_all();
1624 }
1625}
1626
1627impl<R, A, const PAD: bool> core::fmt::Debug for EncoderReader<R, A, PAD>
1628where
1629 A: Alphabet,
1630{
1631 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1632 formatter
1633 .debug_struct("EncoderReader")
1634 .field("inner", &redacted_inner_state(self.inner.is_some()))
1635 .field("engine", &self.engine)
1636 .field("pending", &"<redacted>")
1637 .field("pending_len", &self.pending_len)
1638 .field("pending_input_needed_len", &self.pending_input_needed_len())
1639 .field("buffered_output_len", &self.output.len())
1640 .field("buffered_output_capacity", &self.output.capacity())
1641 .field(
1642 "buffered_output_remaining_capacity",
1643 &self.output.available_capacity(),
1644 )
1645 .field("can_into_inner", &self.can_into_inner())
1646 .field("finished", &self.finished)
1647 .field("failed", &self.failed)
1648 .finish()
1649 }
1650}
1651
1652impl<R, A, const PAD: bool> Read for EncoderReader<R, A, PAD>
1653where
1654 R: Read,
1655 A: Alphabet,
1656{
1657 fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
1658 if self.failed {
1659 return Err(stream_encoder_failed_error());
1660 }
1661
1662 if output.is_empty() {
1663 return Ok(0);
1664 }
1665
1666 while self.output.is_empty() && !self.finished {
1667 self.fill_output()?;
1668 }
1669
1670 Ok(self.output.pop_slice(output))
1671 }
1672}
1673
1674impl<R, A, const PAD: bool> EncoderReader<R, A, PAD>
1675where
1676 R: Read,
1677 A: Alphabet,
1678{
1679 fn fill_output(&mut self) -> io::Result<()> {
1680 let mut input = [0u8; 768];
1681 let read = match self.inner_mut().read(&mut input) {
1682 Ok(read) => read,
1683 Err(err) => {
1684 crate::wipe_bytes(&mut input);
1685 return Err(err);
1686 }
1687 };
1688 if read == 0 {
1689 crate::wipe_bytes(&mut input);
1690 self.finished = true;
1691 if let Err(err) = self.push_final_pending() {
1692 self.failed = true;
1693 return Err(err);
1694 }
1695 return Ok(());
1696 }
1697
1698 let mut consumed = 0;
1699 if self.pending_len > 0 {
1700 let needed = 3 - self.pending_len;
1701 if read < needed {
1702 self.pending[self.pending_len..self.pending_len + read]
1703 .copy_from_slice(&input[..read]);
1704 self.pending_len += read;
1705 crate::wipe_bytes(&mut input);
1706 return Ok(());
1707 }
1708
1709 let mut chunk = [0u8; 3];
1710 chunk[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
1711 chunk[self.pending_len..].copy_from_slice(&input[..needed]);
1712 let result = self.push_encoded(&chunk);
1713 crate::wipe_bytes(&mut chunk);
1714 if let Err(err) = result {
1715 crate::wipe_bytes(&mut input);
1716 self.failed = true;
1717 return Err(err);
1718 }
1719 self.clear_pending();
1720 consumed += needed;
1721 }
1722
1723 let remaining = &input[consumed..read];
1724 let full_len = remaining.len() / 3 * 3;
1725 let tail_len = remaining.len() - full_len;
1726 let mut tail = [0u8; 2];
1727 tail[..tail_len].copy_from_slice(&remaining[full_len..]);
1728 let result = if full_len > 0 {
1729 self.push_encoded(&remaining[..full_len])
1730 } else {
1731 Ok(())
1732 };
1733 crate::wipe_bytes(&mut input);
1734 if let Err(err) = result {
1735 crate::wipe_bytes(&mut tail);
1736 self.failed = true;
1737 return Err(err);
1738 }
1739 self.pending[..tail_len].copy_from_slice(&tail[..tail_len]);
1740 crate::wipe_bytes(&mut tail);
1741 self.pending_len = tail_len;
1742 Ok(())
1743 }
1744
1745 fn push_final_pending(&mut self) -> io::Result<()> {
1746 if self.pending_len == 0 {
1747 return Ok(());
1748 }
1749
1750 let mut pending = [0u8; 2];
1751 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
1752 let pending_len = self.pending_len;
1753 self.clear_pending();
1754 let result = self.push_encoded(&pending[..pending_len]);
1755 crate::wipe_bytes(&mut pending);
1756 result
1757 }
1758
1759 fn push_encoded(&mut self, input: &[u8]) -> io::Result<()> {
1760 let mut encoded = [0u8; 1024];
1761 let written = match self.engine.encode_slice(input, &mut encoded) {
1762 Ok(written) => written,
1763 Err(err) => {
1764 crate::wipe_bytes(&mut encoded);
1765 return Err(encode_error_to_io(err));
1766 }
1767 };
1768 let result = self.output.push_slice(&encoded[..written]);
1769 crate::wipe_bytes(&mut encoded);
1770 result
1771 }
1772}
1773
1774const fn redacted_inner_state(present: bool) -> &'static str {
1775 if present { "<present>" } else { "<taken>" }
1776}