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::{
10    Read,
11    Result,
12};
13
14/// Minimal indexed input interface over units.
15///
16/// `Input` is intentionally smaller and lower-level than [`Read`]. It only
17/// states that an implementor can read up to `count` units into
18/// `output[index..index + count]`. The caller owns range validation so hot
19/// paths can avoid repeated slicing and bounds checks.
20pub trait Input {
21    /// The unit type read from this input.
22    type Item;
23
24    /// Reads units into an indexed output range without checking the range.
25    ///
26    /// # Parameters
27    ///
28    /// * `output` - Destination storage.
29    /// * `index` - Start index inside `output`.
30    /// * `count` - Maximum number of units to read.
31    ///
32    /// # Returns
33    ///
34    /// The number of units written into `output[index..index + count]`. The
35    /// value must be in `0..=count`.
36    ///
37    /// # Errors
38    ///
39    /// Returns the input error reported by the implementation.
40    ///
41    /// # Safety
42    ///
43    /// The caller must guarantee that `index..index + count` is a valid range
44    /// inside `output` and that the addition does not overflow.
45    unsafe fn read_unchecked(
46        &mut self,
47        output: &mut [Self::Item],
48        index: usize,
49        count: usize,
50    ) -> Result<usize>;
51}
52
53impl<R> Input for R
54where
55    R: Read + ?Sized,
56{
57    type Item = u8;
58
59    /// Reads bytes from a standard [`Read`] value into an indexed range.
60    #[inline(always)]
61    unsafe fn read_unchecked(
62        &mut self,
63        output: &mut [u8],
64        index: usize,
65        count: usize,
66    ) -> Result<usize> {
67        debug_assert!(
68            index
69                .checked_add(count)
70                .is_some_and(|end| end <= output.len()),
71            "unchecked read range exceeds output buffer"
72        );
73        // SAFETY: The caller guarantees that the range is valid inside
74        // `output`.
75        let target = unsafe {
76            core::slice::from_raw_parts_mut(
77                output.as_mut_ptr().add(index),
78                count,
79            )
80        };
81        self.read(target)
82    }
83}