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 if result.is_err() {
900 self.failed = true;
901 }
902 result?;
903 Ok(written)
904 }
905
906 fn drain_output(&mut self) -> io::Result<()> {
907 let mut chunk = [0u8; 1024];
908 while !self.output.is_empty() {
909 let pending = self.output.copy_front(&mut chunk);
910 let result = self.inner_mut().write(&chunk[..pending]);
911 crate::wipe_bytes(&mut chunk[..pending]);
912 match result {
913 Ok(0) => {
914 return Err(io::Error::new(
915 io::ErrorKind::WriteZero,
916 "base64 stream decoder could not drain buffered output",
917 ));
918 }
919 Ok(written) => {
920 if written > pending {
921 self.failed = true;
922 return Err(io::Error::new(
923 io::ErrorKind::InvalidData,
924 "wrapped writer reported more bytes than provided",
925 ));
926 }
927 self.output.discard_front(written);
928 }
929 Err(err) => return Err(err),
930 }
931 }
932
933 Ok(())
934 }
935}
936
937impl<W, A, const PAD: bool> Write for Decoder<W, A, PAD>
938where
939 W: Write,
940 A: Alphabet,
941{
942 fn write(&mut self, input: &[u8]) -> io::Result<usize> {
943 if self.failed {
944 return Err(stream_decoder_failed_error());
945 }
946 if input.is_empty() {
947 self.drain_output()?;
948 return Ok(0);
949 }
950 self.drain_output()?;
951 if self.finalized {
952 return Err(io::Error::new(
953 io::ErrorKind::InvalidInput,
954 "base64 stream decoder received input after finalization",
955 ));
956 }
957 if self.finished {
958 self.failed = true;
959 return Err(trailing_input_after_padding_error());
960 }
961
962 let mut consumed = 0;
963 if self.pending_len > 0 {
964 let needed = 4 - self.pending_len;
965 if input.len() < needed {
966 self.pending[self.pending_len..self.pending_len + input.len()]
967 .copy_from_slice(input);
968 self.pending_len += input.len();
969 return Ok(input.len());
970 }
971
972 let mut quad = [0u8; 4];
973 quad[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
974 quad[self.pending_len..].copy_from_slice(&input[..needed]);
975 let result = self.queue_full_quad(quad);
976 crate::wipe_bytes(&mut quad);
977 if let Err(err) = result {
978 self.clear_pending();
979 return Err(err);
980 }
981 self.clear_pending();
982 consumed += needed;
983
984 if self.finished {
985 return Ok(consumed);
986 }
987 }
988
989 while input.len() - consumed >= 4 {
990 if self.output.available_capacity() < 3 {
991 return Ok(consumed);
992 }
993
994 let mut quad = [
995 input[consumed],
996 input[consumed + 1],
997 input[consumed + 2],
998 input[consumed + 3],
999 ];
1000 let mut decoded = [0u8; 3];
1001 let written = match self.engine.decode_slice(&quad, &mut decoded) {
1002 Ok(written) => written,
1003 Err(err) => {
1004 crate::wipe_bytes(&mut quad);
1005 crate::wipe_bytes(&mut decoded);
1006 self.failed = true;
1007 if consumed > 0 {
1008 return Ok(consumed);
1009 }
1010
1011 return Err(decode_error_to_io(err));
1012 }
1013 };
1014
1015 let result = self.output.push_slice(&decoded[..written]);
1016 crate::wipe_bytes(&mut quad);
1017 crate::wipe_bytes(&mut decoded);
1018 result?;
1019 consumed += 4;
1020
1021 if written < 3 {
1022 self.finished = true;
1023 return Ok(consumed);
1024 }
1025 }
1026
1027 let tail = &input[consumed..];
1028 self.pending[..tail.len()].copy_from_slice(tail);
1029 self.pending_len = tail.len();
1030 consumed += tail.len();
1031
1032 Ok(consumed)
1033 }
1034
1035 fn flush(&mut self) -> io::Result<()> {
1036 if self.failed {
1037 return Err(stream_decoder_failed_error());
1038 }
1039 self.drain_output()?;
1040 self.inner_mut().flush()
1041 }
1042}
1043
1044fn decode_error_to_io(err: DecodeError) -> io::Error {
1045 io::Error::new(io::ErrorKind::InvalidInput, err)
1046}
1047
1048fn trailing_input_after_padding_error() -> io::Error {
1049 io::Error::new(
1050 io::ErrorKind::InvalidInput,
1051 "base64 decoder received trailing input after padding",
1052 )
1053}
1054
1055fn stream_decoder_failed_error() -> io::Error {
1056 io::Error::new(
1057 io::ErrorKind::InvalidInput,
1058 "base64 stream decoder is failed after malformed input",
1059 )
1060}
1061
1062fn stream_encoder_failed_error() -> io::Error {
1063 io::Error::new(
1064 io::ErrorKind::InvalidInput,
1065 "base64 stream encoder is failed after internal error",
1066 )
1067}
1068
1069pub struct DecoderReader<R, A, const PAD: bool>
1084where
1085 A: Alphabet,
1086{
1087 inner: Option<R>,
1088 engine: Engine<A, PAD>,
1089 pending: [u8; 4],
1090 pending_len: usize,
1091 output: OutputQueue<3>,
1092 finished: bool,
1093 terminal_seen: bool,
1094 failed: bool,
1095}
1096
1097impl<R, A, const PAD: bool> DecoderReader<R, A, PAD>
1098where
1099 A: Alphabet,
1100{
1101 #[must_use]
1108 pub fn new(inner: R, engine: Engine<A, PAD>) -> Self {
1109 Self {
1110 inner: Some(inner),
1111 engine,
1112 pending: [0; 4],
1113 pending_len: 0,
1114 output: OutputQueue::new(),
1115 finished: false,
1116 terminal_seen: false,
1117 failed: false,
1118 }
1119 }
1120
1121 #[must_use]
1123 pub fn get_ref(&self) -> &R {
1124 self.inner_ref()
1125 }
1126
1127 pub fn get_mut(&mut self) -> &mut R {
1129 self.inner_mut()
1130 }
1131
1132 #[must_use]
1134 pub const fn engine(&self) -> Engine<A, PAD> {
1135 self.engine
1136 }
1137
1138 #[must_use]
1140 pub const fn is_padded(&self) -> bool {
1141 PAD
1142 }
1143
1144 #[must_use]
1147 pub const fn pending_len(&self) -> usize {
1148 self.pending_len
1149 }
1150
1151 #[must_use]
1154 pub const fn has_pending_input(&self) -> bool {
1155 self.pending_len != 0
1156 }
1157
1158 #[must_use]
1163 pub const fn pending_input_needed_len(&self) -> usize {
1164 if self.has_pending_input() {
1165 4 - self.pending_len
1166 } else {
1167 0
1168 }
1169 }
1170
1171 #[must_use]
1174 pub const fn buffered_output_len(&self) -> usize {
1175 self.output.len()
1176 }
1177
1178 #[must_use]
1181 pub const fn buffered_output_capacity(&self) -> usize {
1182 self.output.capacity()
1183 }
1184
1185 #[must_use]
1188 pub const fn buffered_output_remaining_capacity(&self) -> usize {
1189 self.output.available_capacity()
1190 }
1191
1192 #[must_use]
1195 pub const fn has_buffered_output(&self) -> bool {
1196 !self.output.is_empty()
1197 }
1198
1199 #[must_use]
1206 pub const fn has_terminal_padding(&self) -> bool {
1207 self.terminal_seen
1208 }
1209
1210 #[must_use]
1216 pub const fn has_finished_input(&self) -> bool {
1217 self.finished
1218 }
1219
1220 #[must_use]
1223 pub const fn is_finished(&self) -> bool {
1224 self.finished && self.output.is_empty()
1225 }
1226
1227 #[must_use]
1234 pub const fn is_failed(&self) -> bool {
1235 self.failed
1236 }
1237
1238 #[must_use]
1241 pub const fn can_into_inner(&self) -> bool {
1242 !self.is_failed() && self.is_finished()
1243 }
1244
1245 #[must_use]
1247 pub fn into_inner(mut self) -> R {
1248 self.take_inner()
1249 }
1250
1251 #[allow(clippy::result_large_err)]
1259 pub fn try_into_inner(mut self) -> Result<R, Self> {
1260 if !self.can_into_inner() {
1261 return Err(self);
1262 }
1263 Ok(self.take_inner())
1264 }
1265
1266 fn inner_ref(&self) -> &R {
1267 match &self.inner {
1268 Some(inner) => inner,
1269 None => unreachable!("stream decoder reader inner reader was already taken"),
1270 }
1271 }
1272
1273 fn inner_mut(&mut self) -> &mut R {
1274 match &mut self.inner {
1275 Some(inner) => inner,
1276 None => unreachable!("stream decoder reader inner reader was already taken"),
1277 }
1278 }
1279
1280 fn take_inner(&mut self) -> R {
1281 match self.inner.take() {
1282 Some(inner) => inner,
1283 None => unreachable!("stream decoder reader inner reader was already taken"),
1284 }
1285 }
1286
1287 fn clear_pending(&mut self) {
1288 crate::wipe_bytes(&mut self.pending);
1289 self.pending_len = 0;
1290 }
1291}
1292
1293impl<R, A, const PAD: bool> Drop for DecoderReader<R, A, PAD>
1294where
1295 A: Alphabet,
1296{
1297 fn drop(&mut self) {
1298 self.clear_pending();
1299 self.output.clear_all();
1300 }
1301}
1302
1303impl<R, A, const PAD: bool> core::fmt::Debug for DecoderReader<R, A, PAD>
1304where
1305 A: Alphabet,
1306{
1307 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1308 formatter
1309 .debug_struct("DecoderReader")
1310 .field("inner", &redacted_inner_state(self.inner.is_some()))
1311 .field("engine", &self.engine)
1312 .field("pending", &"<redacted>")
1313 .field("pending_len", &self.pending_len)
1314 .field("pending_input_needed_len", &self.pending_input_needed_len())
1315 .field("buffered_output_len", &self.output.len())
1316 .field("buffered_output_capacity", &self.output.capacity())
1317 .field(
1318 "buffered_output_remaining_capacity",
1319 &self.output.available_capacity(),
1320 )
1321 .field("can_into_inner", &self.can_into_inner())
1322 .field("finished", &self.finished)
1323 .field("terminal_padding", &self.terminal_seen)
1324 .field("failed", &self.failed)
1325 .finish()
1326 }
1327}
1328
1329impl<R, A, const PAD: bool> Read for DecoderReader<R, A, PAD>
1330where
1331 R: Read,
1332 A: Alphabet,
1333{
1334 fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
1335 if output.is_empty() {
1336 return Ok(0);
1337 }
1338 if self.failed {
1339 return Err(stream_decoder_failed_error());
1340 }
1341
1342 while self.output.is_empty() && !self.finished {
1343 self.fill_output()?;
1344 }
1345
1346 Ok(self.output.pop_slice(output))
1347 }
1348}
1349
1350impl<R, A, const PAD: bool> DecoderReader<R, A, PAD>
1351where
1352 R: Read,
1353 A: Alphabet,
1354{
1355 fn fill_output(&mut self) -> io::Result<()> {
1356 if self.failed {
1357 return Err(stream_decoder_failed_error());
1358 }
1359 if self.terminal_seen {
1360 self.finished = true;
1361 return Ok(());
1362 }
1363
1364 let mut input = [0u8; 4];
1365 let available = 4 - self.pending_len;
1366 let read = match self.inner_mut().read(&mut input[..available]) {
1367 Ok(read) => read,
1368 Err(err) => {
1369 crate::wipe_bytes(&mut input);
1370 return Err(err);
1371 }
1372 };
1373 if read == 0 {
1374 crate::wipe_bytes(&mut input);
1375 self.finished = true;
1376 self.push_final_pending()?;
1377 return Ok(());
1378 }
1379
1380 self.pending[self.pending_len..self.pending_len + read].copy_from_slice(&input[..read]);
1381 crate::wipe_bytes(&mut input);
1382 self.pending_len += read;
1383 if self.pending_len < 4 {
1384 return Ok(());
1385 }
1386
1387 let mut quad = self.pending;
1388 self.clear_pending();
1389 let result = self.push_decoded(&quad);
1390 crate::wipe_bytes(&mut quad);
1391 result?;
1392 if self.terminal_seen {
1393 self.finished = true;
1394 }
1395 Ok(())
1396 }
1397
1398 fn push_final_pending(&mut self) -> io::Result<()> {
1399 if self.pending_len == 0 {
1400 return Ok(());
1401 }
1402
1403 let mut pending = [0u8; 4];
1404 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
1405 let pending_len = self.pending_len;
1406 self.clear_pending();
1407 let result = self.push_decoded(&pending[..pending_len]);
1408 crate::wipe_bytes(&mut pending);
1409 result
1410 }
1411
1412 fn push_decoded(&mut self, input: &[u8]) -> io::Result<()> {
1413 let mut decoded = [0u8; 3];
1414 let written = match self.engine.decode_slice(input, &mut decoded) {
1415 Ok(written) => written,
1416 Err(err) => {
1417 crate::wipe_bytes(&mut decoded);
1418 self.failed = true;
1419 return Err(decode_error_to_io(err));
1420 }
1421 };
1422 let result = self.output.push_slice(&decoded[..written]);
1423 crate::wipe_bytes(&mut decoded);
1424 if result.is_err() {
1425 self.failed = true;
1426 }
1427 result?;
1428 if input.len() == 4 && written < 3 {
1429 self.terminal_seen = true;
1430 }
1431 Ok(())
1432 }
1433}
1434
1435pub struct EncoderReader<R, A, const PAD: bool>
1437where
1438 A: Alphabet,
1439{
1440 inner: Option<R>,
1441 engine: Engine<A, PAD>,
1442 pending: [u8; 2],
1443 pending_len: usize,
1444 output: OutputQueue<1024>,
1445 finished: bool,
1446 failed: bool,
1447}
1448
1449impl<R, A, const PAD: bool> EncoderReader<R, A, PAD>
1450where
1451 A: Alphabet,
1452{
1453 #[must_use]
1455 pub fn new(inner: R, engine: Engine<A, PAD>) -> Self {
1456 Self {
1457 inner: Some(inner),
1458 engine,
1459 pending: [0; 2],
1460 pending_len: 0,
1461 output: OutputQueue::new(),
1462 finished: false,
1463 failed: false,
1464 }
1465 }
1466
1467 #[must_use]
1469 pub fn get_ref(&self) -> &R {
1470 self.inner_ref()
1471 }
1472
1473 pub fn get_mut(&mut self) -> &mut R {
1475 self.inner_mut()
1476 }
1477
1478 #[must_use]
1480 pub const fn engine(&self) -> Engine<A, PAD> {
1481 self.engine
1482 }
1483
1484 #[must_use]
1486 pub const fn is_padded(&self) -> bool {
1487 PAD
1488 }
1489
1490 #[must_use]
1493 pub const fn pending_len(&self) -> usize {
1494 self.pending_len
1495 }
1496
1497 #[must_use]
1500 pub const fn has_pending_input(&self) -> bool {
1501 self.pending_len != 0
1502 }
1503
1504 #[must_use]
1509 pub const fn pending_input_needed_len(&self) -> usize {
1510 if self.has_pending_input() {
1511 3 - self.pending_len
1512 } else {
1513 0
1514 }
1515 }
1516
1517 #[must_use]
1520 pub const fn buffered_output_len(&self) -> usize {
1521 self.output.len()
1522 }
1523
1524 #[must_use]
1527 pub const fn buffered_output_capacity(&self) -> usize {
1528 self.output.capacity()
1529 }
1530
1531 #[must_use]
1534 pub const fn buffered_output_remaining_capacity(&self) -> usize {
1535 self.output.available_capacity()
1536 }
1537
1538 #[must_use]
1541 pub const fn has_buffered_output(&self) -> bool {
1542 !self.output.is_empty()
1543 }
1544
1545 #[must_use]
1551 pub const fn has_finished_input(&self) -> bool {
1552 self.finished
1553 }
1554
1555 #[must_use]
1558 pub const fn is_finished(&self) -> bool {
1559 self.finished && self.output.is_empty()
1560 }
1561
1562 #[must_use]
1565 pub const fn is_failed(&self) -> bool {
1566 self.failed
1567 }
1568
1569 #[must_use]
1572 pub const fn can_into_inner(&self) -> bool {
1573 self.is_finished() && !self.failed
1574 }
1575
1576 #[must_use]
1578 pub fn into_inner(mut self) -> R {
1579 self.take_inner()
1580 }
1581
1582 #[allow(clippy::result_large_err)]
1589 pub fn try_into_inner(mut self) -> Result<R, Self> {
1590 if !self.can_into_inner() {
1591 return Err(self);
1592 }
1593 Ok(self.take_inner())
1594 }
1595
1596 fn inner_ref(&self) -> &R {
1597 match &self.inner {
1598 Some(inner) => inner,
1599 None => unreachable!("stream encoder reader inner reader was already taken"),
1600 }
1601 }
1602
1603 fn inner_mut(&mut self) -> &mut R {
1604 match &mut self.inner {
1605 Some(inner) => inner,
1606 None => unreachable!("stream encoder reader inner reader was already taken"),
1607 }
1608 }
1609
1610 fn take_inner(&mut self) -> R {
1611 match self.inner.take() {
1612 Some(inner) => inner,
1613 None => unreachable!("stream encoder reader inner reader was already taken"),
1614 }
1615 }
1616
1617 fn clear_pending(&mut self) {
1618 crate::wipe_bytes(&mut self.pending);
1619 self.pending_len = 0;
1620 }
1621}
1622
1623impl<R, A, const PAD: bool> Drop for EncoderReader<R, A, PAD>
1624where
1625 A: Alphabet,
1626{
1627 fn drop(&mut self) {
1628 self.clear_pending();
1629 self.output.clear_all();
1630 }
1631}
1632
1633impl<R, A, const PAD: bool> core::fmt::Debug for EncoderReader<R, A, PAD>
1634where
1635 A: Alphabet,
1636{
1637 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1638 formatter
1639 .debug_struct("EncoderReader")
1640 .field("inner", &redacted_inner_state(self.inner.is_some()))
1641 .field("engine", &self.engine)
1642 .field("pending", &"<redacted>")
1643 .field("pending_len", &self.pending_len)
1644 .field("pending_input_needed_len", &self.pending_input_needed_len())
1645 .field("buffered_output_len", &self.output.len())
1646 .field("buffered_output_capacity", &self.output.capacity())
1647 .field(
1648 "buffered_output_remaining_capacity",
1649 &self.output.available_capacity(),
1650 )
1651 .field("can_into_inner", &self.can_into_inner())
1652 .field("finished", &self.finished)
1653 .field("failed", &self.failed)
1654 .finish()
1655 }
1656}
1657
1658impl<R, A, const PAD: bool> Read for EncoderReader<R, A, PAD>
1659where
1660 R: Read,
1661 A: Alphabet,
1662{
1663 fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
1664 if self.failed {
1665 return Err(stream_encoder_failed_error());
1666 }
1667
1668 if output.is_empty() {
1669 return Ok(0);
1670 }
1671
1672 while self.output.is_empty() && !self.finished {
1673 self.fill_output()?;
1674 }
1675
1676 Ok(self.output.pop_slice(output))
1677 }
1678}
1679
1680impl<R, A, const PAD: bool> EncoderReader<R, A, PAD>
1681where
1682 R: Read,
1683 A: Alphabet,
1684{
1685 fn fill_output(&mut self) -> io::Result<()> {
1686 let mut input = [0u8; 768];
1687 let read = match self.inner_mut().read(&mut input) {
1688 Ok(read) => read,
1689 Err(err) => {
1690 crate::wipe_bytes(&mut input);
1691 return Err(err);
1692 }
1693 };
1694 if read == 0 {
1695 crate::wipe_bytes(&mut input);
1696 self.finished = true;
1697 if let Err(err) = self.push_final_pending() {
1698 self.failed = true;
1699 return Err(err);
1700 }
1701 return Ok(());
1702 }
1703
1704 let mut consumed = 0;
1705 if self.pending_len > 0 {
1706 let needed = 3 - self.pending_len;
1707 if read < needed {
1708 self.pending[self.pending_len..self.pending_len + read]
1709 .copy_from_slice(&input[..read]);
1710 self.pending_len += read;
1711 crate::wipe_bytes(&mut input);
1712 return Ok(());
1713 }
1714
1715 let mut chunk = [0u8; 3];
1716 chunk[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
1717 chunk[self.pending_len..].copy_from_slice(&input[..needed]);
1718 let result = self.push_encoded(&chunk);
1719 crate::wipe_bytes(&mut chunk);
1720 if let Err(err) = result {
1721 crate::wipe_bytes(&mut input);
1722 self.failed = true;
1723 return Err(err);
1724 }
1725 self.clear_pending();
1726 consumed += needed;
1727 }
1728
1729 let remaining = &input[consumed..read];
1730 let full_len = remaining.len() / 3 * 3;
1731 let tail_len = remaining.len() - full_len;
1732 let mut tail = [0u8; 2];
1733 tail[..tail_len].copy_from_slice(&remaining[full_len..]);
1734 let result = if full_len > 0 {
1735 self.push_encoded(&remaining[..full_len])
1736 } else {
1737 Ok(())
1738 };
1739 crate::wipe_bytes(&mut input);
1740 if let Err(err) = result {
1741 crate::wipe_bytes(&mut tail);
1742 self.failed = true;
1743 return Err(err);
1744 }
1745 self.pending[..tail_len].copy_from_slice(&tail[..tail_len]);
1746 crate::wipe_bytes(&mut tail);
1747 self.pending_len = tail_len;
1748 Ok(())
1749 }
1750
1751 fn push_final_pending(&mut self) -> io::Result<()> {
1752 if self.pending_len == 0 {
1753 return Ok(());
1754 }
1755
1756 let mut pending = [0u8; 2];
1757 pending[..self.pending_len].copy_from_slice(&self.pending[..self.pending_len]);
1758 let pending_len = self.pending_len;
1759 self.clear_pending();
1760 let result = self.push_encoded(&pending[..pending_len]);
1761 crate::wipe_bytes(&mut pending);
1762 result
1763 }
1764
1765 fn push_encoded(&mut self, input: &[u8]) -> io::Result<()> {
1766 let mut encoded = [0u8; 1024];
1767 let written = match self.engine.encode_slice(input, &mut encoded) {
1768 Ok(written) => written,
1769 Err(err) => {
1770 crate::wipe_bytes(&mut encoded);
1771 return Err(encode_error_to_io(err));
1772 }
1773 };
1774 let result = self.output.push_slice(&encoded[..written]);
1775 crate::wipe_bytes(&mut encoded);
1776 result
1777 }
1778}
1779
1780const fn redacted_inner_state(present: bool) -> &'static str {
1781 if present { "<present>" } else { "<taken>" }
1782}