irox_bits/
mutbits.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2025 IROX Contributors
3//
4
5cfg_feature_alloc! {
6    extern crate alloc;
7}
8
9use crate::{Bits, Error, ErrorKind};
10use core::ops::{Deref, DerefMut};
11
12///
13/// Write methods for the primitive types
14pub trait MutBits {
15    /// Writes a single [`u8`]
16    fn write_u8(&mut self, val: u8) -> Result<(), Error>;
17
18    /// Writes a single [`i8`]
19    fn write_i8(&mut self, val: i8) -> Result<(), Error> {
20        self.write_u8(val as u8)
21    }
22
23    /// Writes 1u8 if true, 0u8 if false
24    fn write_bool(&mut self, val: bool) -> Result<(), Error> {
25        self.write_u8(val as u8)
26    }
27
28    /// Encodes the character as UTF-8, and writes anywhere from 1-4 bytes.  The number of bytes
29    /// written is returned.
30    fn write_be_utf8_char(&mut self, val: char) -> Result<usize, Error> {
31        crate::utf::write_be_utf8_char(val, self)
32    }
33
34    /// Writes a single [`u16`] in big-endian order, 2 bytes, MSB first.
35    fn write_be_u16(&mut self, val: u16) -> Result<(), Error> {
36        self.write_all_bytes(&val.to_be_bytes())
37    }
38    /// Writes a single [`u16`] in little-endian order, 2 bytes, LSB first.
39    fn write_le_u16(&mut self, val: u16) -> Result<(), Error> {
40        self.write_all_bytes(&val.swap_bytes().to_be_bytes())
41    }
42    /// Writes a single [`u32`] in big-endian order, 4 bytes, MSB first.
43    fn write_be_u32(&mut self, val: u32) -> Result<(), Error> {
44        self.write_all_bytes(&val.to_be_bytes())
45    }
46    /// Writes a single [`u32`] in little-endian order, 4 bytes, LSB first.
47    fn write_le_u32(&mut self, val: u32) -> Result<(), Error> {
48        self.write_all_bytes(&val.swap_bytes().to_be_bytes())
49    }
50    /// Writes a single [`u64`] in big-endian order, 8 bytes, MSB first.
51    fn write_be_u64(&mut self, val: u64) -> Result<(), Error> {
52        self.write_all_bytes(&val.to_be_bytes())
53    }
54    /// Writes a single [`u64`] in little-endian order, 8 bytes, LSB first.
55    fn write_le_u64(&mut self, val: u64) -> Result<(), Error> {
56        self.write_all_bytes(&val.swap_bytes().to_be_bytes())
57    }
58    /// Writes a single [`u128`] in big-endian order, 16 bytes, MSB first.
59    fn write_be_u128(&mut self, val: u128) -> Result<(), Error> {
60        self.write_all_bytes(&val.to_be_bytes())
61    }
62    /// Writes a single [`u128`] in little-endian order, 16 bytes, LSB first.
63    fn write_le_u128(&mut self, val: u128) -> Result<(), Error> {
64        self.write_all_bytes(&val.swap_bytes().to_be_bytes())
65    }
66
67    /// Writes a single [`f32`] in standard IEEE754 format, 4 bytes
68    fn write_be_f32(&mut self, val: f32) -> Result<(), Error> {
69        self.write_all_bytes(&val.to_be_bytes())
70    }
71    /// Writes a single [`f32`] in reversed IEEE754 format, 4 bytes
72    fn write_le_f32(&mut self, val: f32) -> Result<(), Error> {
73        self.write_all_bytes(&val.to_le_bytes())
74    }
75    /// Writes a single [`u16`] in standard IEEE754 format, 8 bytes
76    fn write_be_f64(&mut self, val: f64) -> Result<(), Error> {
77        self.write_all_bytes(&val.to_be_bytes())
78    }
79    /// Writes a single [`u16`] in reversed IEEE754 format, 8 bytes
80    fn write_le_f64(&mut self, val: f64) -> Result<(), Error> {
81        self.write_all_bytes(&val.to_le_bytes())
82    }
83
84    /// Writes a single [`i16`] in big-endian order, 2 bytes, MSB first.
85    fn write_be_i16(&mut self, val: i16) -> Result<(), Error> {
86        self.write_all_bytes(&val.to_be_bytes())
87    }
88    /// Writes a single [`i16`] in little-endian order, 2 bytes, LSB first.
89    fn write_le_i16(&mut self, val: i16) -> Result<(), Error> {
90        self.write_all_bytes(&val.swap_bytes().to_be_bytes())
91    }
92    /// Writes a single [`i32`] in big-endian order, 4 bytes, MSB first.
93    fn write_be_i32(&mut self, val: i32) -> Result<(), Error> {
94        self.write_all_bytes(&val.to_be_bytes())
95    }
96    /// Writes a single [`i32`] in little-endian order, 4 bytes, LSB first.
97    fn write_le_i32(&mut self, val: i32) -> Result<(), Error> {
98        self.write_all_bytes(&val.swap_bytes().to_be_bytes())
99    }
100    /// Writes a single [`i64`] in big-endian order, 8 bytes, MSB first.
101    fn write_be_i64(&mut self, val: i64) -> Result<(), Error> {
102        self.write_all_bytes(&val.to_be_bytes())
103    }
104    /// Writes a single [`i64`] in little-endian order, 8 bytes, LSB first.
105    fn write_le_i64(&mut self, val: i64) -> Result<(), Error> {
106        self.write_all_bytes(&val.swap_bytes().to_be_bytes())
107    }
108    /// Writes a single [`i128`] in big-endian order, 16 bytes, MSB first.
109    fn write_be_i128(&mut self, val: i128) -> Result<(), Error> {
110        self.write_all_bytes(&val.to_be_bytes())
111    }
112    /// Writes a single [`i128`] in little-endian order, 16 bytes, LSB first.
113    fn write_le_i128(&mut self, val: i128) -> Result<(), Error> {
114        self.write_all_bytes(&val.swap_bytes().to_be_bytes())
115    }
116
117    /// Writes a sized blob, a series of bytes preceded by a [`u8`] declaring the size
118    fn write_u8_blob(&mut self, val: &[u8]) -> Result<(), Error> {
119        if val.len() > u8::MAX as usize {
120            return Err(Error::new(
121                ErrorKind::InvalidData,
122                "value is too long to fit into a u8",
123            ));
124        }
125        self.write_u8(val.len() as u8)?;
126        self.write_all_bytes(val)
127    }
128    /// Writes a sized blob, a series of bytes preceded by a [`u16`] declaring the size
129    fn write_be_u16_blob(&mut self, val: &[u8]) -> Result<(), Error> {
130        if val.len() > u16::MAX as usize {
131            return Err(Error::new(
132                ErrorKind::InvalidData,
133                "value is too long to fit into a u16",
134            ));
135        }
136        self.write_be_u16(val.len() as u16)?;
137        self.write_all_bytes(val)
138    }
139    /// Writes a sized blob, a series of bytes preceded by a [`u16`] declaring the size
140    fn write_le_u16_blob(&mut self, val: &[u8]) -> Result<(), Error> {
141        if val.len() > u16::MAX as usize {
142            return Err(Error::new(
143                ErrorKind::InvalidData,
144                "value is too long to fit into a u16",
145            ));
146        }
147        self.write_le_u16(val.len() as u16)?;
148        self.write_all_bytes(val)
149    }
150    /// Writes a sized blob, a series of bytes preceded by a [`u32`] declaring the size
151    fn write_be_u32_blob(&mut self, val: &[u8]) -> Result<(), Error> {
152        if val.len() > u32::MAX as usize {
153            return Err(Error::new(
154                ErrorKind::InvalidData,
155                "value is too long to fit into a u32",
156            ));
157        }
158        self.write_be_u32(val.len() as u32)?;
159        self.write_all_bytes(val)
160    }
161    /// Writes a sized blob, a series of bytes preceded by a [`u32`] declaring the size
162    fn write_le_u32_blob(&mut self, val: &[u8]) -> Result<(), Error> {
163        if val.len() > u32::MAX as usize {
164            return Err(Error::new(
165                ErrorKind::InvalidData,
166                "value is too long to fit into a u32",
167            ));
168        }
169        self.write_le_u32(val.len() as u32)?;
170        self.write_all_bytes(val)
171    }
172    /// Writes a sized blob, a series of bytes preceded by a [`u64`] declaring the size
173    fn write_be_u64_blob(&mut self, val: &[u8]) -> Result<(), Error> {
174        if val.len() > u64::MAX as usize {
175            return Err(Error::new(
176                ErrorKind::InvalidData,
177                "value is too long to fit into a u64",
178            ));
179        }
180        self.write_be_u64(val.len() as u64)?;
181        self.write_all_bytes(val)
182    }
183    /// Writes a sized blob, a series of bytes preceded by a [`u64`] declaring the size
184    fn write_le_u64_blob(&mut self, val: &[u8]) -> Result<(), Error> {
185        if val.len() > u64::MAX as usize {
186            return Err(Error::new(
187                ErrorKind::InvalidData,
188                "value is too long to fit into a u64",
189            ));
190        }
191        self.write_le_u64(val.len() as u64)?;
192        self.write_all_bytes(val)
193    }
194
195    /// Writes all the bytes in order
196    fn write_all_bytes(&mut self, val: &[u8]) -> Result<(), Error> {
197        for v in val {
198            self.write_u8(*v)?;
199        }
200        Ok(())
201    }
202
203    cfg_feature_alloc! {
204        /// Allows the use of [`core::format_args`] macro
205        fn write_fmt_impl(&mut self, args: core::fmt::Arguments<'_>) -> Result<(), Error> {
206            extern crate alloc;
207            self.write_all_bytes(alloc::fmt::format(args).as_bytes())
208        }
209    }
210
211    ///
212    /// Writes some subset of bytes until either the input is exhausted, or the
213    /// underlying buffer fills up or errors.  Returns the total number of bytes
214    /// written
215    fn write_some_bytes(&mut self, val: &[u8]) -> usize {
216        let mut wrote = 0;
217        for val in val {
218            if self.write_u8(*val).is_err() {
219                return wrote;
220            }
221            wrote += 1;
222        }
223        wrote
224    }
225
226    ///
227    /// Writes a specific sized string from the stream, a string prefixed by a
228    /// 4-byte big-endian length.
229    fn write_str_u32_blob(&mut self, val: &str) -> Result<usize, Error> {
230        let len = val.len() as u32;
231        self.write_be_u32(len)?;
232        self.write_all_bytes(val.as_bytes())?;
233
234        Ok((len + 4) as usize)
235    }
236
237    ///
238    /// Writes the exact amount of bytes from the input buffer to the output stream
239    /// Returns an error if the buffer doesn't have enough values or if the
240    /// output stream errors.
241    fn write_exact(&mut self, val: &[u8], len: usize) -> Result<(), Error> {
242        for idx in 0..len {
243            let Some(val) = val.get(idx) else {
244                return Err(ErrorKind::UnexpectedEof.into());
245            };
246            self.write_u8(*val)?;
247        }
248        Ok(())
249    }
250
251    ///
252    /// Copies all data from the other stream into this stream.
253    fn write_all_into_self_from<T: Bits>(&mut self, other: &mut T) -> Result<u64, Error> {
254        let mut used = 0;
255        while let Some(v) = other.next_u8()? {
256            self.write_u8(v)?;
257            used += 1;
258        }
259        Ok(used)
260    }
261
262    ///
263    /// Flush all bytes out of the cache.  Most impl's won't need this.
264    fn flush(&mut self) -> Result<(), Error> {
265        Ok(())
266    }
267}
268
269impl MutBits for &mut [u8] {
270    fn write_u8(&mut self, val: u8) -> Result<(), Error> {
271        let Some((a, b)) = core::mem::take(self).split_first_mut() else {
272            return Err(ErrorKind::UnexpectedEof.into());
273        };
274        *a = val;
275        *self = b;
276        Ok(())
277    }
278}
279
280/// Wraps a borrowed [`MutBits`], providing an implementation of [`core::fmt::Write`] to permit the
281/// use of the [`core::write!`] macro with a target of `&mut`[`MutBits`]
282pub struct FormatBits<'a, T: MutBits + ?Sized>(pub &'a mut T);
283
284impl<'a, T: MutBits + ?Sized> FormatBits<'a, T> {
285    pub fn wrap(val: &'a mut T) -> Self {
286        FormatBits(val)
287    }
288}
289impl<'a, T: MutBits + ?Sized> From<&'a mut T> for FormatBits<'a, T> {
290    fn from(val: &'a mut T) -> Self {
291        FormatBits(val)
292    }
293}
294impl<T: MutBits + ?Sized> Deref for FormatBits<'_, T> {
295    type Target = T;
296
297    fn deref(&self) -> &Self::Target {
298        self.0
299    }
300}
301impl<T: MutBits + ?Sized> DerefMut for FormatBits<'_, T> {
302    fn deref_mut(&mut self) -> &mut Self::Target {
303        self.0
304    }
305}
306
307impl<T: MutBits + ?Sized> core::fmt::Write for FormatBits<'_, T> {
308    fn write_str(&mut self, s: &str) -> core::fmt::Result {
309        for ch in s.chars() {
310            self.write_char(ch)?;
311        }
312        Ok(())
313    }
314
315    fn write_char(&mut self, c: char) -> core::fmt::Result {
316        self.write_be_utf8_char(c)?;
317        Ok(())
318    }
319}