use crate::put_bytes::{PutBytes, PutBytesError};
pub trait ToBytes {
fn to_bytes<PB: PutBytes, E: PutBytesError>(&self, target: &mut PB) -> Result<usize, E>;
}
impl ToBytes for bool {
fn to_bytes<PB: PutBytes, E: PutBytesError>(&self, target: &mut PB) -> Result<usize, E> {
let val = if *self { 1u8 } else { 0u8 };
ToBytes::to_bytes(&val, target)
}
}
macro_rules! impl_to_bytes_for_primitive {
($type:ty) => {
impl ToBytes for $type {
fn to_bytes<PB: PutBytes, E: PutBytesError>(
&self,
target: &mut PB,
) -> Result<usize, E> {
target
.put_bytes(&self.to_be_bytes())
.map(|()| std::mem::size_of::<$type>())
}
}
};
}
impl_to_bytes_for_primitive!(i8);
impl_to_bytes_for_primitive!(i16);
impl_to_bytes_for_primitive!(i32);
impl_to_bytes_for_primitive!(i64);
impl_to_bytes_for_primitive!(u8);
impl_to_bytes_for_primitive!(u16);
impl_to_bytes_for_primitive!(u32);
impl_to_bytes_for_primitive!(u64);
impl_to_bytes_for_primitive!(f32);
impl_to_bytes_for_primitive!(f64);
impl ToBytes for usize {
fn to_bytes<PB: PutBytes, E: PutBytesError>(&self, target: &mut PB) -> Result<usize, E> {
ToBytes::to_bytes(&(*self as u64), target)
}
}
impl ToBytes for char {
fn to_bytes<PB: PutBytes, E: PutBytesError>(&self, target: &mut PB) -> Result<usize, E> {
ToBytes::to_bytes(&(*self as u32), target)
}
}
impl<TB: ToBytes, const COUNT: usize> ToBytes for [TB; COUNT] {
fn to_bytes<PB: PutBytes, E: PutBytesError>(&self, target: &mut PB) -> Result<usize, E> {
let mut n = 0;
for i in 0..COUNT {
n += ToBytes::to_bytes(&self[i], target)?;
}
Ok(n)
}
}
impl<TB: ToBytes> ToBytes for &[TB] {
fn to_bytes<PB: PutBytes, E: PutBytesError>(&self, target: &mut PB) -> Result<usize, E> {
let mut n = self.len().to_bytes(target)?;
for i in 0..self.len() {
n += self.as_ref()[i].to_bytes(target)?;
}
Ok(n)
}
}
impl ToBytes for &str {
fn to_bytes<PB: PutBytes, E: PutBytesError>(&self, target: &mut PB) -> Result<usize, E> {
self.as_bytes().to_bytes(target)
}
}
impl<T: ToBytes> ToBytes for Option<T> {
fn to_bytes<PB: PutBytes, E: PutBytesError>(&self, target: &mut PB) -> Result<usize, E> {
match self {
Some(val) => Ok(ToBytes::to_bytes(&1u8, target)? + ToBytes::to_bytes(val, target)?),
None => ToBytes::to_bytes(&0u8, target),
}
}
}