use crate::{
decode_u32, decode_u64, encode_u32, encode_u64, CompactEncoding, EncodingError, U32_SIZE,
U64_SIZE,
};
pub trait FixedWidthEncoding {
type Decode;
fn fw_encoded_size(&self) -> Result<usize, EncodingError>;
fn fw_encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError>;
fn fw_decode(buffer: &[u8]) -> Result<(Self::Decode, &[u8]), EncodingError>
where
Self: Sized;
fn as_fixed_width(&self) -> FixedWidthUint<'_, Self> {
FixedWidthUint(self)
}
}
#[derive(Debug)]
pub struct FixedWidthUint<'a, T: FixedWidthEncoding + ?Sized>(&'a T);
impl<T: FixedWidthEncoding> CompactEncoding<T::Decode> for FixedWidthUint<'_, T> {
fn encoded_size(&self) -> Result<usize, EncodingError> {
self.0.fw_encoded_size()
}
fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
self.0.fw_encode(buffer)
}
fn decode(buffer: &[u8]) -> Result<(T::Decode, &[u8]), EncodingError>
where
Self: Sized,
{
<T as FixedWidthEncoding>::fw_decode(buffer)
}
}
impl FixedWidthEncoding for u32 {
type Decode = u32;
fn fw_encoded_size(&self) -> Result<usize, EncodingError> {
Ok(U32_SIZE)
}
fn fw_encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
encode_u32(*self, buffer)
}
fn fw_decode(buffer: &[u8]) -> Result<(Self::Decode, &[u8]), EncodingError>
where
Self: Sized,
{
decode_u32(buffer)
}
}
impl FixedWidthEncoding for u64 {
type Decode = u64;
fn fw_encoded_size(&self) -> Result<usize, EncodingError> {
Ok(U64_SIZE)
}
fn fw_encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
encode_u64(*self, buffer)
}
fn fw_decode(buffer: &[u8]) -> Result<(Self::Decode, &[u8]), EncodingError>
where
Self: Sized,
{
decode_u64(buffer)
}
}
pub type FixedWidthU32<'a> = FixedWidthUint<'a, u32>;
pub type FixedWidthU64<'a> = FixedWidthUint<'a, u64>;
#[cfg(test)]
mod test {
use crate::{map_decode, to_encoded_bytes};
use super::*;
#[test]
fn fixed_width_u32() -> Result<(), EncodingError> {
let x = 42u32;
let fixed_buff = to_encoded_bytes!(x.as_fixed_width());
let var_buff = to_encoded_bytes!(x);
assert_eq!(fixed_buff, [42_u8, 0, 0, 0].into());
assert_eq!(var_buff, [42_u8].into());
let ((fixed_dec,), rest) = map_decode!(&fixed_buff, [FixedWidthU32]);
assert!(rest.is_empty());
assert_eq!(fixed_dec, x);
let ((var_dec,), rest) = map_decode!(&var_buff, [u32]);
assert!(rest.is_empty());
assert_eq!(var_dec, x);
Ok(())
}
#[test]
fn fixed_width_u64() -> Result<(), EncodingError> {
let x = 42u64;
let fixed_buff = to_encoded_bytes!(x.as_fixed_width());
let var_buff = to_encoded_bytes!(x);
assert_eq!(fixed_buff, [42, 0, 0, 0, 0, 0, 0, 0].into());
assert_eq!(var_buff, [42].into());
let ((fixed_dec,), rest) = map_decode!(&fixed_buff, [FixedWidthU64]);
assert!(rest.is_empty());
assert_eq!(fixed_dec, x);
Ok(())
}
}