Skip to main content

qubit_io/ext/
binary_read_ext.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10
11use std::io::{
12    Read,
13    Result,
14};
15
16use crate::codec::{
17    BigEndian,
18    BinaryCodec,
19    ByteOrder,
20    LittleEndian,
21};
22
23macro_rules! read_binary_value {
24    ($reader:expr, $ty:ty, $order:ty) => {
25        read_binary::<{ BinaryCodec::<$ty, $order>::REQUIRED_MIN_BUFFER_LEN }, _, _, _>($reader, |bytes| {
26            // SAFETY: The local buffer is exactly the codec's minimum buffer length.
27            unsafe { BinaryCodec::<$ty, $order>::read_unchecked(bytes, 0) }
28        })
29    };
30}
31
32/// Extension methods for reading fixed-width binary values from byte streams.
33pub trait BinaryReadExt: Read {
34    /// Reads an unsigned 8-bit integer.
35    #[inline]
36    fn read_u8(&mut self) -> Result<u8> {
37        read_binary_value!(self, u8, BigEndian)
38    }
39
40    /// Reads a signed 8-bit integer.
41    #[inline]
42    fn read_i8(&mut self) -> Result<i8> {
43        read_binary_value!(self, i8, BigEndian)
44    }
45
46    /// Reads an unsigned 16-bit integer using a runtime byte order.
47    #[inline]
48    fn read_u16(&mut self, byte_order: ByteOrder) -> Result<u16> {
49        match byte_order {
50            ByteOrder::BigEndian => self.read_u16_be(),
51            ByteOrder::LittleEndian => self.read_u16_le(),
52        }
53    }
54
55    /// Reads a big-endian unsigned 16-bit integer.
56    #[inline]
57    fn read_u16_be(&mut self) -> Result<u16> {
58        read_binary_value!(self, u16, BigEndian)
59    }
60
61    /// Reads a little-endian unsigned 16-bit integer.
62    #[inline]
63    fn read_u16_le(&mut self) -> Result<u16> {
64        read_binary_value!(self, u16, LittleEndian)
65    }
66
67    /// Reads an unsigned 32-bit integer using a runtime byte order.
68    #[inline]
69    fn read_u32(&mut self, byte_order: ByteOrder) -> Result<u32> {
70        match byte_order {
71            ByteOrder::BigEndian => self.read_u32_be(),
72            ByteOrder::LittleEndian => self.read_u32_le(),
73        }
74    }
75
76    /// Reads a big-endian unsigned 32-bit integer.
77    #[inline]
78    fn read_u32_be(&mut self) -> Result<u32> {
79        read_binary_value!(self, u32, BigEndian)
80    }
81
82    /// Reads a little-endian unsigned 32-bit integer.
83    #[inline]
84    fn read_u32_le(&mut self) -> Result<u32> {
85        read_binary_value!(self, u32, LittleEndian)
86    }
87
88    /// Reads an unsigned 64-bit integer using a runtime byte order.
89    #[inline]
90    fn read_u64(&mut self, byte_order: ByteOrder) -> Result<u64> {
91        match byte_order {
92            ByteOrder::BigEndian => self.read_u64_be(),
93            ByteOrder::LittleEndian => self.read_u64_le(),
94        }
95    }
96
97    /// Reads a big-endian unsigned 64-bit integer.
98    #[inline]
99    fn read_u64_be(&mut self) -> Result<u64> {
100        read_binary_value!(self, u64, BigEndian)
101    }
102
103    /// Reads a little-endian unsigned 64-bit integer.
104    #[inline]
105    fn read_u64_le(&mut self) -> Result<u64> {
106        read_binary_value!(self, u64, LittleEndian)
107    }
108
109    /// Reads an unsigned 128-bit integer using a runtime byte order.
110    #[inline]
111    fn read_u128(&mut self, byte_order: ByteOrder) -> Result<u128> {
112        match byte_order {
113            ByteOrder::BigEndian => self.read_u128_be(),
114            ByteOrder::LittleEndian => self.read_u128_le(),
115        }
116    }
117
118    /// Reads a big-endian unsigned 128-bit integer.
119    #[inline]
120    fn read_u128_be(&mut self) -> Result<u128> {
121        read_binary_value!(self, u128, BigEndian)
122    }
123
124    /// Reads a little-endian unsigned 128-bit integer.
125    #[inline]
126    fn read_u128_le(&mut self) -> Result<u128> {
127        read_binary_value!(self, u128, LittleEndian)
128    }
129
130    /// Reads a signed 16-bit integer using a runtime byte order.
131    #[inline]
132    fn read_i16(&mut self, byte_order: ByteOrder) -> Result<i16> {
133        match byte_order {
134            ByteOrder::BigEndian => self.read_i16_be(),
135            ByteOrder::LittleEndian => self.read_i16_le(),
136        }
137    }
138
139    /// Reads a big-endian signed 16-bit integer.
140    #[inline]
141    fn read_i16_be(&mut self) -> Result<i16> {
142        read_binary_value!(self, i16, BigEndian)
143    }
144
145    /// Reads a little-endian signed 16-bit integer.
146    #[inline]
147    fn read_i16_le(&mut self) -> Result<i16> {
148        read_binary_value!(self, i16, LittleEndian)
149    }
150
151    /// Reads a signed 32-bit integer using a runtime byte order.
152    #[inline]
153    fn read_i32(&mut self, byte_order: ByteOrder) -> Result<i32> {
154        match byte_order {
155            ByteOrder::BigEndian => self.read_i32_be(),
156            ByteOrder::LittleEndian => self.read_i32_le(),
157        }
158    }
159
160    /// Reads a big-endian signed 32-bit integer.
161    #[inline]
162    fn read_i32_be(&mut self) -> Result<i32> {
163        read_binary_value!(self, i32, BigEndian)
164    }
165
166    /// Reads a little-endian signed 32-bit integer.
167    #[inline]
168    fn read_i32_le(&mut self) -> Result<i32> {
169        read_binary_value!(self, i32, LittleEndian)
170    }
171
172    /// Reads a signed 64-bit integer using a runtime byte order.
173    #[inline]
174    fn read_i64(&mut self, byte_order: ByteOrder) -> Result<i64> {
175        match byte_order {
176            ByteOrder::BigEndian => self.read_i64_be(),
177            ByteOrder::LittleEndian => self.read_i64_le(),
178        }
179    }
180
181    /// Reads a big-endian signed 64-bit integer.
182    #[inline]
183    fn read_i64_be(&mut self) -> Result<i64> {
184        read_binary_value!(self, i64, BigEndian)
185    }
186
187    /// Reads a little-endian signed 64-bit integer.
188    #[inline]
189    fn read_i64_le(&mut self) -> Result<i64> {
190        read_binary_value!(self, i64, LittleEndian)
191    }
192
193    /// Reads a signed 128-bit integer using a runtime byte order.
194    #[inline]
195    fn read_i128(&mut self, byte_order: ByteOrder) -> Result<i128> {
196        match byte_order {
197            ByteOrder::BigEndian => self.read_i128_be(),
198            ByteOrder::LittleEndian => self.read_i128_le(),
199        }
200    }
201
202    /// Reads a big-endian signed 128-bit integer.
203    #[inline]
204    fn read_i128_be(&mut self) -> Result<i128> {
205        read_binary_value!(self, i128, BigEndian)
206    }
207
208    /// Reads a little-endian signed 128-bit integer.
209    #[inline]
210    fn read_i128_le(&mut self) -> Result<i128> {
211        read_binary_value!(self, i128, LittleEndian)
212    }
213
214    /// Reads a 32-bit float using a runtime byte order.
215    #[inline]
216    fn read_f32(&mut self, byte_order: ByteOrder) -> Result<f32> {
217        match byte_order {
218            ByteOrder::BigEndian => self.read_f32_be(),
219            ByteOrder::LittleEndian => self.read_f32_le(),
220        }
221    }
222
223    /// Reads a big-endian 32-bit float.
224    #[inline]
225    fn read_f32_be(&mut self) -> Result<f32> {
226        read_binary_value!(self, f32, BigEndian)
227    }
228
229    /// Reads a little-endian 32-bit float.
230    #[inline]
231    fn read_f32_le(&mut self) -> Result<f32> {
232        read_binary_value!(self, f32, LittleEndian)
233    }
234
235    /// Reads a 64-bit float using a runtime byte order.
236    #[inline]
237    fn read_f64(&mut self, byte_order: ByteOrder) -> Result<f64> {
238        match byte_order {
239            ByteOrder::BigEndian => self.read_f64_be(),
240            ByteOrder::LittleEndian => self.read_f64_le(),
241        }
242    }
243
244    /// Reads a big-endian 64-bit float.
245    #[inline]
246    fn read_f64_be(&mut self) -> Result<f64> {
247        read_binary_value!(self, f64, BigEndian)
248    }
249
250    /// Reads a little-endian 64-bit float.
251    #[inline]
252    fn read_f64_le(&mut self) -> Result<f64> {
253        read_binary_value!(self, f64, LittleEndian)
254    }
255}
256
257impl<R> BinaryReadExt for R where R: Read + ?Sized {}
258
259#[inline]
260fn read_binary<const N: usize, T, R, F>(reader: &mut R, decode: F) -> Result<T>
261where
262    R: Read + ?Sized,
263    F: FnOnce(&[u8]) -> T,
264{
265    let mut bytes = [0u8; N];
266    reader.read_exact(&mut bytes)?;
267    Ok(decode(&bytes))
268}