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