qubit_io/codecs/binary_reader.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 ******************************************************************************/
10use std::io::{
11 BufRead,
12 Read,
13 Result,
14 Seek,
15 SeekFrom,
16};
17
18use crate::{
19 BinaryReadExt,
20 ByteOrder,
21 StringReadExt,
22};
23
24/// Reader wrapper for binary scalar and length-prefixed string decoding.
25///
26/// Multi-byte methods use the configured [`ByteOrder`].
27///
28/// # Examples
29/// ```
30/// use std::io::Cursor;
31///
32/// use qubit_io::{
33/// BinaryReader,
34/// BinaryWriter,
35/// ByteOrder,
36/// };
37///
38/// let mut output = BinaryWriter::new(Vec::new(), ByteOrder::BigEndian);
39/// output.write_u16(0x1234)?;
40///
41/// let mut input = BinaryReader::new(Cursor::new(output.into_inner()), ByteOrder::BigEndian);
42/// assert_eq!(0x1234, input.read_u16()?);
43/// # Ok::<(), std::io::Error>(())
44/// ```
45pub struct BinaryReader<R> {
46 inner: R,
47 byte_order: ByteOrder,
48}
49
50impl<R> BinaryReader<R> {
51 /// Creates a binary reader.
52 ///
53 /// # Parameters
54 /// - `inner`: Reader to wrap.
55 /// - `byte_order`: Byte order used by multi-byte reads.
56 ///
57 /// # Returns
58 /// A new binary reader.
59 #[inline]
60 pub fn new(inner: R, byte_order: ByteOrder) -> Self {
61 Self { inner, byte_order }
62 }
63
64 /// Returns an immutable reference to the wrapped reader.
65 ///
66 /// # Returns
67 /// The wrapped reader reference.
68 #[inline]
69 pub fn get_ref(&self) -> &R {
70 &self.inner
71 }
72
73 /// Returns a mutable reference to the wrapped reader.
74 ///
75 /// # Returns
76 /// The wrapped reader reference.
77 #[inline]
78 pub fn get_mut(&mut self) -> &mut R {
79 &mut self.inner
80 }
81
82 /// Consumes this wrapper and returns the wrapped reader.
83 ///
84 /// # Returns
85 /// The wrapped reader.
86 #[inline]
87 pub fn into_inner(self) -> R {
88 self.inner
89 }
90
91 /// Returns the byte order used by multi-byte reads.
92 ///
93 /// # Returns
94 /// The configured byte order.
95 #[inline]
96 pub fn byte_order(&self) -> ByteOrder {
97 self.byte_order
98 }
99
100 /// Changes the byte order used by multi-byte reads.
101 ///
102 /// # Parameters
103 /// - `byte_order`: New byte order.
104 #[inline]
105 pub fn set_byte_order(&mut self, byte_order: ByteOrder) {
106 self.byte_order = byte_order;
107 }
108}
109
110impl<R> BinaryReader<R>
111where
112 R: Read,
113{
114 /// Reads one unsigned byte.
115 ///
116 /// # Errors
117 /// Returns an I/O error from the wrapped reader.
118 #[inline]
119 pub fn read_u8(&mut self) -> Result<u8> {
120 self.inner.read_u8()
121 }
122
123 /// Reads one signed byte.
124 ///
125 /// # Errors
126 /// Returns an I/O error from the wrapped reader.
127 #[inline]
128 pub fn read_i8(&mut self) -> Result<i8> {
129 self.inner.read_i8()
130 }
131
132 /// Reads a `u16` using the configured byte order.
133 ///
134 /// # Errors
135 /// Returns an I/O error from the wrapped reader.
136 #[inline]
137 pub fn read_u16(&mut self) -> Result<u16> {
138 self.inner.read_u16(self.byte_order)
139 }
140
141 /// Reads an `i16` using the configured byte order.
142 ///
143 /// # Errors
144 /// Returns an I/O error from the wrapped reader.
145 #[inline]
146 pub fn read_i16(&mut self) -> Result<i16> {
147 self.inner.read_i16(self.byte_order)
148 }
149
150 /// Reads a `u32` using the configured byte order.
151 ///
152 /// # Errors
153 /// Returns an I/O error from the wrapped reader.
154 #[inline]
155 pub fn read_u32(&mut self) -> Result<u32> {
156 self.inner.read_u32(self.byte_order)
157 }
158
159 /// Reads an `i32` using the configured byte order.
160 ///
161 /// # Errors
162 /// Returns an I/O error from the wrapped reader.
163 #[inline]
164 pub fn read_i32(&mut self) -> Result<i32> {
165 self.inner.read_i32(self.byte_order)
166 }
167
168 /// Reads a `u64` using the configured byte order.
169 ///
170 /// # Errors
171 /// Returns an I/O error from the wrapped reader.
172 #[inline]
173 pub fn read_u64(&mut self) -> Result<u64> {
174 self.inner.read_u64(self.byte_order)
175 }
176
177 /// Reads an `i64` using the configured byte order.
178 ///
179 /// # Errors
180 /// Returns an I/O error from the wrapped reader.
181 #[inline]
182 pub fn read_i64(&mut self) -> Result<i64> {
183 self.inner.read_i64(self.byte_order)
184 }
185
186 /// Reads a `u128` using the configured byte order.
187 ///
188 /// # Errors
189 /// Returns an I/O error from the wrapped reader.
190 #[inline]
191 pub fn read_u128(&mut self) -> Result<u128> {
192 self.inner.read_u128(self.byte_order)
193 }
194
195 /// Reads an `i128` using the configured byte order.
196 ///
197 /// # Errors
198 /// Returns an I/O error from the wrapped reader.
199 #[inline]
200 pub fn read_i128(&mut self) -> Result<i128> {
201 self.inner.read_i128(self.byte_order)
202 }
203
204 /// Reads an `f32` using the configured byte order.
205 ///
206 /// # Errors
207 /// Returns an I/O error from the wrapped reader.
208 #[inline]
209 pub fn read_f32(&mut self) -> Result<f32> {
210 self.inner.read_f32(self.byte_order)
211 }
212
213 /// Reads an `f64` using the configured byte order.
214 ///
215 /// # Errors
216 /// Returns an I/O error from the wrapped reader.
217 #[inline]
218 pub fn read_f64(&mut self) -> Result<f64> {
219 self.inner.read_f64(self.byte_order)
220 }
221
222 /// Reads a UTF-8 string with a `u16` byte-length prefix.
223 ///
224 /// # Parameters
225 /// - `max_len`: Maximum accepted UTF-8 payload length in bytes.
226 ///
227 /// # Errors
228 /// Returns an I/O error from the wrapped reader, or `InvalidData` when the
229 /// payload length exceeds `max_len` or the payload is not valid UTF-8.
230 #[inline]
231 pub fn read_utf8_string_u16(&mut self, max_len: usize) -> Result<String> {
232 match self.byte_order {
233 ByteOrder::BigEndian => self.inner.read_utf8_string_u16_be(max_len),
234 ByteOrder::LittleEndian => self.inner.read_utf8_string_u16_le(max_len),
235 }
236 }
237
238 /// Reads a UTF-8 string with a `u32` byte-length prefix.
239 ///
240 /// # Parameters
241 /// - `max_len`: Maximum accepted UTF-8 payload length in bytes.
242 ///
243 /// # Errors
244 /// Returns an I/O error from the wrapped reader, or `InvalidData` when the
245 /// payload length exceeds `max_len` or the payload is not valid UTF-8.
246 #[inline]
247 pub fn read_utf8_string_u32(&mut self, max_len: usize) -> Result<String> {
248 match self.byte_order {
249 ByteOrder::BigEndian => self.inner.read_utf8_string_u32_be(max_len),
250 ByteOrder::LittleEndian => self.inner.read_utf8_string_u32_le(max_len),
251 }
252 }
253}
254
255impl<R> Read for BinaryReader<R>
256where
257 R: Read,
258{
259 #[inline]
260 fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
261 self.inner.read(buffer)
262 }
263}
264
265impl<R> BufRead for BinaryReader<R>
266where
267 R: BufRead,
268{
269 #[inline]
270 fn fill_buf(&mut self) -> Result<&[u8]> {
271 self.inner.fill_buf()
272 }
273
274 #[inline]
275 fn consume(&mut self, amount: usize) {
276 self.inner.consume(amount);
277 }
278}
279
280impl<R> Seek for BinaryReader<R>
281where
282 R: Seek,
283{
284 #[inline]
285 fn seek(&mut self, position: SeekFrom) -> Result<u64> {
286 self.inner.seek(position)
287 }
288}