Skip to main content

qubit_io/std_io/impls/
input.rs

1// =============================================================================
2//    Copyright (c) 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8
9//! Standard [`Read`](std::io::Read) implementations of item input traits.
10
11use std::io::Read;
12use std::io::Result;
13
14use crate::Input;
15use crate::traits::validate_read_count;
16use crate::util::UncheckedSlice;
17use crate::util::io_slices_mut;
18use crate::util::requested_items;
19
20/// Bridges byte-oriented standard readers to item-oriented input.
21impl<R> Input for R
22where
23    R: Read + ?Sized,
24{
25    /// Bytes read by the standard Read implementation.
26    type Item = u8;
27
28    /// Reads bytes into a caller-validated indexed output range.
29    ///
30    /// # Parameters
31    ///
32    /// - `output`: Destination byte slice.
33    /// - `index`: Start offset inside `output`.
34    /// - `count`: Maximum number of bytes to read.
35    ///
36    /// # Returns
37    ///
38    /// The number of bytes reported by the standard reader.
39    ///
40    /// A successful call may read fewer than `count` bytes. A return value of
41    /// zero indicates that no bytes were read; for a nonempty request this
42    /// normally signals end of input. This method does not retry short reads.
43    ///
44    /// # Errors
45    ///
46    /// Returns the error reported by the standard reader.
47    ///
48    /// # Panics
49    ///
50    /// Panics in debug builds if the requested destination range does not fit.
51    ///
52    /// # Safety
53    ///
54    /// The caller must ensure that index through index plus count is a valid
55    /// range inside output without overflowing.
56    #[inline(always)]
57    unsafe fn read_unchecked(&mut self, output: &mut [u8], index: usize, count: usize) -> Result<usize> {
58        // SAFETY: The caller guarantees that the range is valid inside output.
59        let target = unsafe { UncheckedSlice::subslice_mut(output, index, count) };
60        Read::read(self, target)
61    }
62
63    /// Reads bytes into the complete output slice.
64    ///
65    /// # Parameters
66    ///
67    /// - `output`: Destination byte slice.
68    ///
69    /// # Returns
70    ///
71    /// The number of bytes read into `output`.
72    ///
73    /// A successful call may fill only part of `output`; zero means no bytes
74    /// were read and normally signals end of input for a nonempty buffer. This
75    /// method does not retry short reads.
76    ///
77    /// # Errors
78    ///
79    /// Returns [`std::io::ErrorKind::InvalidData`] if the reader reports more
80    /// bytes than `output` holds, or the error reported by the standard reader.
81    #[inline(always)]
82    fn read(&mut self, output: &mut [Self::Item]) -> Result<usize> {
83        let read = Read::read(self, output)?;
84        validate_read_count(read, output.len())?;
85        Ok(read)
86    }
87
88    /// Reads from the buffers in order using the standard reader's vectored
89    /// method. A single descriptor uses stack storage; multiple descriptors
90    /// may allocate descriptor storage, and the reader may allocate
91    /// independently. Short progress and reader errors are returned without
92    /// retrying or undoing underlying side effects.
93    ///
94    /// # Parameters
95    ///
96    /// - `buffers`: Mutable byte buffers to fill in order.
97    ///
98    /// # Returns
99    ///
100    /// The number of bytes reported by the standard reader, up to the total
101    /// capacity of `buffers`.
102    ///
103    /// # Errors
104    ///
105    /// Returns [`std::io::ErrorKind::InvalidInput`] if the total buffer length
106    /// overflows, [`std::io::ErrorKind::OutOfMemory`] if multiple-descriptor
107    /// preparation fails before I/O, [`std::io::ErrorKind::InvalidData`] if
108    /// the reader reports more than the total capacity, or the error reported
109    /// by the standard reader.
110    fn read_vectored(&mut self, buffers: &mut [&mut [u8]]) -> Result<usize> {
111        let capacity = requested_items(buffers.iter().map(|buffer| buffer.len()))?;
112        if capacity == 0 {
113            return Ok(0);
114        }
115        let count = if let [buffer] = buffers {
116            let mut slices = [std::io::IoSliceMut::new(buffer)];
117            Read::read_vectored(self, &mut slices)?
118        } else {
119            let mut slices = io_slices_mut(buffers)?;
120            Read::read_vectored(self, &mut slices)?
121        };
122        validate_read_count(count, capacity)?;
123        Ok(count)
124    }
125}