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