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}