qubit_io/ext/binary_write_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 ******************************************************************************/
10use std::io::{
11 Result,
12 Write,
13};
14
15use crate::ByteOrder;
16
17/// Extension methods for writing binary scalar values to [`Write`] streams.
18///
19/// Multi-byte values can be written either with explicit byte-order suffixes
20/// or with a runtime [`ByteOrder`] argument. All methods delegate to
21/// [`Write::write_all`], so they either write the complete encoded value or
22/// return the first I/O error.
23pub trait BinaryWriteExt: Write {
24 /// Writes one unsigned byte.
25 ///
26 /// # Parameters
27 /// - `value`: Byte to write.
28 ///
29 /// # Errors
30 /// Returns an I/O error from the underlying writer.
31 fn write_u8(&mut self, value: u8) -> Result<()>;
32
33 /// Writes one signed byte.
34 ///
35 /// # Parameters
36 /// - `value`: Byte to write.
37 ///
38 /// # Errors
39 /// Returns an I/O error from the underlying writer.
40 fn write_i8(&mut self, value: i8) -> Result<()>;
41
42 /// Writes a `u16` using `order`.
43 ///
44 /// # Parameters
45 /// - `value`: Value to encode.
46 /// - `order`: Byte order used to encode the value.
47 ///
48 /// # Errors
49 /// Returns an I/O error from the underlying writer.
50 #[inline]
51 fn write_u16(&mut self, value: u16, order: ByteOrder) -> Result<()> {
52 match order {
53 ByteOrder::BigEndian => self.write_u16_be(value),
54 ByteOrder::LittleEndian => self.write_u16_le(value),
55 }
56 }
57
58 /// Writes a big-endian `u16`.
59 ///
60 /// # Parameters
61 /// - `value`: Value to encode.
62 ///
63 /// # Errors
64 /// Returns an I/O error from the underlying writer.
65 fn write_u16_be(&mut self, value: u16) -> Result<()>;
66
67 /// Writes a little-endian `u16`.
68 ///
69 /// # Parameters
70 /// - `value`: Value to encode.
71 ///
72 /// # Errors
73 /// Returns an I/O error from the underlying writer.
74 fn write_u16_le(&mut self, value: u16) -> Result<()>;
75
76 /// Writes an `i16` using `order`.
77 ///
78 /// # Parameters
79 /// - `value`: Value to encode.
80 /// - `order`: Byte order used to encode the value.
81 ///
82 /// # Errors
83 /// Returns an I/O error from the underlying writer.
84 #[inline]
85 fn write_i16(&mut self, value: i16, order: ByteOrder) -> Result<()> {
86 match order {
87 ByteOrder::BigEndian => self.write_i16_be(value),
88 ByteOrder::LittleEndian => self.write_i16_le(value),
89 }
90 }
91
92 /// Writes a big-endian `i16`.
93 ///
94 /// # Parameters
95 /// - `value`: Value to encode.
96 ///
97 /// # Errors
98 /// Returns an I/O error from the underlying writer.
99 fn write_i16_be(&mut self, value: i16) -> Result<()>;
100
101 /// Writes a little-endian `i16`.
102 ///
103 /// # Parameters
104 /// - `value`: Value to encode.
105 ///
106 /// # Errors
107 /// Returns an I/O error from the underlying writer.
108 fn write_i16_le(&mut self, value: i16) -> Result<()>;
109
110 /// Writes a `u32` using `order`.
111 ///
112 /// # Parameters
113 /// - `value`: Value to encode.
114 /// - `order`: Byte order used to encode the value.
115 ///
116 /// # Errors
117 /// Returns an I/O error from the underlying writer.
118 #[inline]
119 fn write_u32(&mut self, value: u32, order: ByteOrder) -> Result<()> {
120 match order {
121 ByteOrder::BigEndian => self.write_u32_be(value),
122 ByteOrder::LittleEndian => self.write_u32_le(value),
123 }
124 }
125
126 /// Writes a big-endian `u32`.
127 ///
128 /// # Parameters
129 /// - `value`: Value to encode.
130 ///
131 /// # Errors
132 /// Returns an I/O error from the underlying writer.
133 fn write_u32_be(&mut self, value: u32) -> Result<()>;
134
135 /// Writes a little-endian `u32`.
136 ///
137 /// # Parameters
138 /// - `value`: Value to encode.
139 ///
140 /// # Errors
141 /// Returns an I/O error from the underlying writer.
142 fn write_u32_le(&mut self, value: u32) -> Result<()>;
143
144 /// Writes an `i32` using `order`.
145 ///
146 /// # Parameters
147 /// - `value`: Value to encode.
148 /// - `order`: Byte order used to encode the value.
149 ///
150 /// # Errors
151 /// Returns an I/O error from the underlying writer.
152 #[inline]
153 fn write_i32(&mut self, value: i32, order: ByteOrder) -> Result<()> {
154 match order {
155 ByteOrder::BigEndian => self.write_i32_be(value),
156 ByteOrder::LittleEndian => self.write_i32_le(value),
157 }
158 }
159
160 /// Writes a big-endian `i32`.
161 ///
162 /// # Parameters
163 /// - `value`: Value to encode.
164 ///
165 /// # Errors
166 /// Returns an I/O error from the underlying writer.
167 fn write_i32_be(&mut self, value: i32) -> Result<()>;
168
169 /// Writes a little-endian `i32`.
170 ///
171 /// # Parameters
172 /// - `value`: Value to encode.
173 ///
174 /// # Errors
175 /// Returns an I/O error from the underlying writer.
176 fn write_i32_le(&mut self, value: i32) -> Result<()>;
177
178 /// Writes a `u64` using `order`.
179 ///
180 /// # Parameters
181 /// - `value`: Value to encode.
182 /// - `order`: Byte order used to encode the value.
183 ///
184 /// # Errors
185 /// Returns an I/O error from the underlying writer.
186 #[inline]
187 fn write_u64(&mut self, value: u64, order: ByteOrder) -> Result<()> {
188 match order {
189 ByteOrder::BigEndian => self.write_u64_be(value),
190 ByteOrder::LittleEndian => self.write_u64_le(value),
191 }
192 }
193
194 /// Writes a big-endian `u64`.
195 ///
196 /// # Parameters
197 /// - `value`: Value to encode.
198 ///
199 /// # Errors
200 /// Returns an I/O error from the underlying writer.
201 fn write_u64_be(&mut self, value: u64) -> Result<()>;
202
203 /// Writes a little-endian `u64`.
204 ///
205 /// # Parameters
206 /// - `value`: Value to encode.
207 ///
208 /// # Errors
209 /// Returns an I/O error from the underlying writer.
210 fn write_u64_le(&mut self, value: u64) -> Result<()>;
211
212 /// Writes an `i64` using `order`.
213 ///
214 /// # Parameters
215 /// - `value`: Value to encode.
216 /// - `order`: Byte order used to encode the value.
217 ///
218 /// # Errors
219 /// Returns an I/O error from the underlying writer.
220 #[inline]
221 fn write_i64(&mut self, value: i64, order: ByteOrder) -> Result<()> {
222 match order {
223 ByteOrder::BigEndian => self.write_i64_be(value),
224 ByteOrder::LittleEndian => self.write_i64_le(value),
225 }
226 }
227
228 /// Writes a big-endian `i64`.
229 ///
230 /// # Parameters
231 /// - `value`: Value to encode.
232 ///
233 /// # Errors
234 /// Returns an I/O error from the underlying writer.
235 fn write_i64_be(&mut self, value: i64) -> Result<()>;
236
237 /// Writes a little-endian `i64`.
238 ///
239 /// # Parameters
240 /// - `value`: Value to encode.
241 ///
242 /// # Errors
243 /// Returns an I/O error from the underlying writer.
244 fn write_i64_le(&mut self, value: i64) -> Result<()>;
245
246 /// Writes a `u128` using `order`.
247 ///
248 /// # Parameters
249 /// - `value`: Value to encode.
250 /// - `order`: Byte order used to encode the value.
251 ///
252 /// # Errors
253 /// Returns an I/O error from the underlying writer.
254 #[inline]
255 fn write_u128(&mut self, value: u128, order: ByteOrder) -> Result<()> {
256 match order {
257 ByteOrder::BigEndian => self.write_u128_be(value),
258 ByteOrder::LittleEndian => self.write_u128_le(value),
259 }
260 }
261
262 /// Writes a big-endian `u128`.
263 ///
264 /// # Parameters
265 /// - `value`: Value to encode.
266 ///
267 /// # Errors
268 /// Returns an I/O error from the underlying writer.
269 fn write_u128_be(&mut self, value: u128) -> Result<()>;
270
271 /// Writes a little-endian `u128`.
272 ///
273 /// # Parameters
274 /// - `value`: Value to encode.
275 ///
276 /// # Errors
277 /// Returns an I/O error from the underlying writer.
278 fn write_u128_le(&mut self, value: u128) -> Result<()>;
279
280 /// Writes an `i128` using `order`.
281 ///
282 /// # Parameters
283 /// - `value`: Value to encode.
284 /// - `order`: Byte order used to encode the value.
285 ///
286 /// # Errors
287 /// Returns an I/O error from the underlying writer.
288 #[inline]
289 fn write_i128(&mut self, value: i128, order: ByteOrder) -> Result<()> {
290 match order {
291 ByteOrder::BigEndian => self.write_i128_be(value),
292 ByteOrder::LittleEndian => self.write_i128_le(value),
293 }
294 }
295
296 /// Writes a big-endian `i128`.
297 ///
298 /// # Parameters
299 /// - `value`: Value to encode.
300 ///
301 /// # Errors
302 /// Returns an I/O error from the underlying writer.
303 fn write_i128_be(&mut self, value: i128) -> Result<()>;
304
305 /// Writes a little-endian `i128`.
306 ///
307 /// # Parameters
308 /// - `value`: Value to encode.
309 ///
310 /// # Errors
311 /// Returns an I/O error from the underlying writer.
312 fn write_i128_le(&mut self, value: i128) -> Result<()>;
313
314 /// Writes an IEEE-754 `f32` using `order`.
315 ///
316 /// # Parameters
317 /// - `value`: Value to encode.
318 /// - `order`: Byte order used to encode the value.
319 ///
320 /// # Errors
321 /// Returns an I/O error from the underlying writer.
322 #[inline]
323 fn write_f32(&mut self, value: f32, order: ByteOrder) -> Result<()> {
324 match order {
325 ByteOrder::BigEndian => self.write_f32_be(value),
326 ByteOrder::LittleEndian => self.write_f32_le(value),
327 }
328 }
329
330 /// Writes a big-endian IEEE-754 `f32`.
331 ///
332 /// # Parameters
333 /// - `value`: Value to encode.
334 ///
335 /// # Errors
336 /// Returns an I/O error from the underlying writer.
337 fn write_f32_be(&mut self, value: f32) -> Result<()>;
338
339 /// Writes a little-endian IEEE-754 `f32`.
340 ///
341 /// # Parameters
342 /// - `value`: Value to encode.
343 ///
344 /// # Errors
345 /// Returns an I/O error from the underlying writer.
346 fn write_f32_le(&mut self, value: f32) -> Result<()>;
347
348 /// Writes an IEEE-754 `f64` using `order`.
349 ///
350 /// # Parameters
351 /// - `value`: Value to encode.
352 /// - `order`: Byte order used to encode the value.
353 ///
354 /// # Errors
355 /// Returns an I/O error from the underlying writer.
356 #[inline]
357 fn write_f64(&mut self, value: f64, order: ByteOrder) -> Result<()> {
358 match order {
359 ByteOrder::BigEndian => self.write_f64_be(value),
360 ByteOrder::LittleEndian => self.write_f64_le(value),
361 }
362 }
363
364 /// Writes a big-endian IEEE-754 `f64`.
365 ///
366 /// # Parameters
367 /// - `value`: Value to encode.
368 ///
369 /// # Errors
370 /// Returns an I/O error from the underlying writer.
371 fn write_f64_be(&mut self, value: f64) -> Result<()>;
372
373 /// Writes a little-endian IEEE-754 `f64`.
374 ///
375 /// # Parameters
376 /// - `value`: Value to encode.
377 ///
378 /// # Errors
379 /// Returns an I/O error from the underlying writer.
380 fn write_f64_le(&mut self, value: f64) -> Result<()>;
381}
382
383impl<T> BinaryWriteExt for T
384where
385 T: Write + ?Sized,
386{
387 #[inline]
388 fn write_u8(&mut self, value: u8) -> Result<()> {
389 self.write_all(&[value])
390 }
391
392 #[inline]
393 fn write_i8(&mut self, value: i8) -> Result<()> {
394 self.write_all(&[value as u8])
395 }
396
397 #[inline]
398 fn write_u16_be(&mut self, value: u16) -> Result<()> {
399 self.write_all(&value.to_be_bytes())
400 }
401
402 #[inline]
403 fn write_u16_le(&mut self, value: u16) -> Result<()> {
404 self.write_all(&value.to_le_bytes())
405 }
406
407 #[inline]
408 fn write_i16_be(&mut self, value: i16) -> Result<()> {
409 self.write_all(&value.to_be_bytes())
410 }
411
412 #[inline]
413 fn write_i16_le(&mut self, value: i16) -> Result<()> {
414 self.write_all(&value.to_le_bytes())
415 }
416
417 #[inline]
418 fn write_u32_be(&mut self, value: u32) -> Result<()> {
419 self.write_all(&value.to_be_bytes())
420 }
421
422 #[inline]
423 fn write_u32_le(&mut self, value: u32) -> Result<()> {
424 self.write_all(&value.to_le_bytes())
425 }
426
427 #[inline]
428 fn write_i32_be(&mut self, value: i32) -> Result<()> {
429 self.write_all(&value.to_be_bytes())
430 }
431
432 #[inline]
433 fn write_i32_le(&mut self, value: i32) -> Result<()> {
434 self.write_all(&value.to_le_bytes())
435 }
436
437 #[inline]
438 fn write_u64_be(&mut self, value: u64) -> Result<()> {
439 self.write_all(&value.to_be_bytes())
440 }
441
442 #[inline]
443 fn write_u64_le(&mut self, value: u64) -> Result<()> {
444 self.write_all(&value.to_le_bytes())
445 }
446
447 #[inline]
448 fn write_i64_be(&mut self, value: i64) -> Result<()> {
449 self.write_all(&value.to_be_bytes())
450 }
451
452 #[inline]
453 fn write_i64_le(&mut self, value: i64) -> Result<()> {
454 self.write_all(&value.to_le_bytes())
455 }
456
457 #[inline]
458 fn write_u128_be(&mut self, value: u128) -> Result<()> {
459 self.write_all(&value.to_be_bytes())
460 }
461
462 #[inline]
463 fn write_u128_le(&mut self, value: u128) -> Result<()> {
464 self.write_all(&value.to_le_bytes())
465 }
466
467 #[inline]
468 fn write_i128_be(&mut self, value: i128) -> Result<()> {
469 self.write_all(&value.to_be_bytes())
470 }
471
472 #[inline]
473 fn write_i128_le(&mut self, value: i128) -> Result<()> {
474 self.write_all(&value.to_le_bytes())
475 }
476
477 #[inline]
478 fn write_f32_be(&mut self, value: f32) -> Result<()> {
479 self.write_u32_be(value.to_bits())
480 }
481
482 #[inline]
483 fn write_f32_le(&mut self, value: f32) -> Result<()> {
484 self.write_u32_le(value.to_bits())
485 }
486
487 #[inline]
488 fn write_f64_be(&mut self, value: f64) -> Result<()> {
489 self.write_u64_be(value.to_bits())
490 }
491
492 #[inline]
493 fn write_f64_le(&mut self, value: f64) -> Result<()> {
494 self.write_u64_le(value.to_bits())
495 }
496}