qubit_codec/transcode/io/transcode_decode_input.rs
1// =============================================================================
2// Copyright (c) 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Buffered input driver that decodes units into values.
9
10use core::fmt;
11use std::collections::TryReserveError;
12use std::io::{
13 Error,
14 ErrorKind,
15 Read,
16 Result,
17 Seek,
18 SeekFrom,
19};
20
21use qubit_io::{
22 Buffer,
23 BufferedInput,
24 Input,
25 Seekable,
26 UncheckedSlice,
27};
28
29use crate::{
30 Codec,
31 DecodeLifecycleOutput,
32 DecodeLifecycleProgress,
33 TranscodeFailure,
34 TranscodeProgress,
35 TranscodeStatus,
36 Transcoder,
37 codec::assert_unit_bounds,
38};
39
40use super::codec_decode_driver::CodecDecodeDriver;
41use super::transcode_progress_validation::validate_decode_progress;
42
43/// Decodes an [`Input`] unit stream into an [`Input`] value stream.
44///
45/// This type owns only the unit-level [`qubit_io::BufferedInput`]. Callers pass
46/// a streaming [`Transcoder`] and error mapper to each decode operation, which
47/// lets one buffered input drive different decoders without nesting buffers or
48/// storing decoder-specific state in the buffer owner.
49///
50/// # Type Parameters
51///
52/// * `I` - Wrapped unit input.
53pub struct TranscodeDecodeInput<I>
54where
55 I: Input,
56 I::Item: Copy + Default,
57{
58 input: BufferedInput<I>,
59}
60
61impl<I> TranscodeDecodeInput<I>
62where
63 I: Input,
64 I::Item: Copy + Default,
65{
66 /// Creates a decoder input with the default unit buffer capacity.
67 ///
68 /// # Parameters
69 ///
70 /// * `inner` - Unit input read by this adapter.
71 ///
72 /// # Returns
73 ///
74 /// A new buffered decoder input.
75 #[must_use]
76 pub fn new(inner: I) -> Self {
77 Self {
78 input: BufferedInput::new(inner),
79 }
80 }
81
82 /// Creates a decoder input with a unit buffer of at least `capacity`.
83 ///
84 /// # Parameters
85 ///
86 /// * `inner` - Unit input read by this adapter.
87 /// * `capacity` - Requested internal unit buffer capacity.
88 ///
89 /// # Returns
90 ///
91 /// A new buffered decoder input.
92 #[must_use]
93 pub fn with_capacity(inner: I, capacity: usize) -> Self {
94 Self {
95 input: BufferedInput::with_capacity(inner, capacity),
96 }
97 }
98
99 /// Creates a decoder input with a unit buffer of at least `capacity`.
100 ///
101 /// # Parameters
102 ///
103 /// * `inner` - Unit input read by this adapter.
104 /// * `capacity` - Requested internal unit buffer capacity.
105 ///
106 /// # Errors
107 ///
108 /// Returns an allocation error when the requested buffer cannot be
109 /// allocated.
110 #[inline]
111 pub fn try_with_capacity(
112 inner: I,
113 capacity: usize,
114 ) -> std::result::Result<Self, TryReserveError> {
115 Ok(Self {
116 input: BufferedInput::try_with_capacity(inner, capacity)?,
117 })
118 }
119
120 /// Returns a shared reference to the wrapped unit input.
121 ///
122 /// The wrapped input can be physically positioned after units that remain
123 /// unread in this adapter's internal buffer.
124 ///
125 /// # Returns
126 ///
127 /// A shared reference to the wrapped unit input.
128 #[must_use]
129 pub const fn inner(&self) -> &I {
130 self.input.inner()
131 }
132
133 /// Returns the number of unread units currently buffered.
134 ///
135 /// # Returns
136 ///
137 /// The number of unread units in the internal buffer.
138 #[must_use]
139 pub fn unread_len(&self) -> usize {
140 self.input.unread_len()
141 }
142
143 /// Returns the currently buffered unread units.
144 ///
145 /// # Returns
146 ///
147 /// Returns a shared slice over the unread portion of the internal unit
148 /// buffer. The slice is valid until this adapter is mutated.
149 #[must_use]
150 pub fn unread(&self) -> &[I::Item] {
151 self.input.unread()
152 }
153
154 /// Returns the internal unit buffer capacity.
155 ///
156 /// # Returns
157 ///
158 /// The maximum number of units retained in the internal buffer.
159 #[must_use]
160 pub fn capacity(&self) -> usize {
161 self.input.capacity()
162 }
163
164 /// Refills the internal buffer until at least `count` unread units are
165 /// available.
166 ///
167 /// # Parameters
168 ///
169 /// * `count` - Minimum number of unread units required.
170 ///
171 /// # Errors
172 ///
173 /// Returns allocation errors mapped to [`ErrorKind::OutOfMemory`], or I/O
174 /// errors from the wrapped input while refilling.
175 pub fn fill_until(&mut self, count: usize) -> std::io::Result<bool> {
176 if count > self.input.capacity() {
177 self.input
178 .try_reserve_capacity(count)
179 .map_err(allocation_to_io_error)?;
180 }
181 self.input.fill_until(count)
182 }
183
184 /// Performs one decode step and preserves the transcoder stop status.
185 ///
186 /// `None` means that the wrapped input reached EOF with no buffered units.
187 /// Consumed input is committed before this method returns. Callers can use
188 /// the returned [`TranscodeProgress`] to distinguish `NeedOutput` from an
189 /// incomplete input tail without guessing from the unread buffer alone.
190 pub fn transcode_step<D, M, Value>(
191 &mut self,
192 decoder: &mut D,
193 map_error: &mut M,
194 output: &mut [Value],
195 output_index: usize,
196 count: usize,
197 ) -> Result<Option<TranscodeProgress>>
198 where
199 D: Transcoder<Input = I::Item, Output = Value>,
200 M: FnMut(D::Error) -> Error,
201 {
202 let output_end = UncheckedSlice::checked_range_end(
203 output.len(),
204 output_index,
205 count,
206 "decoded output range exceeds destination buffer",
207 )?;
208 if count == 0 {
209 return Ok(Some(TranscodeProgress::complete(0, 0)));
210 }
211 if self.unread_len() == 0 && !self.fill_more()? {
212 return Ok(None);
213 }
214 let available_input = self.unread_len();
215 let progress = decoder
216 .transcode(
217 self.unread(),
218 0,
219 &mut output[..output_end],
220 output_index,
221 )
222 .map_err(&mut *map_error)
223 .and_then(|progress| {
224 validate_decode_progress(
225 progress,
226 0,
227 available_input,
228 output_index,
229 count,
230 )
231 })?;
232 self.consume(progress.read());
233 Ok(Some(progress))
234 }
235
236 /// Performs one decode step after the caller has established EOF.
237 ///
238 /// This method does not read from the wrapped input. It passes the current
239 /// unread buffer to [`Transcoder::transcode_eof`], validates the returned
240 /// progress, and commits consumed source units before returning.
241 ///
242 /// # Errors
243 ///
244 /// Returns invalid output-range errors, or decoder errors mapped by
245 /// `map_error`.
246 pub fn transcode_eof_step<D, M, Value>(
247 &mut self,
248 decoder: &mut D,
249 map_error: &mut M,
250 output: &mut [Value],
251 output_index: usize,
252 count: usize,
253 ) -> Result<TranscodeProgress>
254 where
255 D: Transcoder<Input = I::Item, Output = Value>,
256 M: FnMut(D::Error) -> Error,
257 {
258 let output_end = UncheckedSlice::checked_range_end(
259 output.len(),
260 output_index,
261 count,
262 "decoded EOF output range exceeds destination buffer",
263 )?;
264 if count == 0 {
265 return Ok(TranscodeProgress::complete(0, 0));
266 }
267 if self.unread_len() == 0 {
268 return Ok(TranscodeProgress::complete(0, 0));
269 }
270 let available_input = self.unread_len();
271 let progress = decoder
272 .transcode_eof(
273 self.unread(),
274 0,
275 &mut output[..output_end],
276 output_index,
277 )
278 .map_err(&mut *map_error)
279 .and_then(|progress| {
280 validate_decode_progress(
281 progress,
282 0,
283 available_input,
284 output_index,
285 count,
286 )
287 })?;
288 self.consume(progress.read());
289 Ok(progress)
290 }
291
292 /// Consumes unread units from the current buffer window.
293 ///
294 /// # Parameters
295 ///
296 /// * `count` - Number of unread units to discard.
297 ///
298 /// # Panics
299 ///
300 /// Panics when `count` exceeds [`Self::unread_len`].
301 pub fn consume(&mut self, count: usize) {
302 assert!(
303 count <= self.unread_len(),
304 "cannot consume beyond buffered input",
305 );
306 // SAFETY: The caller-provided count is within the unread window.
307 unsafe {
308 self.input.consume(count);
309 }
310 }
311
312 /// Copies unread units into an indexed output range without consuming them.
313 ///
314 /// # Parameters
315 ///
316 /// * `output` - Destination storage that receives a copy of unread units.
317 /// * `output_index` - Start index inside `output`.
318 /// * `count` - Number of unread units to copy.
319 ///
320 /// # Safety
321 ///
322 /// The caller must guarantee that `output_index..output_index + count` is
323 /// a valid range inside `output`, that the addition does not overflow, that
324 /// `count <= self.unread_len()`, and that the destination range does not
325 /// overlap with the unread units stored inside this buffer.
326 pub unsafe fn copy_unread_to(
327 &self,
328 output: &mut [I::Item],
329 output_index: usize,
330 count: usize,
331 ) {
332 // SAFETY: The caller guarantees the destination range and non-overlap
333 // requirements for the unread copy.
334 let unread = self.unread();
335 unsafe {
336 UncheckedSlice::copy_nonoverlapping(
337 unread,
338 0,
339 output,
340 output_index,
341 count,
342 );
343 }
344 }
345
346 /// Consumes this adapter and returns its parts.
347 ///
348 /// # Returns
349 ///
350 /// The wrapped input and the buffer holding unread units.
351 #[must_use = "the returned input and unread buffer must be handled"]
352 pub fn into_parts(self) -> (I, Buffer<I::Item>) {
353 self.input.into_parts()
354 }
355
356 /// Reads buffered units into an indexed output range.
357 ///
358 /// # Parameters
359 ///
360 /// * `output` - Destination unit storage.
361 /// * `output_index` - Start index inside `output`.
362 /// * `count` - Maximum number of units to read.
363 ///
364 /// # Returns
365 ///
366 /// The number of units copied into `output`.
367 ///
368 /// # Errors
369 ///
370 /// Returns input or buffer validation errors from the wrapped
371 /// [`qubit_io::BufferedInput`].
372 ///
373 /// # Safety
374 ///
375 /// The caller must guarantee that `output_index..output_index + count` is
376 /// a valid range inside `output` and that the addition does not overflow.
377 pub unsafe fn read_unchecked(
378 &mut self,
379 output: &mut [I::Item],
380 output_index: usize,
381 count: usize,
382 ) -> Result<usize> {
383 debug_assert!(
384 UncheckedSlice::range_fits(output.len(), output_index, count),
385 "unchecked read output range exceeds destination buffer",
386 );
387 if count == 0 {
388 return Ok(0);
389 }
390 // SAFETY: The caller guarantees the destination range is valid.
391 unsafe { self.input.read_unchecked(output, output_index, count) }
392 }
393
394 /// Decodes one codec value from the buffered unit input.
395 ///
396 /// This strict convenience method supports codecs whose decode reset and
397 /// finish phases do not emit values. Use
398 /// [`Self::read_decoded_lifecycle_with`] when those phases have output.
399 ///
400 /// # Parameters
401 ///
402 /// * `codec` - Codec used for this single-value decode.
403 /// * `map_error` - Mapper for codec-domain invalid-input errors.
404 ///
405 /// # Returns
406 ///
407 /// Returns one decoded codec value.
408 ///
409 /// # Errors
410 ///
411 /// Returns [`ErrorKind::Unsupported`] before invoking the codec or reading
412 /// input when reset or finish may emit values. Otherwise, returns I/O
413 /// errors from the wrapped input, `UnexpectedEof` when EOF occurs before a
414 /// complete value is available, `InvalidData` when the codec reports an
415 /// impossible incomplete state, or the error returned by `map_error` for
416 /// codec reset, invalid input, or codec finish failures.
417 ///
418 /// # Panics
419 ///
420 /// Panics when the codec reports more reset or finish values than its
421 /// declared bounds.
422 pub fn read_decoded_with<C, M>(
423 &mut self,
424 codec: &mut C,
425 map_error: M,
426 ) -> Result<C::Value>
427 where
428 C: Codec<Unit = I::Item>,
429 M: FnMut(C::DecodeError) -> Error,
430 {
431 TranscodeFailure::ensure_no_decode_lifecycle_output::<C>()
432 .map_err(|error| Error::new(ErrorKind::Unsupported, error))?;
433 let progress = self.read_decoded_lifecycle_with_scratch_impl(
434 codec,
435 &mut [],
436 &mut [],
437 map_error,
438 )?;
439 let (value, reset_written, finish_written) = progress.into_parts();
440 debug_assert_eq!(0, reset_written);
441 debug_assert_eq!(0, finish_written);
442 Ok(value)
443 }
444
445 /// Decodes one complete codec lifecycle and preserves every output phase.
446 ///
447 /// The method allocates independent storage for values emitted by
448 /// `decode_reset` and `decode_finish`, so neither phase can overwrite the
449 /// other.
450 ///
451 /// # Parameters
452 ///
453 /// - `codec`: Codec used to decode one complete lifecycle.
454 /// - `map_error`: Maps codec decode errors to I/O errors.
455 ///
456 /// # Returns
457 ///
458 /// Returns reset output, the main decoded value, and finish output.
459 ///
460 /// # Errors
461 ///
462 /// Returns I/O errors from the wrapped input, `UnexpectedEof` when EOF
463 /// occurs before a complete value is available, `InvalidData` when the
464 /// codec reports an impossible incomplete state, or the error returned
465 /// by `map_error` for codec reset, invalid input, or codec finish failures.
466 ///
467 /// # Panics
468 ///
469 /// Panics when the codec reports more reset or finish values than its
470 /// declared bounds.
471 pub fn read_decoded_lifecycle_with<C, M>(
472 &mut self,
473 codec: &mut C,
474 map_error: M,
475 ) -> Result<DecodeLifecycleOutput<C::Value>>
476 where
477 C: Codec<Unit = I::Item>,
478 C::Value: Default,
479 M: FnMut(C::DecodeError) -> Error,
480 {
481 assert_unit_bounds::<C>();
482 let mut reset_output = Vec::new();
483 reset_output.resize_with(C::MAX_DECODE_RESET_VALUES, C::Value::default);
484 let mut finish_output = Vec::new();
485 finish_output
486 .resize_with(C::MAX_DECODE_FINISH_VALUES, C::Value::default);
487 let progress = self.read_decoded_lifecycle_with_scratch_impl(
488 codec,
489 &mut reset_output,
490 &mut finish_output,
491 map_error,
492 )?;
493 let (value, reset_written, finish_written) = progress.into_parts();
494 reset_output.truncate(reset_written);
495 finish_output.truncate(finish_written);
496 Ok(DecodeLifecycleOutput::new(
497 reset_output,
498 value,
499 finish_output,
500 ))
501 }
502
503 /// Decodes one complete codec lifecycle into separate caller storage.
504 ///
505 /// # Parameters
506 ///
507 /// - `codec`: Codec used to decode one complete lifecycle.
508 /// - `reset_output`: Reusable storage for values emitted by
509 /// [`Codec::decode_reset`].
510 /// - `finish_output`: Reusable storage for values emitted by
511 /// [`Codec::decode_finish`].
512 /// - `map_error`: Maps codec decode errors to I/O errors.
513 ///
514 /// # Returns
515 ///
516 /// Returns the main decoded value and the initialized lengths of both
517 /// lifecycle output buffers.
518 ///
519 /// # Errors
520 ///
521 /// Returns [`ErrorKind::InvalidInput`] when either output buffer is shorter
522 /// than the corresponding codec bound. Returns I/O errors from the wrapped
523 /// input, `UnexpectedEof` when EOF occurs before a complete value is
524 /// available, `InvalidData` when the codec reports an impossible
525 /// incomplete state, or the error returned by `map_error` for codec reset,
526 /// invalid input, or codec finish failures.
527 ///
528 /// # Panics
529 ///
530 /// Panics when the codec reports more reset or finish values than its
531 /// declared bounds.
532 pub fn read_decoded_lifecycle_with_scratch<C, M>(
533 &mut self,
534 codec: &mut C,
535 reset_output: &mut [C::Value],
536 finish_output: &mut [C::Value],
537 map_error: M,
538 ) -> Result<DecodeLifecycleProgress<C::Value>>
539 where
540 C: Codec<Unit = I::Item>,
541 M: FnMut(C::DecodeError) -> Error,
542 {
543 self.read_decoded_lifecycle_with_scratch_impl(
544 codec,
545 reset_output,
546 finish_output,
547 map_error,
548 )
549 }
550
551 fn read_decoded_lifecycle_with_scratch_impl<C, M>(
552 &mut self,
553 codec: &mut C,
554 reset_output: &mut [C::Value],
555 finish_output: &mut [C::Value],
556 mut map_error: M,
557 ) -> Result<DecodeLifecycleProgress<C::Value>>
558 where
559 C: Codec<Unit = I::Item>,
560 M: FnMut(C::DecodeError) -> Error,
561 {
562 assert_unit_bounds::<C>();
563 if reset_output.len() < C::MAX_DECODE_RESET_VALUES {
564 return Err(Error::new(
565 ErrorKind::InvalidInput,
566 "decode reset output is shorter than the codec reset bound",
567 ));
568 }
569 if finish_output.len() < C::MAX_DECODE_FINISH_VALUES {
570 return Err(Error::new(
571 ErrorKind::InvalidInput,
572 "decode finish output is shorter than the codec finish bound",
573 ));
574 }
575 let reset_written = unsafe {
576 // SAFETY: The reset output length check above reserves the codec's
577 // declared decode-reset output bound.
578 codec.decode_reset(reset_output, 0)
579 }
580 .map_err(&mut map_error)?;
581 assert!(
582 reset_written <= C::MAX_DECODE_RESET_VALUES,
583 "Codec::decode_reset wrote beyond its reset bound",
584 );
585
586 let value = CodecDecodeDriver::new(&mut self.input)
587 .read_one(codec, &mut map_error)?;
588
589 let finish_written = unsafe {
590 // SAFETY: The finish output length check above reserves the
591 // codec's declared decode-finish output bound.
592 codec.decode_finish(finish_output, 0)
593 }
594 .map_err(&mut map_error)?;
595 assert!(
596 finish_written <= C::MAX_DECODE_FINISH_VALUES,
597 "Codec::decode_finish wrote beyond its finish bound",
598 );
599 Ok(DecodeLifecycleProgress::new(
600 value,
601 reset_written,
602 finish_written,
603 ))
604 }
605
606 /// Runs decoder reset into an indexed output range.
607 ///
608 /// This method does not read or consume buffered input units.
609 ///
610 /// # Errors
611 ///
612 /// Returns invalid output ranges, insufficient declared output capacity,
613 /// capacity errors, or reset errors mapped by `map_error`.
614 ///
615 /// # Panics
616 ///
617 /// Panics when the decoder reports writing more values than its declared
618 /// reset bound.
619 pub fn reset<D, M, Value>(
620 &self,
621 decoder: &mut D,
622 map_error: &mut M,
623 output: &mut [Value],
624 output_index: usize,
625 count: usize,
626 ) -> Result<usize>
627 where
628 D: Transcoder<Input = I::Item, Output = Value>,
629 M: FnMut(D::Error) -> Error,
630 {
631 let required = decoder
632 .max_reset_output_len()
633 .map_err(capacity_to_io_error)?;
634 let output_end = UncheckedSlice::checked_range_end(
635 output.len(),
636 output_index,
637 count,
638 "reset output range exceeds destination buffer",
639 )?;
640 if count < required {
641 return Err(Error::new(
642 ErrorKind::InvalidData,
643 "insufficient output for decoder reset bound",
644 ));
645 }
646 let output = &mut output[..output_end];
647 let written = decoder
648 .reset(output, output_index)
649 .map_err(&mut *map_error)?;
650 assert!(written <= required, "reset wrote beyond its bound");
651 Ok(written)
652 }
653
654 /// Decodes values into an indexed output range using a streaming
655 /// [`Transcoder`].
656 ///
657 /// # Parameters
658 ///
659 /// * `decoder` - Streaming decoder used for this operation.
660 /// * `map_error` - Function mapping transcode errors into I/O errors.
661 /// * `output` - Destination value storage.
662 /// * `output_index` - Start index inside `output`.
663 /// * `count` - Maximum number of values to write.
664 ///
665 /// # Returns
666 ///
667 /// The number of values written. Once a refill confirms EOF, any retained
668 /// tail is passed to [`Transcoder::transcode_eof`] before this method
669 /// returns.
670 ///
671 /// # Errors
672 ///
673 /// Returns input errors, invalid output ranges, capacity errors from the
674 /// internal buffer, or transcode errors mapped by `map_error`.
675 pub fn transcode<D, M, Value>(
676 &mut self,
677 decoder: &mut D,
678 map_error: &mut M,
679 output: &mut [Value],
680 output_index: usize,
681 count: usize,
682 ) -> Result<usize>
683 where
684 D: Transcoder<Input = I::Item, Output = Value>,
685 M: FnMut(D::Error) -> Error,
686 {
687 let output_end = UncheckedSlice::checked_range_end(
688 output.len(),
689 output_index,
690 count,
691 "decoded output range exceeds destination buffer",
692 )?;
693 if count == 0 {
694 return Ok(0);
695 }
696 let output = &mut output[..output_end];
697 let mut written_total = 0;
698 loop {
699 if self.unread_len() == 0 && !self.fill_more()? {
700 return Ok(written_total);
701 }
702 let units = self.unread();
703 let available_input = units.len();
704 let remaining_output = count - written_total;
705 let progress = decoder
706 .transcode(units, 0, output, output_index + written_total)
707 .map_err(&mut *map_error)?;
708 let progress = validate_decode_progress(
709 progress,
710 0,
711 available_input,
712 output_index + written_total,
713 remaining_output,
714 )?;
715 let consumed = progress.read();
716 let written = progress.written();
717 self.consume(consumed);
718 written_total += written;
719 match progress.status() {
720 TranscodeStatus::Complete => {
721 if written_total == count {
722 return Ok(written_total);
723 }
724 }
725 TranscodeStatus::NeedOutput { .. } => {
726 return Ok(written_total);
727 }
728 TranscodeStatus::NeedInput { required, .. } => {
729 if self.fill_until(required.get())? {
730 continue;
731 }
732 let remaining_output = count - written_total;
733 let eof_progress = self.transcode_eof_step(
734 decoder,
735 map_error,
736 output,
737 output_index + written_total,
738 remaining_output,
739 )?;
740 written_total += eof_progress.written();
741 return Ok(written_total);
742 }
743 }
744 }
745 }
746
747 /// Finishes a streaming decoder into an indexed output range.
748 ///
749 /// # Parameters
750 ///
751 /// * `decoder` - Streaming decoder whose final output is being collected.
752 /// * `map_error` - Function mapping transcode errors into I/O errors.
753 /// * `output` - Destination value storage.
754 /// * `output_index` - Start index inside `output`.
755 /// * `count` - Maximum number of finish values to write.
756 ///
757 /// # Returns
758 ///
759 /// The number of values written by the decoder finish operation.
760 ///
761 /// # Errors
762 ///
763 /// Returns invalid output ranges, capacity errors, or transcode
764 /// finalization errors mapped to I/O errors.
765 ///
766 /// # Panics
767 ///
768 /// Panics when the decoder reports writing more values than its
769 /// [`Transcoder::max_finish_output_len`] bound.
770 pub fn finish<D, M, Value>(
771 &self,
772 decoder: &mut D,
773 map_error: &mut M,
774 output: &mut [Value],
775 output_index: usize,
776 count: usize,
777 ) -> Result<usize>
778 where
779 D: Transcoder<Input = I::Item, Output = Value>,
780 M: FnMut(D::Error) -> Error,
781 {
782 let required = decoder
783 .max_finish_output_len()
784 .map_err(capacity_to_io_error)?;
785 // Validate the caller-supplied count range first (InvalidInput).
786 let output_end = UncheckedSlice::checked_range_end(
787 output.len(),
788 output_index,
789 count,
790 "finish output range exceeds destination buffer",
791 )?;
792 // `count` is the caller's declared writable finish range. The
793 // destination slice may be larger, but passing extra capacity to the
794 // decoder would allow it to write beyond the range the caller granted.
795 if count < required {
796 return Err(Error::new(
797 ErrorKind::InvalidData,
798 "insufficient output for decoder finish bound",
799 ));
800 }
801 let output = &mut output[..output_end];
802 let written = decoder
803 .finish(output, output_index)
804 .map_err(&mut *map_error)?;
805 assert!(written <= required, "finish wrote beyond its bound");
806 Ok(written)
807 }
808}
809
810impl<I> TranscodeDecodeInput<I>
811where
812 I: Input<Item = u8> + Seekable<Unit = u8>,
813{
814 /// Seeks the wrapped byte input and discards buffered bytes after success.
815 ///
816 /// # Parameters
817 ///
818 /// * `position` - Target seek position.
819 ///
820 /// # Returns
821 ///
822 /// The new stream position reported by the wrapped input.
823 ///
824 /// # Errors
825 ///
826 /// Returns seek errors from the wrapped input.
827 pub fn seek(&mut self, position: SeekFrom) -> Result<u64> {
828 self.input.seek_to(position)
829 }
830}
831
832impl<I> TranscodeDecodeInput<I>
833where
834 I: Input,
835 I::Item: Copy + Default,
836{
837 /// Refills the underlying buffer.
838 fn fill_more(&mut self) -> Result<bool> {
839 self.input.fill_more()
840 }
841}
842
843impl<I> Read for TranscodeDecodeInput<I>
844where
845 I: Input<Item = u8>,
846{
847 /// Reads raw bytes through the internal buffer.
848 fn read(&mut self, output: &mut [u8]) -> Result<usize> {
849 // SAFETY: The full output slice is a valid destination range.
850 unsafe { self.read_unchecked(output, 0, output.len()) }
851 }
852}
853
854impl<I> Seek for TranscodeDecodeInput<I>
855where
856 I: Input<Item = u8> + Seekable<Unit = u8>,
857{
858 /// Seeks the wrapped byte input and discards buffered bytes after success.
859 fn seek(&mut self, position: SeekFrom) -> Result<u64> {
860 self.seek(position)
861 }
862}
863
864impl<I> fmt::Debug for TranscodeDecodeInput<I>
865where
866 I: Input,
867 I::Item: Copy + Default,
868 BufferedInput<I>: fmt::Debug,
869{
870 /// Formats this buffered decode input for debugging.
871 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
872 formatter
873 .debug_struct("TranscodeDecodeInput")
874 .field("input", &self.input)
875 .finish()
876 }
877}
878
879/// Converts a capacity planning failure into an I/O error.
880fn capacity_to_io_error(error: crate::CapacityError) -> Error {
881 Error::new(ErrorKind::InvalidData, error)
882}
883
884/// Converts an allocation failure into an I/O boundary error.
885fn allocation_to_io_error(error: std::collections::TryReserveError) -> Error {
886 Error::new(ErrorKind::OutOfMemory, error)
887}