Skip to main content

qubit_io/std_io/ext/
read_ext.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
9//! Extension operations for standard byte readers.
10
11use std::io::{
12    ErrorKind,
13    Read,
14    Result,
15    Write,
16    copy as copy_all,
17};
18
19use crate::Streams;
20use crate::std_io::ext::internal::read_ext_impl;
21use crate::util::{
22    UncheckedSlice,
23    allocation_error,
24    try_reserve_string,
25};
26
27/// Default stack buffer size used by discard operations.
28const DISCARD_BUFFER_SIZE: usize = 8 * 1024;
29
30/// Extension methods for [`Read`] values.
31///
32/// `ReadExt` fills small semantic gaps in the standard [`Read`] trait while
33/// keeping the same blocking and error model. The methods are implemented for
34/// every type that implements [`Read`], including `dyn Read` trait objects.
35///
36/// # Examples
37/// ```
38/// use qubit_io::std_io::ext::ReadExt;
39/// use std::io::Cursor;
40///
41/// let mut input = Cursor::new(b"abcdef".to_vec());
42/// let header = input.read_exact_array::<2>()?;
43/// let payload = input.read_exact_vec_limited(4, 16)?;
44///
45/// assert_eq!(*b"ab", header);
46/// assert_eq!(b"cdef", payload.as_slice());
47/// # Ok::<(), std::io::Error>(())
48/// ```
49pub trait ReadExt: Read {
50    /// Reads bytes into a range of `buffer` without checking the range bounds
51    /// in release builds.
52    ///
53    /// This method delegates to [`Read::read`] after creating the target slice
54    /// with raw pointer arithmetic. It performs at most one read operation and
55    /// returns the number of bytes read, keeping the same short-read and error
56    /// behavior as [`Read::read`].
57    ///
58    /// # Parameters
59    /// - `buffer`: Destination buffer.
60    /// - `start_index`: Start offset inside `buffer`.
61    /// - `count`: Maximum number of bytes to read.
62    ///
63    /// # Returns
64    /// The number of bytes written into `buffer[start_index..start_index +
65    /// count]`. The value is in `0..=count`.
66    ///
67    /// # Errors
68    /// Returns the error reported by [`Read::read`].
69    ///
70    /// # Panics
71    /// Panics in debug builds if the requested destination range does not fit.
72    ///
73    /// # Safety
74    /// The caller must guarantee that `start_index..start_index + count` is a
75    /// valid range within `buffer` and that `start_index + count` does not
76    /// overflow `usize`.
77    unsafe fn read_unchecked(
78        &mut self,
79        buffer: &mut [u8],
80        start_index: usize,
81        count: usize,
82    ) -> Result<usize>;
83
84    /// Reads exactly `count` bytes into a range of `buffer` without checking
85    /// the range bounds in release builds.
86    ///
87    /// This method delegates to [`Read::read_exact`] after creating the target
88    /// slice with raw pointer arithmetic. It keeps the same blocking and error
89    /// behavior as [`Read::read_exact`].
90    ///
91    /// # Parameters
92    /// - `buffer`: Destination buffer.
93    /// - `start_index`: Start offset inside `buffer`.
94    /// - `count`: Number of bytes to read.
95    ///
96    /// # Returns
97    /// `Ok(())` after the requested range has been filled.
98    ///
99    /// # Errors
100    /// Returns the error reported by [`Read::read_exact`], including
101    /// [`ErrorKind::UnexpectedEof`] when EOF is reached before `count` bytes
102    /// are read.
103    ///
104    /// # Panics
105    /// Panics in debug builds if the requested destination range does not fit.
106    ///
107    /// # Safety
108    /// The caller must guarantee that `start_index..start_index + count` is a
109    /// valid range within `buffer` and that `start_index + count` does not
110    /// overflow `usize`.
111    unsafe fn read_exact_unchecked(
112        &mut self,
113        buffer: &mut [u8],
114        start_index: usize,
115        count: usize,
116    ) -> Result<()>;
117
118    /// Reads bytes into a range of `buffer` until that range is full or EOF is
119    /// reached, without checking the range bounds in release builds.
120    ///
121    /// This method has the same EOF and retry behavior as
122    /// [`ReadExt::read_exact_or_eof`], but writes into
123    /// `buffer[start_index..start_index + count]` using raw pointer
124    /// arithmetic.
125    ///
126    /// # Parameters
127    /// - `buffer`: Destination buffer.
128    /// - `start_index`: Start offset inside `buffer`.
129    /// - `count`: Number of bytes to try to read.
130    ///
131    /// # Returns
132    /// The number of bytes written into `buffer[start_index..start_index +
133    /// count]`. The value is in `0..=count`.
134    ///
135    /// # Errors
136    /// Returns the first non-[`ErrorKind::Interrupted`] error reported by the
137    /// underlying reader. Interrupted reads are retried.
138    ///
139    /// # Panics
140    /// Panics in debug builds if the requested destination range does not fit.
141    ///
142    /// # Safety
143    /// The caller must guarantee that `start_index..start_index + count` is a
144    /// valid range within `buffer` and that `start_index + count` does not
145    /// overflow `usize`.
146    unsafe fn read_exact_or_eof_unchecked(
147        &mut self,
148        buffer: &mut [u8],
149        start_index: usize,
150        count: usize,
151    ) -> Result<usize>;
152
153    /// Reads bytes until `buffer` is full or EOF is reached.
154    ///
155    /// This method differs from [`Read::read_exact`] by treating EOF as a
156    /// successful partial result. It keeps retrying short reads until the
157    /// caller-provided buffer is full, EOF is reached, or a non-interrupted
158    /// I/O error occurs.
159    ///
160    /// # Parameters
161    /// - `buffer`: Destination buffer to fill.
162    ///
163    /// # Returns
164    /// The number of bytes written into `buffer`. The value is in
165    /// `0..=buffer.len()`.
166    ///
167    /// # Errors
168    /// Returns the first non-[`ErrorKind::Interrupted`] error reported by the
169    /// underlying reader. Interrupted reads are retried.
170    fn read_exact_or_eof(&mut self, buffer: &mut [u8]) -> Result<usize>;
171
172    /// Reads exactly `N` bytes into a stack-allocated array.
173    ///
174    /// This method uses [`Read::read_exact`] and therefore requires the reader
175    /// to provide exactly `N` bytes before EOF.
176    ///
177    /// # Type Parameters
178    /// - `N`: Number of bytes in the returned array.
179    ///
180    /// # Returns
181    /// An array containing exactly `N` bytes read from this reader.
182    ///
183    /// # Errors
184    /// Returns the error reported by [`Read::read_exact`], including
185    /// [`ErrorKind::UnexpectedEof`] when EOF is reached before the array is
186    /// full.
187    fn read_exact_array<const N: usize>(&mut self) -> Result<[u8; N]>;
188
189    /// Reads exactly `len` bytes into a new vector after checking a limit.
190    ///
191    /// If `len` is greater than `max_len`, this method returns
192    /// [`ErrorKind::InvalidData`] before reading any bytes.
193    ///
194    /// # Parameters
195    /// - `len`: Exact number of bytes to read.
196    /// - `max_len`: Maximum accepted exact read length.
197    ///
198    /// # Returns
199    /// A vector containing exactly `len` bytes.
200    ///
201    /// # Errors
202    /// Returns [`ErrorKind::InvalidData`] when `len > max_len`. Returns the
203    /// [`ErrorKind::OutOfMemory`] error when the result vector cannot be
204    /// allocated. Returns the error reported by [`Read::read_exact`], including
205    /// [`ErrorKind::UnexpectedEof`] when EOF is reached before `len` bytes are
206    /// read.
207    fn read_exact_vec_limited(
208        &mut self,
209        len: usize,
210        max_len: usize,
211    ) -> Result<Vec<u8>>;
212
213    /// Reads exactly `len` bytes and appends them to `output`.
214    ///
215    /// If `len` is greater than `max_len`, this method returns
216    /// [`ErrorKind::InvalidData`] before reading any bytes and leaves `output`
217    /// unchanged. On a read error, `output` is truncated back to its original
218    /// length. The underlying reader may still have consumed bytes before the
219    /// error because [`Read`] does not provide rollback.
220    ///
221    /// # Parameters
222    /// - `output`: Destination vector to append to.
223    /// - `len`: Exact number of bytes to read.
224    /// - `max_len`: Maximum accepted exact read length.
225    ///
226    /// # Returns
227    /// `Ok(())` after exactly `len` bytes have been appended to `output`.
228    ///
229    /// # Errors
230    /// Returns [`ErrorKind::InvalidData`] when `len > max_len`,
231    /// [`ErrorKind::InvalidInput`] when `output.len() + len` overflows, or
232    /// [`ErrorKind::OutOfMemory`] when `output` cannot reserve the appended
233    /// bytes. Returns the error reported by [`Read::read_exact`], including
234    /// [`ErrorKind::UnexpectedEof`] when EOF is reached before `len` bytes are
235    /// read.
236    fn read_exact_vec_limited_into(
237        &mut self,
238        output: &mut Vec<u8>,
239        len: usize,
240        max_len: usize,
241    ) -> Result<()>;
242
243    /// Discards up to `bytes` bytes from this reader.
244    ///
245    /// The method repeatedly reads into an internal stack buffer until the
246    /// requested number of bytes has been consumed or EOF is reached. It does
247    /// not allocate and does not require seeking support.
248    ///
249    /// # Parameters
250    /// - `bytes`: Maximum number of bytes to discard.
251    ///
252    /// # Returns
253    /// The number of bytes actually discarded. The value may be smaller than
254    /// `bytes` when EOF is reached first.
255    ///
256    /// # Errors
257    /// Returns the first non-[`ErrorKind::Interrupted`] error reported by the
258    /// underlying reader. Interrupted reads are retried.
259    fn discard_exact_or_eof(&mut self, bytes: u64) -> Result<u64>;
260
261    /// Copies all remaining bytes from this reader into `writer`.
262    ///
263    /// This method is a method-style wrapper around [`std::io::copy`]. It
264    /// copies from the current reader position until EOF and does not close or
265    /// flush either stream.
266    ///
267    /// # Parameters
268    /// - `writer`: Destination writer.
269    ///
270    /// # Returns
271    /// The number of bytes copied.
272    ///
273    /// # Errors
274    /// Returns the first read or write error reported by the underlying
275    /// streams, using the same error behavior as [`std::io::copy`].
276    fn copy_to(&mut self, writer: &mut dyn Write) -> Result<u64>;
277
278    /// Copies at most `max_bytes` bytes from this reader into `writer`.
279    ///
280    /// This method stops successfully when either EOF is reached or
281    /// `max_bytes` bytes have been copied. It does not close or flush either
282    /// stream.
283    ///
284    /// # Parameters
285    /// - `writer`: Destination writer.
286    /// - `max_bytes`: Maximum number of bytes to copy.
287    ///
288    /// # Returns
289    /// The number of bytes copied.
290    ///
291    /// # Errors
292    /// Returns [`ErrorKind::OutOfMemory`] if the temporary copy buffer cannot
293    /// be allocated. Returns the first non-[`ErrorKind::Interrupted`] read
294    /// error or write error reported by the underlying streams. Interrupted
295    /// reads are retried.
296    fn copy_to_at_most(
297        &mut self,
298        writer: &mut dyn Write,
299        max_bytes: u64,
300    ) -> Result<u64>;
301
302    /// Copies the remaining input if its total length is at most `max_bytes`.
303    ///
304    /// This method copies from the current reader position until EOF. If EOF is
305    /// not reached within `max_bytes` bytes, it returns
306    /// [`ErrorKind::InvalidData`]. Detecting oversized input consumes one
307    /// excess byte from this reader; that excess byte is not written to
308    /// `writer`.
309    ///
310    /// Unlike bounded reads into in-memory collections, this method cannot roll
311    /// back bytes already accepted by `writer` when the limit is exceeded
312    /// because [`Write`] does not provide truncation. On
313    /// [`ErrorKind::InvalidData`], up to `max_bytes` bytes may remain in
314    /// `writer`.
315    ///
316    /// # Parameters
317    /// - `writer`: Destination writer.
318    /// - `max_bytes`: Maximum accepted number of bytes in the remaining input.
319    ///
320    /// # Returns
321    /// The number of bytes copied when EOF is reached within the limit.
322    ///
323    /// # Errors
324    /// Returns [`ErrorKind::InvalidData`] when the remaining input is longer
325    /// than `max_bytes`. Returns [`ErrorKind::OutOfMemory`] if the temporary
326    /// copy buffer cannot be allocated. Returns the first
327    /// non-[`ErrorKind::Interrupted`] read error or write error reported by the
328    /// underlying streams. Interrupted reads are retried.
329    fn copy_to_end_limited(
330        &mut self,
331        writer: &mut dyn Write,
332        max_bytes: u64,
333    ) -> Result<u64>;
334
335    /// Reads the remaining bytes into a vector with a maximum accepted length.
336    ///
337    /// This method consumes bytes from the current reader position until EOF is
338    /// reached. If the stream contains more than `max_len` bytes, it returns
339    /// [`ErrorKind::InvalidData`] after detecting the first excess byte. No
340    /// vector is returned on failure.
341    ///
342    /// # Parameters
343    /// - `max_len`: Maximum number of bytes accepted in the returned vector.
344    ///
345    /// # Returns
346    /// A vector containing all remaining bytes when the stream length is within
347    /// the limit.
348    ///
349    /// # Errors
350    /// Returns [`ErrorKind::InvalidData`] when the stream contains more than
351    /// `max_len` bytes. Returns [`ErrorKind::OutOfMemory`] when the result
352    /// vector cannot grow. Returns the first non-[`ErrorKind::Interrupted`]
353    /// error reported by the underlying reader; interrupted reads are
354    /// retried.
355    fn read_to_end_limited(&mut self, max_len: usize) -> Result<Vec<u8>>;
356
357    /// Reads the remaining bytes into `output` with a maximum accepted length.
358    ///
359    /// This method appends at most `max_len` bytes from the current reader
360    /// position to `output`. If the stream contains more than `max_len` bytes,
361    /// it returns [`ErrorKind::InvalidData`] after detecting the first excess
362    /// byte and truncates `output` back to its original length. The underlying
363    /// reader may still have consumed bytes before the error because [`Read`]
364    /// does not provide rollback.
365    ///
366    /// # Parameters
367    /// - `output`: Destination vector to append to.
368    /// - `max_len`: Maximum number of bytes accepted from this reader.
369    ///
370    /// # Returns
371    /// The number of bytes appended to `output`.
372    ///
373    /// # Errors
374    /// Returns [`ErrorKind::InvalidData`] when the stream contains more than
375    /// `max_len` bytes. Returns [`ErrorKind::OutOfMemory`] when `output` cannot
376    /// grow. Returns the first non-[`ErrorKind::Interrupted`] error reported by
377    /// the underlying reader; interrupted reads are retried.
378    fn read_to_end_limited_into(
379        &mut self,
380        output: &mut Vec<u8>,
381        max_len: usize,
382    ) -> Result<usize>;
383
384    /// Reads the remaining bytes as UTF-8 text with a maximum accepted length.
385    ///
386    /// This method has the same size limit and read semantics as
387    /// [`ReadExt::read_to_end_limited`], then validates the collected bytes as
388    /// UTF-8.
389    ///
390    /// # Parameters
391    /// - `max_len`: Maximum number of bytes accepted before UTF-8 decoding.
392    ///
393    /// # Returns
394    /// The decoded UTF-8 string.
395    ///
396    /// # Errors
397    /// Returns [`ErrorKind::InvalidData`] when the stream contains more than
398    /// `max_len` bytes or when the collected bytes are not valid UTF-8. Returns
399    /// [`ErrorKind::OutOfMemory`] when the result buffer cannot grow. Returns
400    /// the first non-[`ErrorKind::Interrupted`] error reported by the
401    /// underlying reader; interrupted reads are retried.
402    fn read_to_string_limited(&mut self, max_len: usize) -> Result<String>;
403
404    /// Reads the remaining bytes as UTF-8 text and appends to `output`.
405    ///
406    /// This method accepts at most `max_len` bytes from the current reader
407    /// position, validates them as UTF-8, and appends the decoded text to
408    /// `output`. If the input is oversized or invalid UTF-8, `output` is
409    /// truncated back to its original length. Oversized input may still consume
410    /// up to `max_len + 1` bytes from the reader while detecting the limit
411    /// violation.
412    ///
413    /// # Parameters
414    /// - `output`: Destination string to append to.
415    /// - `max_len`: Maximum number of bytes accepted before UTF-8 decoding.
416    ///
417    /// # Returns
418    /// The number of bytes appended to `output`.
419    ///
420    /// # Errors
421    /// Returns [`ErrorKind::InvalidData`] when the stream contains more than
422    /// `max_len` bytes or when the collected bytes are not valid UTF-8. Returns
423    /// [`ErrorKind::OutOfMemory`] when the temporary byte buffer or `output`
424    /// cannot grow. Returns the first non-[`ErrorKind::Interrupted`] error
425    /// reported by the underlying reader; interrupted reads are retried.
426    fn read_to_string_limited_into(
427        &mut self,
428        output: &mut String,
429        max_len: usize,
430    ) -> Result<usize>;
431}
432
433/// Reads an indexed range to EOF through a type-erased reader.
434///
435/// # Parameters
436/// - `reader`: Reader that supplies the bytes.
437/// - `buffer`: Destination buffer.
438/// - `start_index`: Start offset inside `buffer`.
439/// - `count`: Number of bytes to try to read.
440///
441/// # Returns
442/// The number of bytes written into the requested range.
443///
444/// # Errors
445/// Returns the first non-interrupted read error.
446///
447/// # Panics
448/// Panics in debug builds if the requested output range does not fit.
449///
450/// # Safety
451/// The caller must guarantee that `start_index..start_index + count` is valid
452/// inside `buffer` and that the addition does not overflow.
453unsafe fn read_exact_or_eof_unchecked_impl(
454    reader: &mut dyn Read,
455    buffer: &mut [u8],
456    start_index: usize,
457    count: usize,
458) -> Result<usize> {
459    debug_assert!(
460        UncheckedSlice::range_fits(buffer.len(), start_index, count),
461        "unchecked read range exceeds buffer"
462    );
463    let mut total = 0;
464    while total < count {
465        // SAFETY: The caller guarantees that `start_index..start_index + count`
466        // is valid for `buffer`; `total < count`, so this suffix is valid.
467        let target = unsafe {
468            UncheckedSlice::subslice_mut(
469                buffer,
470                start_index + total,
471                count - total,
472            )
473        };
474        match reader.read(target) {
475            Ok(0) => break,
476            Ok(read) => total += read,
477            Err(error) => {
478                if error.kind() == ErrorKind::Interrupted {
479                    continue;
480                }
481                return Err(error);
482            }
483        }
484    }
485    Ok(total)
486}
487
488/// Reads a fixed-size byte array through a type-erased reader.
489///
490/// # Type Parameters
491/// - `N`: Number of bytes in the returned array.
492///
493/// # Parameters
494/// - `reader`: Reader that supplies the bytes.
495///
496/// # Returns
497/// An array containing exactly `N` bytes.
498///
499/// # Errors
500/// Returns the error reported by [`Read::read_exact`].
501#[inline]
502fn read_exact_array_impl<const N: usize>(
503    reader: &mut dyn Read,
504) -> Result<[u8; N]> {
505    let mut buffer = [0; N];
506    reader.read_exact(&mut buffer)?;
507    Ok(buffer)
508}
509
510/// Reads an exactly sized bounded vector through a type-erased reader.
511///
512/// # Parameters
513/// - `reader`: Reader that supplies the bytes.
514/// - `len`: Exact number of bytes to read.
515/// - `max_len`: Maximum accepted exact read length.
516///
517/// # Returns
518/// A vector containing exactly `len` bytes.
519///
520/// # Errors
521/// Returns [`ErrorKind::OutOfMemory`] if the result vector cannot be allocated,
522/// a read error, or [`ErrorKind::InvalidData`] when `len > max_len`.
523#[inline]
524fn read_exact_vec_limited_impl(
525    reader: &mut dyn Read,
526    len: usize,
527    max_len: usize,
528) -> Result<Vec<u8>> {
529    let mut output = Vec::new();
530    read_ext_impl::read_exact_vec_limited_into(
531        reader,
532        &mut output,
533        len,
534        max_len,
535    )?;
536    Ok(output)
537}
538
539/// Discards a bounded byte count through a type-erased reader.
540///
541/// # Parameters
542/// - `reader`: Reader whose bytes are discarded.
543/// - `bytes`: Maximum number of bytes to discard.
544///
545/// # Returns
546/// The number of bytes discarded before the limit or EOF was reached.
547///
548/// # Errors
549/// Returns the first non-interrupted read error.
550fn discard_exact_or_eof_impl(reader: &mut dyn Read, bytes: u64) -> Result<u64> {
551    let mut buffer = [0; DISCARD_BUFFER_SIZE];
552    let mut remaining = bytes;
553    let mut discarded = 0;
554    while remaining > 0 {
555        let requested = remaining.min(DISCARD_BUFFER_SIZE as u64) as usize;
556        match reader.read(&mut buffer[..requested]) {
557            Ok(0) => break,
558            Ok(count) => {
559                let count = count as u64;
560                remaining -= count;
561                discarded += count;
562            }
563            Err(error) => {
564                if error.kind() == ErrorKind::Interrupted {
565                    continue;
566                }
567                return Err(error);
568            }
569        }
570    }
571    Ok(discarded)
572}
573
574/// Reads bounded UTF-8 text through a type-erased reader.
575///
576/// # Parameters
577/// - `reader`: Reader that supplies the text bytes.
578/// - `max_len`: Maximum accepted byte length.
579///
580/// # Returns
581/// The decoded UTF-8 string.
582///
583/// # Errors
584/// Returns [`ErrorKind::OutOfMemory`] if the result buffer cannot grow, a read
585/// error, or [`ErrorKind::InvalidData`] when the input exceeds `max_len` or is
586/// not valid UTF-8.
587#[inline]
588fn read_to_string_limited_impl(
589    reader: &mut dyn Read,
590    max_len: usize,
591) -> Result<String> {
592    let bytes = read_ext_impl::read_to_end_limited(reader, max_len)?;
593    String::from_utf8(bytes).map_err(read_ext_impl::invalid_utf8_error)
594}
595
596/// Appends bounded UTF-8 text read through a type-erased reader.
597///
598/// # Parameters
599/// - `reader`: Reader that supplies the text bytes.
600/// - `output`: String that receives the decoded text.
601/// - `max_len`: Maximum accepted byte length.
602///
603/// # Returns
604/// The number of bytes appended to `output`.
605///
606/// # Errors
607/// Returns [`ErrorKind::OutOfMemory`] if the temporary byte buffer or `output`
608/// cannot grow, a read error, or [`ErrorKind::InvalidData`] when the input
609/// exceeds `max_len` or is not valid UTF-8.
610#[inline]
611fn read_to_string_limited_into_impl(
612    reader: &mut dyn Read,
613    output: &mut String,
614    max_len: usize,
615) -> Result<usize> {
616    let bytes = read_ext_impl::read_to_end_limited(reader, max_len)?;
617    let text =
618        String::from_utf8(bytes).map_err(read_ext_impl::invalid_utf8_error)?;
619    let count = text.len();
620    try_reserve_string(output, count).map_err(allocation_error)?;
621    output.push_str(&text);
622    Ok(count)
623}
624
625impl<T> ReadExt for T
626where
627    T: Read + ?Sized,
628{
629    /// Reads bytes from an unchecked range into a standard [`Read`] value.
630    ///
631    /// # Parameters
632    /// - `buffer`: Destination buffer.
633    /// - `start_index`: Start offset inside `buffer`.
634    /// - `count`: Maximum number of bytes to read.
635    ///
636    /// # Returns
637    /// The number of bytes read into the requested range.
638    ///
639    /// # Errors
640    /// Returns the error reported by [`Read::read`].
641    ///
642    /// # Panics
643    /// Panics in debug builds if the requested output range does not fit.
644    ///
645    /// # Safety
646    /// The caller must guarantee that `start_index..start_index + count` is
647    /// valid inside `buffer` and that the addition does not overflow.
648    #[inline(always)]
649    unsafe fn read_unchecked(
650        &mut self,
651        buffer: &mut [u8],
652        start_index: usize,
653        count: usize,
654    ) -> Result<usize> {
655        // SAFETY: The caller guarantees that the requested range is valid for
656        // `buffer`.
657        let target =
658            unsafe { UncheckedSlice::subslice_mut(buffer, start_index, count) };
659        self.read(target)
660    }
661
662    /// Reads an unchecked range until it is full or EOF is reached.
663    ///
664    /// # Parameters
665    /// - `buffer`: Destination buffer.
666    /// - `start_index`: Start offset inside `buffer`.
667    /// - `count`: Number of bytes to try to read.
668    ///
669    /// # Returns
670    /// The number of bytes read into the requested range.
671    ///
672    /// # Errors
673    /// Returns the first non-interrupted read error.
674    ///
675    /// # Panics
676    /// Panics in debug builds if the requested output range does not fit.
677    ///
678    /// # Safety
679    /// The caller must guarantee that `start_index..start_index + count` is
680    /// valid inside `buffer` and that the addition does not overflow.
681    #[inline(always)]
682    unsafe fn read_exact_or_eof_unchecked(
683        &mut self,
684        buffer: &mut [u8],
685        start_index: usize,
686        count: usize,
687    ) -> Result<usize> {
688        let mut reader = self;
689        // SAFETY: Forwarded from the trait caller.
690        unsafe {
691            read_exact_or_eof_unchecked_impl(
692                &mut reader,
693                buffer,
694                start_index,
695                count,
696            )
697        }
698    }
699
700    /// Reads exactly the requested unchecked range.
701    ///
702    /// # Parameters
703    /// - `buffer`: Destination buffer.
704    /// - `start_index`: Start offset inside `buffer`.
705    /// - `count`: Number of bytes to read.
706    ///
707    /// # Returns
708    /// `Ok(())` after the requested range has been filled.
709    ///
710    /// # Errors
711    /// Returns the error reported by [`Read::read_exact`].
712    ///
713    /// # Panics
714    /// Panics in debug builds if the requested output range does not fit.
715    ///
716    /// # Safety
717    /// The caller must guarantee that `start_index..start_index + count` is
718    /// valid inside `buffer` and that the addition does not overflow.
719    #[inline(always)]
720    unsafe fn read_exact_unchecked(
721        &mut self,
722        buffer: &mut [u8],
723        start_index: usize,
724        count: usize,
725    ) -> Result<()> {
726        // SAFETY: The caller guarantees that the requested range is valid for
727        // `buffer`.
728        let target =
729            unsafe { UncheckedSlice::subslice_mut(buffer, start_index, count) };
730        self.read_exact(target)
731    }
732
733    /// Reads the destination until it is full or EOF is reached.
734    ///
735    /// # Parameters
736    /// - `buffer`: Destination buffer.
737    ///
738    /// # Returns
739    /// The number of bytes read into `buffer`.
740    ///
741    /// # Errors
742    /// Returns the first non-interrupted read error.
743    #[inline(always)]
744    fn read_exact_or_eof(&mut self, buffer: &mut [u8]) -> Result<usize> {
745        let mut reader = self;
746        read_ext_impl::read_exact_or_eof(&mut reader, buffer)
747    }
748
749    /// Reads exactly `N` bytes into an array.
750    ///
751    /// # Type Parameters
752    /// - `N`: Number of bytes in the returned array.
753    ///
754    /// # Returns
755    /// An array containing exactly `N` bytes.
756    ///
757    /// # Errors
758    /// Returns the error reported by [`Read::read_exact`].
759    #[inline(always)]
760    fn read_exact_array<const N: usize>(&mut self) -> Result<[u8; N]> {
761        let mut reader = self;
762        read_exact_array_impl(&mut reader)
763    }
764
765    /// Reads an exactly sized vector within a configured limit.
766    ///
767    /// # Parameters
768    /// - `len`: Exact number of bytes to read.
769    /// - `max_len`: Maximum accepted exact read length.
770    ///
771    /// # Returns
772    /// A vector containing exactly `len` bytes.
773    ///
774    /// # Errors
775    /// Returns [`ErrorKind::OutOfMemory`] if the result vector cannot be
776    /// allocated, a read error, or [`ErrorKind::InvalidData`] when
777    /// `len > max_len`.
778    #[inline(always)]
779    fn read_exact_vec_limited(
780        &mut self,
781        len: usize,
782        max_len: usize,
783    ) -> Result<Vec<u8>> {
784        let mut reader = self;
785        read_exact_vec_limited_impl(&mut reader, len, max_len)
786    }
787
788    /// Reads exactly `len` bytes and appends them to a vector.
789    ///
790    /// # Parameters
791    /// - `output`: Destination vector.
792    /// - `len`: Exact number of bytes to read.
793    /// - `max_len`: Maximum accepted exact read length.
794    ///
795    /// # Returns
796    /// `Ok(())` after exactly `len` bytes have been appended.
797    ///
798    /// # Errors
799    /// Returns [`ErrorKind::OutOfMemory`] if `output` cannot grow, a read
800    /// error, [`ErrorKind::InvalidData`] when `len > max_len`, or
801    /// [`ErrorKind::InvalidInput`] when `output.len() + len` overflows.
802    #[inline(always)]
803    fn read_exact_vec_limited_into(
804        &mut self,
805        output: &mut Vec<u8>,
806        len: usize,
807        max_len: usize,
808    ) -> Result<()> {
809        let mut reader = self;
810        read_ext_impl::read_exact_vec_limited_into(
811            &mut reader,
812            output,
813            len,
814            max_len,
815        )
816    }
817
818    /// Discards at most the requested number of bytes.
819    ///
820    /// # Parameters
821    /// - `bytes`: Maximum number of bytes to discard.
822    ///
823    /// # Returns
824    /// The number of bytes discarded before the limit or EOF was reached.
825    ///
826    /// # Errors
827    /// Returns the first non-interrupted read error.
828    #[inline(always)]
829    fn discard_exact_or_eof(&mut self, bytes: u64) -> Result<u64> {
830        let mut reader = self;
831        discard_exact_or_eof_impl(&mut reader, bytes)
832    }
833
834    /// Copies all remaining bytes to a writer.
835    ///
836    /// # Parameters
837    /// - `writer`: Destination writer.
838    ///
839    /// # Returns
840    /// The number of bytes copied.
841    ///
842    /// # Errors
843    /// Returns the first read or write error.
844    #[inline(always)]
845    fn copy_to(&mut self, writer: &mut dyn Write) -> Result<u64> {
846        copy_all(self, writer)
847    }
848
849    /// Copies at most the requested number of bytes to a writer.
850    ///
851    /// # Parameters
852    /// - `writer`: Destination writer.
853    /// - `max_bytes`: Maximum number of bytes to copy.
854    ///
855    /// # Returns
856    /// The number of bytes copied.
857    ///
858    /// # Errors
859    /// Returns [`ErrorKind::OutOfMemory`] if the temporary copy buffer cannot
860    /// be allocated, or the first non-interrupted read error or write error.
861    #[inline(always)]
862    fn copy_to_at_most(
863        &mut self,
864        writer: &mut dyn Write,
865        max_bytes: u64,
866    ) -> Result<u64> {
867        let mut reader = self;
868        Streams::copy_at_most(&mut reader, writer, max_bytes)
869    }
870
871    /// Copies the remaining input when it fits within a configured limit.
872    ///
873    /// # Parameters
874    /// - `writer`: Destination writer.
875    /// - `max_bytes`: Maximum accepted remaining byte count.
876    ///
877    /// # Returns
878    /// The number of bytes copied.
879    ///
880    /// # Errors
881    /// Returns [`ErrorKind::OutOfMemory`] if the temporary copy buffer cannot
882    /// be allocated, a read or write error, or [`ErrorKind::InvalidData`] when
883    /// the remaining input exceeds `max_bytes`.
884    #[inline(always)]
885    fn copy_to_end_limited(
886        &mut self,
887        writer: &mut dyn Write,
888        max_bytes: u64,
889    ) -> Result<u64> {
890        let mut reader = self;
891        Streams::copy_to_end_limited(&mut reader, writer, max_bytes)
892    }
893
894    /// Reads the remaining bytes into a bounded vector.
895    ///
896    /// # Parameters
897    /// - `max_len`: Maximum accepted remaining byte count.
898    ///
899    /// # Returns
900    /// A vector containing all remaining bytes.
901    ///
902    /// # Errors
903    /// Returns [`ErrorKind::OutOfMemory`] if the result vector cannot grow, a
904    /// read error, or [`ErrorKind::InvalidData`] when the remaining input
905    /// exceeds `max_len`.
906    #[inline(always)]
907    fn read_to_end_limited(&mut self, max_len: usize) -> Result<Vec<u8>> {
908        let mut reader = self;
909        read_ext_impl::read_to_end_limited(&mut reader, max_len)
910    }
911
912    /// Appends the remaining bytes to a bounded vector.
913    ///
914    /// # Parameters
915    /// - `output`: Destination vector.
916    /// - `max_len`: Maximum accepted remaining byte count.
917    ///
918    /// # Returns
919    /// The number of bytes appended to `output`.
920    ///
921    /// # Errors
922    /// Returns [`ErrorKind::OutOfMemory`] if `output` cannot grow, a read
923    /// error, or [`ErrorKind::InvalidData`] when the remaining input
924    /// exceeds `max_len`.
925    #[inline(always)]
926    fn read_to_end_limited_into(
927        &mut self,
928        output: &mut Vec<u8>,
929        max_len: usize,
930    ) -> Result<usize> {
931        let mut reader = self;
932        read_ext_impl::read_to_end_limited_into(&mut reader, output, max_len)
933    }
934
935    /// Reads the remaining bytes as bounded UTF-8 text.
936    ///
937    /// # Parameters
938    /// - `max_len`: Maximum accepted remaining byte count.
939    ///
940    /// # Returns
941    /// The decoded UTF-8 string.
942    ///
943    /// # Errors
944    /// Returns [`ErrorKind::OutOfMemory`] if the result buffer cannot grow, a
945    /// read error, or [`ErrorKind::InvalidData`] when the input exceeds
946    /// `max_len` or is not valid UTF-8.
947    #[inline(always)]
948    fn read_to_string_limited(&mut self, max_len: usize) -> Result<String> {
949        let mut reader = self;
950        read_to_string_limited_impl(&mut reader, max_len)
951    }
952
953    /// Appends the remaining bounded UTF-8 text to a string.
954    ///
955    /// # Parameters
956    /// - `output`: Destination string.
957    /// - `max_len`: Maximum accepted remaining byte count.
958    ///
959    /// # Returns
960    /// The number of bytes appended to `output`.
961    ///
962    /// # Errors
963    /// Returns [`ErrorKind::OutOfMemory`] if the temporary byte buffer or
964    /// `output` cannot grow, a read error, or [`ErrorKind::InvalidData`] when
965    /// the input exceeds `max_len` or is not valid UTF-8.
966    #[inline(always)]
967    fn read_to_string_limited_into(
968        &mut self,
969        output: &mut String,
970        max_len: usize,
971    ) -> Result<usize> {
972        let mut reader = self;
973        read_to_string_limited_into_impl(&mut reader, output, max_len)
974    }
975}