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}