Skip to main content

qubit_io/traits/
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
9use std::io::Error;
10use std::io::ErrorKind;
11use std::io::Result;
12
13use super::validate_read_count;
14use crate::ByteInput;
15use crate::StdRead;
16use crate::util::SliceRange;
17
18/// Minimal indexed input interface over items.
19///
20/// `Input` is intentionally smaller and lower-level than [`std::io::Read`]. It
21/// only states that an implementor can read up to `count` items into
22/// `output[index..index + count]`. The caller owns range validation so hot
23/// paths can avoid repeated slicing and bounds checks.
24///
25/// # Coherence note
26///
27/// Every [`std::io::Read`] value automatically implements `Input<Item = u8>`
28/// through the standard I/O integration. Because [`Input::Item`] is an
29/// associated type rather than a trait parameter, a concrete type that
30/// implements [`std::io::Read`] cannot also provide any other direct `Input`
31/// implementation for the same type, including one with a different item type.
32///
33/// Use a wrapper/newtype when a type needs item-oriented input semantics that
34/// differ from its byte-oriented [`std::io::Read`] implementation.
35///
36/// # Examples
37///
38/// Standard readers implement `Input<Item = u8>` automatically, so callers
39/// can use the trait methods directly on them:
40///
41/// ```
42/// use std::io::Cursor;
43///
44/// use qubit_io::Input;
45///
46/// let mut input = Cursor::new(b"data");
47/// let mut output = [0; 4];
48/// assert_eq!(Input::read(&mut input, &mut output).unwrap(), 4);
49/// assert_eq!(&output, b"data");
50/// ```
51pub trait Input {
52    /// The item type read from this input.
53    type Item;
54
55    /// Converts this byte input into a standard library reader.
56    ///
57    /// The conversion only wraps `self`; it performs no I/O and does not
58    /// allocate. The wrapped input can be recovered with
59    /// [`StdRead::into_inner`].
60    ///
61    /// # Examples
62    ///
63    /// ```
64    /// use qubit_io::Input;
65    /// use std::io::Read;
66    ///
67    /// let input = std::io::Cursor::new(b"hello");
68    /// let mut reader = input.into_std_read();
69    /// let mut bytes = Vec::new();
70    /// reader.read_to_end(&mut bytes).unwrap();
71    /// assert_eq!(bytes, b"hello");
72    /// let input = reader.into_inner();
73    /// assert_eq!(input.position(), 5);
74    /// ```
75    ///
76    /// Non-byte inputs cannot be converted:
77    ///
78    /// ```compile_fail
79    /// use qubit_io::Input;
80    ///
81    /// fn convert<I: Input<Item = char>>(input: I) {
82    ///     let _reader = input.into_std_read();
83    /// }
84    /// ```
85    #[must_use = "the returned reader is the converted input"]
86    #[inline]
87    fn into_std_read(self) -> StdRead<Self>
88    where
89        Self: Sized + ByteInput,
90    {
91        StdRead::new(self)
92    }
93
94    /// Returns whether this input already buffers items internally.
95    ///
96    /// # Returns
97    ///
98    /// `true` when callers should avoid wrapping this input in another generic
99    /// item buffer automatically.
100    #[inline(always)]
101    #[must_use]
102    fn is_buffered(&self) -> bool {
103        false
104    }
105
106    /// Reads items into an indexed output range without checking the range.
107    ///
108    /// # Parameters
109    ///
110    /// * `output` - Destination storage.
111    /// * `index` - Start index inside `output`.
112    /// * `count` - Maximum number of items to read.
113    ///
114    /// # Returns
115    ///
116    /// The number of items written into `output[index..index + count]`. The
117    /// value must be in `0..=count`. A successful call transfers a prefix of
118    /// the requested range and may be short. For a non-empty request, `Ok(0)`
119    /// means that no items were available in this call or that the stream
120    /// reached its end; it does not promise permanent EOF. Aggregate reads
121    /// stop on this zero progress: [`Input::read_fully`] returns the
122    /// accumulated count, while [`Input::read_exactly`] reports
123    /// [`ErrorKind::UnexpectedEof`] if the destination is not full. For a
124    /// zero-length request, a successful call returns zero, which does not
125    /// establish EOF. Empty requests are not guaranteed to suppress
126    /// implementation errors or avoid an inner call.
127    ///
128    /// # Errors
129    ///
130    /// Returns the input error reported by the implementation. An
131    /// [`ErrorKind::Interrupted`] result is retried by aggregate read methods
132    /// and therefore means this call made no confirmed transfer. If a valid
133    /// prefix was transferred, return `Ok(n)` for it and report a later error
134    /// on a subsequent call. A later aggregate error does not undo successful
135    /// earlier calls. Errors with applied or uncertain side effects must not
136    /// be represented as retryable `Interrupted` solely to request a retry;
137    /// the adapter or caller must choose a policy for those effects.
138    ///
139    /// # Safety
140    ///
141    /// The caller must guarantee that `index..index + count` is a valid range
142    /// inside `output` and that the addition does not overflow.
143    unsafe fn read_unchecked(&mut self, output: &mut [Self::Item], index: usize, count: usize) -> Result<usize>;
144
145    /// Reads items into the full output slice.
146    ///
147    /// # Parameters
148    /// - `output`: Destination storage.
149    ///
150    /// # Returns
151    /// The number of items read into `output`. A successful call transfers a
152    /// prefix and may be short. For a non-empty request, `Ok(0)` means that no
153    /// items were available in this call or that the stream reached its end;
154    /// it does not promise permanent EOF. Aggregate reads stop on this zero
155    /// progress: [`Input::read_fully`] returns the accumulated count, while
156    /// [`Input::read_exactly`] reports [`ErrorKind::UnexpectedEof`] if the
157    /// destination is not full. For a zero-length request, a successful call
158    /// returns zero, which does not establish EOF. Empty requests are not
159    /// guaranteed to suppress implementation errors or avoid an inner call.
160    ///
161    /// # Errors
162    ///
163    /// Returns the input error reported by the implementation. Returns
164    /// [`ErrorKind::InvalidData`] if the implementation reports reading more
165    /// items than requested.
166    #[inline(always)]
167    fn read(&mut self, output: &mut [Self::Item]) -> Result<usize> {
168        // SAFETY: The caller ensured the destination slice is valid.
169        let read = unsafe { self.read_unchecked(output, 0, output.len()) }?;
170        validate_read_count(read, output.len())?;
171        Ok(read)
172    }
173
174    /// Reads items into an indexed output range until it is full or EOF is
175    /// reached.
176    ///
177    /// This method retries interrupted reads and treats EOF as a successful
178    /// partial result.
179    ///
180    /// # Parameters
181    ///
182    /// * `output` - Destination storage.
183    /// * `index` - Start index inside `output`.
184    /// * `count` - Maximum number of items to read.
185    ///
186    /// # Returns
187    ///
188    /// The number of items written into `output[index..index + count]`.
189    ///
190    /// # Errors
191    ///
192    /// Returns the first non-[`ErrorKind::Interrupted`] input error. Returns
193    /// [`ErrorKind::InvalidData`] if the implementation reports more items than
194    /// requested.
195    ///
196    /// # Panics
197    ///
198    /// Panics in debug builds if the requested output range does not fit.
199    ///
200    /// # Safety
201    ///
202    /// The caller must guarantee that `index..index + count` is a valid range
203    /// inside `output` and that the addition does not overflow.
204    unsafe fn read_fully_unchecked(&mut self, output: &mut [Self::Item], index: usize, count: usize) -> Result<usize> {
205        debug_assert!(
206            SliceRange::range_fits(output.len(), index, count),
207            "unchecked read-fully range exceeds output buffer"
208        );
209        let mut total = 0;
210        while total < count {
211            let remaining = count - total;
212            // SAFETY: The caller guarantees the original destination range is
213            // valid; `total < count`, so this suffix remains inside it.
214            match unsafe { self.read_unchecked(output, index + total, remaining) } {
215                Ok(0) => break,
216                Ok(read) => {
217                    validate_read_count(read, remaining)?;
218                    total += read;
219                }
220                Err(error) if error.kind() == ErrorKind::Interrupted => {}
221                Err(error) => return Err(error),
222            }
223        }
224        Ok(total)
225    }
226
227    /// Reads items into the full output slice until it is full or EOF is
228    /// reached.
229    ///
230    /// # Parameters
231    /// - `output`: Destination storage to fill as far as possible.
232    ///
233    /// # Returns
234    /// The number of items written into `output`.
235    ///
236    /// # Errors
237    /// Returns the first non-interrupted input error, or
238    /// [`ErrorKind::InvalidData`] if the implementation reports an impossible
239    /// item count.
240    #[inline(always)]
241    fn read_fully(&mut self, output: &mut [Self::Item]) -> Result<usize> {
242        // SAFETY: The full output slice is a valid destination range.
243        unsafe { self.read_fully_unchecked(output, 0, output.len()) }
244    }
245
246    /// Reads items until the full output slice is filled.
247    ///
248    /// # Parameters
249    ///
250    /// * `output` - Destination storage that must be filled completely.
251    ///
252    /// # Returns
253    ///
254    /// `Ok(())` after the destination has been filled completely.
255    ///
256    /// # Errors
257    ///
258    /// Returns [`ErrorKind::UnexpectedEof`] if the input ends before filling
259    /// `output`. Returns the first non-interrupted input error, or
260    /// [`ErrorKind::InvalidData`] if the implementation reports an impossible
261    /// item count.
262    #[inline]
263    fn read_exactly(&mut self, output: &mut [Self::Item]) -> Result<()> {
264        if self.read_fully(output)? == output.len() {
265            Ok(())
266        } else {
267            Err(Error::new(
268                ErrorKind::UnexpectedEof,
269                "failed to fill whole input buffer",
270            ))
271        }
272    }
273
274    /// Reads items into multiple buffers in list order.
275    ///
276    /// The buffers form one logical sequence in list order. `Ok(n)` means that
277    /// the first `n` items of that sequence were read, and `n` must not exceed
278    /// the total requested length. A read may make short progress and need not
279    /// fill every buffer; `n` may cross a buffer boundary. For a non-empty
280    /// request, `Ok(0)` means that no data was available in this call or that
281    /// the stream reached its end; it does not promise permanent EOF.
282    ///
283    /// The default implementation skips empty buffers and calls [`Input::read`]
284    /// once on the first non-empty buffer. It does not continue to later
285    /// buffers after a short read. This is only the default strategy, not a
286    /// limit on overrides. Empty lists and lists whose buffers are all empty
287    /// return `Ok(0)` without performing I/O. Interrupted errors are not
288    /// retried. An error does not undo progress from earlier independent calls.
289    /// An override must uphold the sequence and count contract itself; this
290    /// trait does not validate counts returned by arbitrary overrides. Use
291    /// UFCS when a standard I/O method with the same name is also in scope.
292    ///
293    /// # Parameters
294    ///
295    /// - `buffers`: Mutable destination slices, in the order to read them.
296    ///
297    /// # Returns
298    ///
299    /// The number of items read from the start of the logical sequence.
300    ///
301    /// # Errors
302    ///
303    /// Returns an error from the input operation. The default implementation
304    /// returns [`ErrorKind::InvalidData`] if the selected buffer reports more
305    /// items than it can hold. The standard I/O blanket implementation also
306    /// returns [`ErrorKind::InvalidInput`] if the total length overflows,
307    /// [`ErrorKind::OutOfMemory`] if preparing descriptors fails, or
308    /// [`ErrorKind::InvalidData`] if the standard reader reports more than the
309    /// total capacity. A custom override is responsible for its own checks.
310    ///
311    /// # Examples
312    ///
313    /// This example uses a non-byte stream through a trait object. The default
314    /// method reads only the first non-empty slice; an override may use more.
315    /// For vectored overrides, a count can cross a slice boundary: if two
316    /// destination slices each have length 2, `Ok(3)` means the first slice
317    /// and the first item of the second slice were filled.
318    ///
319    /// ```
320    /// use qubit_io::Input;
321    ///
322    /// struct Characters;
323    /// impl Input for Characters {
324    ///     type Item = char;
325    ///     unsafe fn read_unchecked(
326    ///         &mut self,
327    ///         output: &mut [char],
328    ///         index: usize,
329    ///         count: usize,
330    ///     ) -> std::io::Result<usize> {
331    ///         if count == 0 {
332    ///             return Ok(0);
333    ///         }
334    ///         output[index] = '甲';
335    ///         Ok(1)
336    ///     }
337    /// }
338    /// let mut input = Characters;
339    /// let input: &mut dyn Input<Item = char> = &mut input;
340    /// let mut first = ['!'; 2];
341    /// let mut second = ['?'; 2];
342    /// assert_eq!(Input::read_vectored(input, &mut [&mut first, &mut second])?, 1);
343    /// assert_eq!(first, ['甲', '!']);
344    /// assert_eq!(second, ['?', '?']);
345    /// # Ok::<(), std::io::Error>(())
346    /// ```
347    fn read_vectored(&mut self, buffers: &mut [&mut [Self::Item]]) -> Result<usize> {
348        let Some(buffer) = buffers.iter_mut().find(|buffer| !buffer.is_empty()) else {
349            return Ok(0);
350        };
351        let count = self.read(buffer)?;
352        validate_read_count(count, buffer.len())?;
353        Ok(count)
354    }
355}