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