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