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}