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}