#[cfg(feature = "alloc")]
extern crate alloc;
use crate::{Error, ErrorKind};
use std::ops::{Deref, DerefMut};
pub trait MutBits {
fn write_u8(&mut self, val: u8) -> Result<(), Error>;
fn write_be_u16(&mut self, val: u16) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_le_u16(&mut self, val: u16) -> Result<(), Error> {
self.write_all_bytes(&val.swap_bytes().to_be_bytes())
}
fn write_be_u32(&mut self, val: u32) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_le_u32(&mut self, val: u32) -> Result<(), Error> {
self.write_all_bytes(&val.swap_bytes().to_be_bytes())
}
fn write_be_u64(&mut self, val: u64) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_le_u64(&mut self, val: u64) -> Result<(), Error> {
self.write_all_bytes(&val.swap_bytes().to_be_bytes())
}
fn write_be_u128(&mut self, val: u128) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_le_u128(&mut self, val: u128) -> Result<(), Error> {
self.write_all_bytes(&val.swap_bytes().to_be_bytes())
}
fn write_f32(&mut self, val: f32) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_f64(&mut self, val: f64) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_be_i16(&mut self, val: i16) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_le_i16(&mut self, val: i16) -> Result<(), Error> {
self.write_all_bytes(&val.swap_bytes().to_be_bytes())
}
fn write_be_i32(&mut self, val: i32) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_le_i32(&mut self, val: i32) -> Result<(), Error> {
self.write_all_bytes(&val.swap_bytes().to_be_bytes())
}
fn write_be_i64(&mut self, val: i64) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_le_i64(&mut self, val: i64) -> Result<(), Error> {
self.write_all_bytes(&val.swap_bytes().to_be_bytes())
}
fn write_be_i128(&mut self, val: i128) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_le_i128(&mut self, val: i128) -> Result<(), Error> {
self.write_all_bytes(&val.swap_bytes().to_be_bytes())
}
fn write_u8_blob(&mut self, val: &[u8]) -> Result<(), Error> {
if val.len() > u8::MAX as usize {
return Err(Error::new(
ErrorKind::InvalidData,
"value is too long to fit into a u8",
));
}
self.write_u8(val.len() as u8)?;
self.write_all_bytes(val)
}
fn write_be_u16_blob(&mut self, val: &[u8]) -> Result<(), Error> {
if val.len() > u16::MAX as usize {
return Err(Error::new(
ErrorKind::InvalidData,
"value is too long to fit into a u16",
));
}
self.write_be_u16(val.len() as u16)?;
self.write_all_bytes(val)
}
fn write_le_u16_blob(&mut self, val: &[u8]) -> Result<(), Error> {
if val.len() > u16::MAX as usize {
return Err(Error::new(
ErrorKind::InvalidData,
"value is too long to fit into a u16",
));
}
self.write_le_u16(val.len() as u16)?;
self.write_all_bytes(val)
}
fn write_be_u32_blob(&mut self, val: &[u8]) -> Result<(), Error> {
if val.len() > u32::MAX as usize {
return Err(Error::new(
ErrorKind::InvalidData,
"value is too long to fit into a u32",
));
}
self.write_be_u32(val.len() as u32)?;
self.write_all_bytes(val)
}
fn write_le_u32_blob(&mut self, val: &[u8]) -> Result<(), Error> {
if val.len() > u32::MAX as usize {
return Err(Error::new(
ErrorKind::InvalidData,
"value is too long to fit into a u32",
));
}
self.write_le_u32(val.len() as u32)?;
self.write_all_bytes(val)
}
fn write_be_u64_blob(&mut self, val: &[u8]) -> Result<(), Error> {
if val.len() > u64::MAX as usize {
return Err(Error::new(
ErrorKind::InvalidData,
"value is too long to fit into a u64",
));
}
self.write_be_u64(val.len() as u64)?;
self.write_all_bytes(val)
}
fn write_le_u64_blob(&mut self, val: &[u8]) -> Result<(), Error> {
if val.len() > u64::MAX as usize {
return Err(Error::new(
ErrorKind::InvalidData,
"value is too long to fit into a u64",
));
}
self.write_le_u64(val.len() as u64)?;
self.write_all_bytes(val)
}
fn write_all_bytes(&mut self, val: &[u8]) -> Result<(), Error> {
for val in val {
self.write_u8(*val)?;
}
Ok(())
}
#[cfg(feature = "alloc")]
fn write_fmt_impl(&mut self, args: core::fmt::Arguments<'_>) -> Result<(), Error> {
extern crate alloc;
self.write_all_bytes(alloc::fmt::format(args).as_bytes())
}
fn write_some_bytes(&mut self, val: &[u8]) -> usize {
let mut wrote = 0;
for val in val {
if self.write_u8(*val).is_err() {
return wrote;
}
wrote += 1;
}
wrote
}
fn write_str_u32_blob(&mut self, val: &str) -> Result<usize, Error> {
let len = val.len() as u32;
self.write_be_u32(len)?;
self.write_all_bytes(val.as_bytes())?;
Ok((len + 4) as usize)
}
fn write_exact(&mut self, val: &[u8], len: usize) -> Result<(), Error> {
for idx in 0..len {
let Some(val) = val.get(idx) else {
return Err(ErrorKind::UnexpectedEof.into());
};
self.write_u8(*val)?;
}
Ok(())
}
}
impl MutBits for &mut [u8] {
fn write_u8(&mut self, val: u8) -> Result<(), Error> {
let Some((a, b)) = core::mem::take(self).split_first_mut() else {
return Err(ErrorKind::UnexpectedEof.into());
};
*a = val;
*self = b;
Ok(())
}
}
pub struct FormatBits<'a, T: MutBits + ?Sized> {
val: &'a mut T,
}
impl<'a, T: MutBits + ?Sized> FormatBits<'a, T> {
pub fn wrap(val: &'a mut T) -> Self {
Self { val }
}
}
impl<'a, T: MutBits + ?Sized> From<&'a mut T> for FormatBits<'a, T> {
fn from(val: &'a mut T) -> Self {
FormatBits { val }
}
}
impl<'a, T: MutBits + ?Sized> Deref for FormatBits<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.val
}
}
impl<'a, T: MutBits + ?Sized> DerefMut for FormatBits<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.val
}
}
impl<'a, T: MutBits + ?Sized> core::fmt::Write for FormatBits<'a, T> {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
for ch in s.chars() {
self.write_char(ch)?;
}
Ok(())
}
fn write_char(&mut self, c: char) -> core::fmt::Result {
let mut chr = [0; 4];
let val = c.encode_utf8(&mut chr).len();
if let Err(_e) = self.val.write_exact(&chr, val) {
return Err(core::fmt::Error);
};
Ok(())
}
}