qubit_io/stream/
binary_writer.rs1use core::marker::PhantomData;
12use std::io::{
13 Result,
14 Seek,
15 SeekFrom,
16 Write,
17};
18
19use crate::WriteExt;
20use crate::codec::{
21 BigEndian,
22 BinaryCodec,
23 ByteOrder,
24 ByteOrderSpec,
25 LittleEndian,
26};
27use crate::util::{
28 checked_u16_len,
29 checked_u32_len,
30};
31
32pub struct BinaryWriter<W, O = BigEndian> {
38 inner: W,
39 buffer: [u8; 16],
40 marker: PhantomData<fn() -> O>,
41}
42
43impl<W, O> BinaryWriter<W, O>
44where
45 W: Write,
46 O: ByteOrderSpec,
47{
48 #[must_use]
58 #[inline]
59 pub const fn new(inner: W) -> Self {
60 Self {
61 inner,
62 buffer: [0; 16],
63 marker: PhantomData,
64 }
65 }
66
67 #[must_use]
69 #[inline]
70 pub const fn byte_order(&self) -> ByteOrder {
71 O::ORDER
72 }
73
74 #[must_use]
76 #[inline]
77 pub const fn get_ref(&self) -> &W {
78 &self.inner
79 }
80
81 #[must_use]
83 #[inline]
84 pub fn get_mut(&mut self) -> &mut W {
85 &mut self.inner
86 }
87
88 #[must_use]
90 #[inline]
91 pub fn into_inner(self) -> W {
92 self.inner
93 }
94}
95
96macro_rules! impl_value_write {
97 ($order:ty, $method:ident, $ty:ty, $doc:literal) => {
98 #[doc = $doc]
99 #[inline]
100 pub fn $method(&mut self, value: $ty) -> Result<()> {
101 type Codec = BinaryCodec<$ty, $order>;
102
103 const LEN: usize = Codec::REQUIRED_MIN_BUFFER_LEN;
104 unsafe {
106 Codec::write_unchecked(&mut self.buffer, 0, value);
107 self.inner.write_all_unchecked(&self.buffer, 0, LEN)
108 }
109 }
110 };
111}
112
113macro_rules! impl_for_order {
114 ($order:ty) => {
115 impl<W> BinaryWriter<W, $order>
116 where
117 W: Write,
118 {
119 impl_value_write!($order, write_u8, u8, "Writes an unsigned 8-bit integer.");
120 impl_value_write!($order, write_i8, i8, "Writes a signed 8-bit integer.");
121 impl_value_write!($order, write_u16, u16, "Writes an unsigned 16-bit integer.");
122 impl_value_write!($order, write_u32, u32, "Writes an unsigned 32-bit integer.");
123 impl_value_write!($order, write_u64, u64, "Writes an unsigned 64-bit integer.");
124 impl_value_write!($order, write_u128, u128, "Writes an unsigned 128-bit integer.");
125 impl_value_write!($order, write_i16, i16, "Writes a signed 16-bit integer.");
126 impl_value_write!($order, write_i32, i32, "Writes a signed 32-bit integer.");
127 impl_value_write!($order, write_i64, i64, "Writes a signed 64-bit integer.");
128 impl_value_write!($order, write_i128, i128, "Writes a signed 128-bit integer.");
129 impl_value_write!($order, write_f32, f32, "Writes a 32-bit float.");
130 impl_value_write!($order, write_f64, f64, "Writes a 64-bit float.");
131
132 #[inline]
134 pub fn write_utf8_string_u16(&mut self, value: &str) -> Result<()> {
135 self.write_u16(checked_u16_len(value.len())?)?;
136 let bytes = value.as_bytes();
137 unsafe { self.inner.write_all_unchecked(bytes, 0, bytes.len()) }
139 }
140
141 #[inline]
143 pub fn write_utf8_string_u32(&mut self, value: &str) -> Result<()> {
144 self.write_u32(checked_u32_len(value.len())?)?;
145 let bytes = value.as_bytes();
146 unsafe { self.inner.write_all_unchecked(bytes, 0, bytes.len()) }
148 }
149 }
150 };
151}
152
153impl_for_order!(BigEndian);
154impl_for_order!(LittleEndian);
155
156impl<W, O> Write for BinaryWriter<W, O>
157where
158 W: Write,
159{
160 #[inline]
174 fn write(&mut self, buffer: &[u8]) -> Result<usize> {
175 self.inner.write(buffer)
176 }
177
178 #[inline]
184 fn flush(&mut self) -> Result<()> {
185 self.inner.flush()
186 }
187}
188
189impl<W, O> Seek for BinaryWriter<W, O>
190where
191 W: Seek,
192{
193 #[inline]
207 fn seek(&mut self, position: SeekFrom) -> Result<u64> {
208 self.inner.seek(position)
209 }
210}