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