use crate::raw::{ExtensibleData, ExtensibleDataFixed};
use super::{preview_u16_from_buf, validate_length, DynamicSizeError, FixedSizeError, Parse, ParseExtend};
extern crate alloc;
use alloc::vec;
impl Parse for ExtensibleDataFixed {
type Error = FixedSizeError;
fn from_buf<T: bytes::Buf>(buf: &mut T) -> Result<Self, Self::Error>
where
Self: Sized,
{
let remaining = buf.remaining();
validate_length(remaining, Self::SIZE_IN_BYTES, FixedSizeError::UnsufficientExactBytes)?;
Ok(Self {
header_id: buf.get_u16_le(),
data_size: buf.get_u16_le(),
})
}
fn to_buf<T: bytes::BufMut>(&self, buf: &mut T) -> Result<(), Self::Error> {
let remaining = buf.remaining_mut();
validate_length(remaining, Self::SIZE_IN_BYTES, FixedSizeError::UnsufficientExactBytes)?;
buf.put_u16_le(self.header_id);
buf.put_u16_le(self.data_size);
Ok(())
}
}
impl ParseExtend for ExtensibleData {
type Error = DynamicSizeError;
type Fixed = ExtensibleDataFixed;
fn from_buf_fixed<T: bytes::Buf>(buf: &mut T, fixed: Self::Fixed) -> Result<Self, (Self::Error, Self::Fixed)>
where
Self: Sized,
{
let total = fixed.data_size as usize;
if let Err(e) = validate_length(buf.remaining(), total, DynamicSizeError::UnsufficientExactBytes) {
return Err((e, fixed));
};
let mut data = vec![0; fixed.data_size as usize];
buf.copy_to_slice(&mut data);
Ok(Self { fixed, data })
}
}
impl Parse for ExtensibleData {
type Error = DynamicSizeError;
fn from_buf<T: bytes::Buf>(buf: &mut T) -> Result<Self, Self::Error>
where
Self: Sized,
{
let remaining = buf.remaining();
const SIZE: usize = ExtensibleDataFixed::SIZE_IN_BYTES;
validate_length(remaining, SIZE, DynamicSizeError::UnsufficientAtLeastBytes)?;
let chunk = buf.chunk();
let data_length: u16 = preview_u16_from_buf(chunk, SIZE - 2).ok_or(DynamicSizeError::NotContiguous)?;
let total = SIZE + data_length as usize;
validate_length(remaining, total, DynamicSizeError::UnsufficientExactBytes)?;
let fixed = ExtensibleDataFixed::from_buf(buf)?;
Self::from_buf_fixed(buf, fixed).map_err(|e| e.0)
}
fn to_buf<T: bytes::BufMut>(&self, buf: &mut T) -> Result<(), Self::Error> {
let remaining = buf.remaining_mut();
let total = ExtensibleDataFixed::SIZE_IN_BYTES + self.data.len();
validate_length(remaining, total, FixedSizeError::UnsufficientExactBytes)?;
self.fixed.to_buf(buf)?;
buf.put_slice(&self.data);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{super::*, *};
#[test]
fn cycle_local_file_header() {
let data = vec![48, 49, 32];
let lf = ExtensibleData {
fixed: ExtensibleDataFixed {
header_id: 0x0001,
data_size: data.len() as u16,
},
data: data.clone(),
};
let mut buf = vec![];
lf.to_buf(&mut buf).unwrap();
assert_eq!(buf.len(), ExtensibleDataFixed::SIZE_IN_BYTES + data.len());
let mut readbuf = buf.as_slice();
let lf2 = ExtensibleData::from_buf(&mut readbuf).unwrap();
assert_eq!(lf, lf2);
assert_eq!(lf2.data, data);
}
}