Skip to main content

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    /// Consumes unread units from the current buffer window.
237    ///
238    /// # Parameters
239    ///
240    /// * `count` - Number of unread units to discard.
241    ///
242    /// # Panics
243    ///
244    /// Panics when `count` exceeds [`Self::unread_len`].
245    pub fn consume(&mut self, count: usize) {
246        assert!(
247            count <= self.unread_len(),
248            "cannot consume beyond buffered input",
249        );
250        // SAFETY: The caller-provided count is within the unread window.
251        unsafe {
252            self.input.consume(count);
253        }
254    }
255
256    /// Copies unread units into an indexed output range without consuming them.
257    ///
258    /// # Parameters
259    ///
260    /// * `output` - Destination storage that receives a copy of unread units.
261    /// * `output_index` - Start index inside `output`.
262    /// * `count` - Number of unread units to copy.
263    ///
264    /// # Safety
265    ///
266    /// The caller must guarantee that `output_index..output_index + count` is
267    /// a valid range inside `output`, that the addition does not overflow, that
268    /// `count <= self.unread_len()`, and that the destination range does not
269    /// overlap with the unread units stored inside this buffer.
270    pub unsafe fn copy_unread_to(
271        &self,
272        output: &mut [I::Item],
273        output_index: usize,
274        count: usize,
275    ) {
276        // SAFETY: The caller guarantees the destination range and non-overlap
277        // requirements for the unread copy.
278        let unread = self.unread();
279        unsafe {
280            UncheckedSlice::copy_nonoverlapping(
281                unread,
282                0,
283                output,
284                output_index,
285                count,
286            );
287        }
288    }
289
290    /// Consumes this adapter and returns its parts.
291    ///
292    /// # Returns
293    ///
294    /// The wrapped input and the buffer holding unread units.
295    #[must_use = "the returned input and unread buffer must be handled"]
296    pub fn into_parts(self) -> (I, Buffer<I::Item>) {
297        self.input.into_parts()
298    }
299
300    /// Reads buffered units into an indexed output range.
301    ///
302    /// # Parameters
303    ///
304    /// * `output` - Destination unit storage.
305    /// * `output_index` - Start index inside `output`.
306    /// * `count` - Maximum number of units to read.
307    ///
308    /// # Returns
309    ///
310    /// The number of units copied into `output`.
311    ///
312    /// # Errors
313    ///
314    /// Returns input or buffer validation errors from the wrapped
315    /// [`qubit_io::BufferedInput`].
316    ///
317    /// # Safety
318    ///
319    /// The caller must guarantee that `output_index..output_index + count` is
320    /// a valid range inside `output` and that the addition does not overflow.
321    pub unsafe fn read_unchecked(
322        &mut self,
323        output: &mut [I::Item],
324        output_index: usize,
325        count: usize,
326    ) -> Result<usize> {
327        debug_assert!(
328            UncheckedSlice::range_fits(output.len(), output_index, count),
329            "unchecked read output range exceeds destination buffer",
330        );
331        if count == 0 {
332            return Ok(0);
333        }
334        // SAFETY: The caller guarantees the destination range is valid.
335        unsafe { self.input.read_unchecked(output, output_index, count) }
336    }
337
338    /// Decodes one codec value from the buffered unit input.
339    ///
340    /// This strict convenience method supports codecs whose decode reset and
341    /// finish phases do not emit values. Use
342    /// [`Self::read_decoded_lifecycle_with`] when those phases have output.
343    ///
344    /// # Parameters
345    ///
346    /// * `codec` - Codec used for this single-value decode.
347    /// * `map_error` - Mapper for codec-domain invalid-input errors.
348    ///
349    /// # Returns
350    ///
351    /// Returns one decoded codec value.
352    ///
353    /// # Errors
354    ///
355    /// Returns [`ErrorKind::Unsupported`] before invoking the codec or reading
356    /// input when reset or finish may emit values. Otherwise, returns I/O
357    /// errors from the wrapped input, `UnexpectedEof` when EOF occurs before a
358    /// complete value is available, `InvalidData` when the codec reports an
359    /// impossible incomplete state, or the error returned by `map_error` for
360    /// codec reset, invalid input, or codec finish failures.
361    ///
362    /// # Panics
363    ///
364    /// Panics when the codec reports more reset or finish values than its
365    /// declared bounds.
366    pub fn read_decoded_with<C, M>(
367        &mut self,
368        codec: &mut C,
369        map_error: M,
370    ) -> Result<C::Value>
371    where
372        C: Codec<Unit = I::Item>,
373        M: FnMut(C::DecodeError) -> Error,
374    {
375        TranscodeFailure::ensure_no_decode_lifecycle_output::<C>()
376            .map_err(|error| Error::new(ErrorKind::Unsupported, error))?;
377        let progress = self.read_decoded_lifecycle_with_scratch_impl(
378            codec,
379            &mut [],
380            &mut [],
381            map_error,
382        )?;
383        let (value, reset_written, finish_written) = progress.into_parts();
384        debug_assert_eq!(0, reset_written);
385        debug_assert_eq!(0, finish_written);
386        Ok(value)
387    }
388
389    /// Decodes one complete codec lifecycle and preserves every output phase.
390    ///
391    /// The method allocates independent storage for values emitted by
392    /// `decode_reset` and `decode_finish`, so neither phase can overwrite the
393    /// other.
394    ///
395    /// # Parameters
396    ///
397    /// - `codec`: Codec used to decode one complete lifecycle.
398    /// - `map_error`: Maps codec decode errors to I/O errors.
399    ///
400    /// # Returns
401    ///
402    /// Returns reset output, the main decoded value, and finish output.
403    ///
404    /// # Errors
405    ///
406    /// Returns I/O errors from the wrapped input, `UnexpectedEof` when EOF
407    /// occurs before a complete value is available, `InvalidData` when the
408    /// codec reports an impossible incomplete state, or the error returned
409    /// by `map_error` for codec reset, invalid input, or codec finish failures.
410    ///
411    /// # Panics
412    ///
413    /// Panics when the codec reports more reset or finish values than its
414    /// declared bounds.
415    pub fn read_decoded_lifecycle_with<C, M>(
416        &mut self,
417        codec: &mut C,
418        map_error: M,
419    ) -> Result<DecodeLifecycleOutput<C::Value>>
420    where
421        C: Codec<Unit = I::Item>,
422        C::Value: Default,
423        M: FnMut(C::DecodeError) -> Error,
424    {
425        assert_unit_bounds::<C>();
426        let mut reset_output = Vec::new();
427        reset_output.resize_with(C::MAX_DECODE_RESET_VALUES, C::Value::default);
428        let mut finish_output = Vec::new();
429        finish_output
430            .resize_with(C::MAX_DECODE_FINISH_VALUES, C::Value::default);
431        let progress = self.read_decoded_lifecycle_with_scratch_impl(
432            codec,
433            &mut reset_output,
434            &mut finish_output,
435            map_error,
436        )?;
437        let (value, reset_written, finish_written) = progress.into_parts();
438        reset_output.truncate(reset_written);
439        finish_output.truncate(finish_written);
440        Ok(DecodeLifecycleOutput::new(
441            reset_output,
442            value,
443            finish_output,
444        ))
445    }
446
447    /// Decodes one complete codec lifecycle into separate caller storage.
448    ///
449    /// # Parameters
450    ///
451    /// - `codec`: Codec used to decode one complete lifecycle.
452    /// - `reset_output`: Reusable storage for values emitted by
453    ///   [`Codec::decode_reset`].
454    /// - `finish_output`: Reusable storage for values emitted by
455    ///   [`Codec::decode_finish`].
456    /// - `map_error`: Maps codec decode errors to I/O errors.
457    ///
458    /// # Returns
459    ///
460    /// Returns the main decoded value and the initialized lengths of both
461    /// lifecycle output buffers.
462    ///
463    /// # Errors
464    ///
465    /// Returns [`ErrorKind::InvalidInput`] when either output buffer is shorter
466    /// than the corresponding codec bound. Returns I/O errors from the wrapped
467    /// input, `UnexpectedEof` when EOF occurs before a complete value is
468    /// available, `InvalidData` when the codec reports an impossible
469    /// incomplete state, or the error returned by `map_error` for codec reset,
470    /// invalid input, or codec finish failures.
471    ///
472    /// # Panics
473    ///
474    /// Panics when the codec reports more reset or finish values than its
475    /// declared bounds.
476    pub fn read_decoded_lifecycle_with_scratch<C, M>(
477        &mut self,
478        codec: &mut C,
479        reset_output: &mut [C::Value],
480        finish_output: &mut [C::Value],
481        map_error: M,
482    ) -> Result<DecodeLifecycleProgress<C::Value>>
483    where
484        C: Codec<Unit = I::Item>,
485        M: FnMut(C::DecodeError) -> Error,
486    {
487        self.read_decoded_lifecycle_with_scratch_impl(
488            codec,
489            reset_output,
490            finish_output,
491            map_error,
492        )
493    }
494
495    fn read_decoded_lifecycle_with_scratch_impl<C, M>(
496        &mut self,
497        codec: &mut C,
498        reset_output: &mut [C::Value],
499        finish_output: &mut [C::Value],
500        mut map_error: M,
501    ) -> Result<DecodeLifecycleProgress<C::Value>>
502    where
503        C: Codec<Unit = I::Item>,
504        M: FnMut(C::DecodeError) -> Error,
505    {
506        assert_unit_bounds::<C>();
507        if reset_output.len() < C::MAX_DECODE_RESET_VALUES {
508            return Err(Error::new(
509                ErrorKind::InvalidInput,
510                "decode reset output is shorter than the codec reset bound",
511            ));
512        }
513        if finish_output.len() < C::MAX_DECODE_FINISH_VALUES {
514            return Err(Error::new(
515                ErrorKind::InvalidInput,
516                "decode finish output is shorter than the codec finish bound",
517            ));
518        }
519        let reset_written = unsafe {
520            // SAFETY: The reset output length check above reserves the codec's
521            // declared decode-reset output bound.
522            codec.decode_reset(reset_output, 0)
523        }
524        .map_err(&mut map_error)?;
525        assert!(
526            reset_written <= C::MAX_DECODE_RESET_VALUES,
527            "Codec::decode_reset wrote beyond its reset bound",
528        );
529
530        let value = CodecDecodeDriver::new(&mut self.input)
531            .read_one(codec, &mut map_error)?;
532
533        let finish_written = unsafe {
534            // SAFETY: The finish output length check above reserves the
535            // codec's declared decode-finish output bound.
536            codec.decode_finish(finish_output, 0)
537        }
538        .map_err(&mut map_error)?;
539        assert!(
540            finish_written <= C::MAX_DECODE_FINISH_VALUES,
541            "Codec::decode_finish wrote beyond its finish bound",
542        );
543        Ok(DecodeLifecycleProgress::new(
544            value,
545            reset_written,
546            finish_written,
547        ))
548    }
549
550    /// Runs decoder reset into an indexed output range.
551    ///
552    /// This method does not read or consume buffered input units.
553    ///
554    /// # Errors
555    ///
556    /// Returns invalid output ranges, insufficient declared output capacity,
557    /// capacity errors, or reset errors mapped by `map_error`.
558    ///
559    /// # Panics
560    ///
561    /// Panics when the decoder reports writing more values than its declared
562    /// reset bound.
563    pub fn reset<D, M, Value>(
564        &self,
565        decoder: &mut D,
566        map_error: &mut M,
567        output: &mut [Value],
568        output_index: usize,
569        count: usize,
570    ) -> Result<usize>
571    where
572        D: Transcoder<Input = I::Item, Output = Value>,
573        M: FnMut(D::Error) -> Error,
574    {
575        let required = decoder
576            .max_reset_output_len()
577            .map_err(capacity_to_io_error)?;
578        let output_end = UncheckedSlice::checked_range_end(
579            output.len(),
580            output_index,
581            count,
582            "reset output range exceeds destination buffer",
583        )?;
584        if count < required {
585            return Err(Error::new(
586                ErrorKind::InvalidData,
587                "insufficient output for decoder reset bound",
588            ));
589        }
590        let output = &mut output[..output_end];
591        let written = decoder
592            .reset(output, output_index)
593            .map_err(&mut *map_error)?;
594        assert!(written <= required, "reset wrote beyond its bound");
595        Ok(written)
596    }
597
598    /// Decodes values into an indexed output range using a streaming
599    /// [`Transcoder`].
600    ///
601    /// # Parameters
602    ///
603    /// * `decoder` - Streaming decoder used for this operation.
604    /// * `map_error` - Function mapping transcode errors into I/O errors.
605    /// * `output` - Destination value storage.
606    /// * `output_index` - Start index inside `output`.
607    /// * `count` - Maximum number of values to write.
608    ///
609    /// # Returns
610    ///
611    /// The number of values written. Incomplete EOF tails are left buffered
612    /// and reported as `Ok(written)`, so callers can apply their own EOF
613    /// policy.
614    ///
615    /// # Errors
616    ///
617    /// Returns input errors, invalid output ranges, capacity errors from the
618    /// internal buffer, or transcode errors mapped by `map_error`.
619    pub fn transcode<D, M, Value>(
620        &mut 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 output_end = UncheckedSlice::checked_range_end(
632            output.len(),
633            output_index,
634            count,
635            "decoded output range exceeds destination buffer",
636        )?;
637        if count == 0 {
638            return Ok(0);
639        }
640        let output = &mut output[..output_end];
641        let mut written_total = 0;
642        loop {
643            if self.unread_len() == 0 && !self.fill_more()? {
644                return Ok(written_total);
645            }
646            let units = self.unread();
647            let available_input = units.len();
648            let remaining_output = count - written_total;
649            let progress = decoder
650                .transcode(units, 0, output, output_index + written_total)
651                .map_err(&mut *map_error)?;
652            let progress = validate_decode_progress(
653                progress,
654                0,
655                available_input,
656                output_index + written_total,
657                remaining_output,
658            )?;
659            let consumed = progress.read();
660            let written = progress.written();
661            self.consume(consumed);
662            written_total += written;
663            match progress.status() {
664                TranscodeStatus::Complete => {
665                    if written_total == count {
666                        return Ok(written_total);
667                    }
668                }
669                TranscodeStatus::NeedOutput { .. } => {
670                    return Ok(written_total);
671                }
672                TranscodeStatus::NeedInput { required, .. } => {
673                    if self.fill_until(required.get())? {
674                        continue;
675                    }
676                    return Ok(written_total);
677                }
678            }
679        }
680    }
681
682    /// Finishes a streaming decoder into an indexed output range.
683    ///
684    /// # Parameters
685    ///
686    /// * `decoder` - Streaming decoder whose final output is being collected.
687    /// * `map_error` - Function mapping transcode errors into I/O errors.
688    /// * `output` - Destination value storage.
689    /// * `output_index` - Start index inside `output`.
690    /// * `count` - Maximum number of finish values to write.
691    ///
692    /// # Returns
693    ///
694    /// The number of values written by the decoder finish operation.
695    ///
696    /// # Errors
697    ///
698    /// Returns invalid output ranges, capacity errors, or transcode
699    /// finalization errors mapped to I/O errors.
700    ///
701    /// # Panics
702    ///
703    /// Panics when the decoder reports writing more values than its
704    /// [`Transcoder::max_finish_output_len`] bound.
705    pub fn finish<D, M, Value>(
706        &self,
707        decoder: &mut D,
708        map_error: &mut M,
709        output: &mut [Value],
710        output_index: usize,
711        count: usize,
712    ) -> Result<usize>
713    where
714        D: Transcoder<Input = I::Item, Output = Value>,
715        M: FnMut(D::Error) -> Error,
716    {
717        let required = decoder
718            .max_finish_output_len()
719            .map_err(capacity_to_io_error)?;
720        // Validate the caller-supplied count range first (InvalidInput).
721        let output_end = UncheckedSlice::checked_range_end(
722            output.len(),
723            output_index,
724            count,
725            "finish output range exceeds destination buffer",
726        )?;
727        // `count` is the caller's declared writable finish range.  The
728        // destination slice may be larger, but passing extra capacity to the
729        // decoder would allow it to write beyond the range the caller granted.
730        if count < required {
731            return Err(Error::new(
732                ErrorKind::InvalidData,
733                "insufficient output for decoder finish bound",
734            ));
735        }
736        let output = &mut output[..output_end];
737        let written = decoder
738            .finish(output, output_index)
739            .map_err(&mut *map_error)?;
740        assert!(written <= required, "finish wrote beyond its bound");
741        Ok(written)
742    }
743}
744
745impl<I> TranscodeDecodeInput<I>
746where
747    I: Input<Item = u8> + Seekable<Unit = u8>,
748{
749    /// Seeks the wrapped byte input and discards buffered bytes after success.
750    ///
751    /// # Parameters
752    ///
753    /// * `position` - Target seek position.
754    ///
755    /// # Returns
756    ///
757    /// The new stream position reported by the wrapped input.
758    ///
759    /// # Errors
760    ///
761    /// Returns seek errors from the wrapped input.
762    pub fn seek(&mut self, position: SeekFrom) -> Result<u64> {
763        self.input.seek_to(position)
764    }
765}
766
767impl<I> TranscodeDecodeInput<I>
768where
769    I: Input,
770    I::Item: Copy + Default,
771{
772    /// Refills the underlying buffer.
773    fn fill_more(&mut self) -> Result<bool> {
774        self.input.fill_more()
775    }
776}
777
778impl<I> Read for TranscodeDecodeInput<I>
779where
780    I: Input<Item = u8>,
781{
782    /// Reads raw bytes through the internal buffer.
783    fn read(&mut self, output: &mut [u8]) -> Result<usize> {
784        // SAFETY: The full output slice is a valid destination range.
785        unsafe { self.read_unchecked(output, 0, output.len()) }
786    }
787}
788
789impl<I> Seek for TranscodeDecodeInput<I>
790where
791    I: Input<Item = u8> + Seekable<Unit = u8>,
792{
793    /// Seeks the wrapped byte input and discards buffered bytes after success.
794    fn seek(&mut self, position: SeekFrom) -> Result<u64> {
795        self.seek(position)
796    }
797}
798
799impl<I> fmt::Debug for TranscodeDecodeInput<I>
800where
801    I: Input,
802    I::Item: Copy + Default,
803    BufferedInput<I>: fmt::Debug,
804{
805    /// Formats this buffered decode input for debugging.
806    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
807        formatter
808            .debug_struct("TranscodeDecodeInput")
809            .field("input", &self.input)
810            .finish()
811    }
812}
813
814/// Converts a capacity planning failure into an I/O error.
815fn capacity_to_io_error(error: crate::CapacityError) -> Error {
816    Error::new(ErrorKind::InvalidData, error)
817}
818
819/// Converts an allocation failure into an I/O boundary error.
820fn allocation_to_io_error(error: std::collections::TryReserveError) -> Error {
821    Error::new(ErrorKind::OutOfMemory, error)
822}