Skip to main content

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}