cfg_feature_alloc! {
extern crate alloc;
}
use crate::{Bits, Error, ErrorKind};
use core::ops::{Deref, DerefMut};
pub trait MutBits {
fn write_u8(&mut self, val: u8) -> Result<(), Error>;
fn write_i8(&mut self, val: i8) -> Result<(), Error> {
self.write_u8(val as u8)
}
fn write_bool(&mut self, val: bool) -> Result<(), Error> {
self.write_u8(val as u8)
}
fn write_be_utf8_char(&mut self, val: char) -> Result<usize, Error> {
crate::utf::write_be_utf8_char(val, self)
}
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_be_f32(&mut self, val: f32) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_le_f32(&mut self, val: f32) -> Result<(), Error> {
self.write_all_bytes(&val.to_le_bytes())
}
fn write_be_f64(&mut self, val: f64) -> Result<(), Error> {
self.write_all_bytes(&val.to_be_bytes())
}
fn write_le_f64(&mut self, val: f64) -> Result<(), Error> {
self.write_all_bytes(&val.to_le_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 v in val {
self.write_u8(*v)?;
}
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(())
}
fn write_all_into_self_from<T: Bits>(&mut self, other: &mut T) -> Result<u64, Error> {
let mut used = 0;
while let Some(v) = other.next_u8()? {
self.write_u8(v)?;
used += 1;
}
Ok(used)
}
fn flush(&mut self) -> Result<(), Error> {
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>(pub &'a mut T);
impl<'a, T: MutBits + ?Sized> FormatBits<'a, T> {
pub fn wrap(val: &'a mut T) -> Self {
FormatBits(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.0
}
}
impl<'a, T: MutBits + ?Sized> DerefMut for FormatBits<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
}
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 {
self.write_be_utf8_char(c)?;
Ok(())
}
}