Skip to main content

qubit_io/codecs/
binary_writer.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    Result,
12    Seek,
13    SeekFrom,
14    Write,
15};
16
17use crate::{
18    BinaryWriteExt,
19    ByteOrder,
20    StringWriteExt,
21};
22
23/// Writer wrapper for binary scalar and length-prefixed string encoding.
24///
25/// Multi-byte methods use the configured [`ByteOrder`].
26///
27/// # Examples
28/// ```
29/// use qubit_io::{
30///     BinaryWriter,
31///     ByteOrder,
32/// };
33///
34/// let mut output = BinaryWriter::new(Vec::new(), ByteOrder::LittleEndian);
35/// output.write_u16(0x1234)?;
36///
37/// assert_eq!(vec![0x34, 0x12], output.into_inner());
38/// # Ok::<(), std::io::Error>(())
39/// ```
40pub struct BinaryWriter<W> {
41    inner: W,
42    byte_order: ByteOrder,
43}
44
45impl<W> BinaryWriter<W> {
46    /// Creates a binary writer.
47    ///
48    /// # Parameters
49    /// - `inner`: Writer to wrap.
50    /// - `byte_order`: Byte order used by multi-byte writes.
51    ///
52    /// # Returns
53    /// A new binary writer.
54    #[inline]
55    pub fn new(inner: W, byte_order: ByteOrder) -> Self {
56        Self { inner, byte_order }
57    }
58
59    /// Returns an immutable reference to the wrapped writer.
60    ///
61    /// # Returns
62    /// The wrapped writer reference.
63    #[inline]
64    pub fn get_ref(&self) -> &W {
65        &self.inner
66    }
67
68    /// Returns a mutable reference to the wrapped writer.
69    ///
70    /// # Returns
71    /// The wrapped writer reference.
72    #[inline]
73    pub fn get_mut(&mut self) -> &mut W {
74        &mut self.inner
75    }
76
77    /// Consumes this wrapper and returns the wrapped writer.
78    ///
79    /// # Returns
80    /// The wrapped writer.
81    #[inline]
82    pub fn into_inner(self) -> W {
83        self.inner
84    }
85
86    /// Returns the byte order used by multi-byte writes.
87    ///
88    /// # Returns
89    /// The configured byte order.
90    #[inline]
91    pub fn byte_order(&self) -> ByteOrder {
92        self.byte_order
93    }
94
95    /// Changes the byte order used by multi-byte writes.
96    ///
97    /// # Parameters
98    /// - `byte_order`: New byte order.
99    #[inline]
100    pub fn set_byte_order(&mut self, byte_order: ByteOrder) {
101        self.byte_order = byte_order;
102    }
103}
104
105impl<W> BinaryWriter<W>
106where
107    W: Write,
108{
109    /// Writes one unsigned byte.
110    ///
111    /// # Errors
112    /// Returns an I/O error from the wrapped writer.
113    #[inline]
114    pub fn write_u8(&mut self, value: u8) -> Result<()> {
115        self.inner.write_u8(value)
116    }
117
118    /// Writes one signed byte.
119    ///
120    /// # Errors
121    /// Returns an I/O error from the wrapped writer.
122    #[inline]
123    pub fn write_i8(&mut self, value: i8) -> Result<()> {
124        self.inner.write_i8(value)
125    }
126
127    /// Writes a `u16` using the configured byte order.
128    ///
129    /// # Errors
130    /// Returns an I/O error from the wrapped writer.
131    #[inline]
132    pub fn write_u16(&mut self, value: u16) -> Result<()> {
133        self.inner.write_u16(value, self.byte_order)
134    }
135
136    /// Writes an `i16` using the configured byte order.
137    ///
138    /// # Errors
139    /// Returns an I/O error from the wrapped writer.
140    #[inline]
141    pub fn write_i16(&mut self, value: i16) -> Result<()> {
142        self.inner.write_i16(value, self.byte_order)
143    }
144
145    /// Writes a `u32` using the configured byte order.
146    ///
147    /// # Errors
148    /// Returns an I/O error from the wrapped writer.
149    #[inline]
150    pub fn write_u32(&mut self, value: u32) -> Result<()> {
151        self.inner.write_u32(value, self.byte_order)
152    }
153
154    /// Writes an `i32` using the configured byte order.
155    ///
156    /// # Errors
157    /// Returns an I/O error from the wrapped writer.
158    #[inline]
159    pub fn write_i32(&mut self, value: i32) -> Result<()> {
160        self.inner.write_i32(value, self.byte_order)
161    }
162
163    /// Writes a `u64` using the configured byte order.
164    ///
165    /// # Errors
166    /// Returns an I/O error from the wrapped writer.
167    #[inline]
168    pub fn write_u64(&mut self, value: u64) -> Result<()> {
169        self.inner.write_u64(value, self.byte_order)
170    }
171
172    /// Writes an `i64` using the configured byte order.
173    ///
174    /// # Errors
175    /// Returns an I/O error from the wrapped writer.
176    #[inline]
177    pub fn write_i64(&mut self, value: i64) -> Result<()> {
178        self.inner.write_i64(value, self.byte_order)
179    }
180
181    /// Writes a `u128` using the configured byte order.
182    ///
183    /// # Errors
184    /// Returns an I/O error from the wrapped writer.
185    #[inline]
186    pub fn write_u128(&mut self, value: u128) -> Result<()> {
187        self.inner.write_u128(value, self.byte_order)
188    }
189
190    /// Writes an `i128` using the configured byte order.
191    ///
192    /// # Errors
193    /// Returns an I/O error from the wrapped writer.
194    #[inline]
195    pub fn write_i128(&mut self, value: i128) -> Result<()> {
196        self.inner.write_i128(value, self.byte_order)
197    }
198
199    /// Writes an `f32` using the configured byte order.
200    ///
201    /// # Errors
202    /// Returns an I/O error from the wrapped writer.
203    #[inline]
204    pub fn write_f32(&mut self, value: f32) -> Result<()> {
205        self.inner.write_f32(value, self.byte_order)
206    }
207
208    /// Writes an `f64` using the configured byte order.
209    ///
210    /// # Errors
211    /// Returns an I/O error from the wrapped writer.
212    #[inline]
213    pub fn write_f64(&mut self, value: f64) -> Result<()> {
214        self.inner.write_f64(value, self.byte_order)
215    }
216
217    /// Writes a UTF-8 string with a `u16` byte-length prefix.
218    ///
219    /// # Parameters
220    /// - `value`: String slice to write.
221    ///
222    /// # Errors
223    /// Returns an I/O error from the wrapped writer, or `InvalidInput` when
224    /// the UTF-8 byte length does not fit into `u16`.
225    #[inline]
226    pub fn write_utf8_string_u16(&mut self, value: &str) -> Result<()> {
227        match self.byte_order {
228            ByteOrder::BigEndian => self.inner.write_utf8_string_u16_be(value),
229            ByteOrder::LittleEndian => self.inner.write_utf8_string_u16_le(value),
230        }
231    }
232
233    /// Writes a UTF-8 string with a `u32` byte-length prefix.
234    ///
235    /// # Parameters
236    /// - `value`: String slice to write.
237    ///
238    /// # Errors
239    /// Returns an I/O error from the wrapped writer, or `InvalidInput` when
240    /// the UTF-8 byte length does not fit into `u32`.
241    #[inline]
242    pub fn write_utf8_string_u32(&mut self, value: &str) -> Result<()> {
243        match self.byte_order {
244            ByteOrder::BigEndian => self.inner.write_utf8_string_u32_be(value),
245            ByteOrder::LittleEndian => self.inner.write_utf8_string_u32_le(value),
246        }
247    }
248}
249
250impl<W> Write for BinaryWriter<W>
251where
252    W: Write,
253{
254    #[inline]
255    fn write(&mut self, buffer: &[u8]) -> Result<usize> {
256        self.inner.write(buffer)
257    }
258
259    #[inline]
260    fn flush(&mut self) -> Result<()> {
261        self.inner.flush()
262    }
263}
264
265impl<W> Seek for BinaryWriter<W>
266where
267    W: Seek,
268{
269    #[inline]
270    fn seek(&mut self, position: SeekFrom) -> Result<u64> {
271        self.inner.seek(position)
272    }
273}