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