zip-core 0.0.4

zip implementation independent structs and helpers
Documentation
use super::{
    super::{DigitalSignature, DigitalSignatureFixed},
    preview_u16_from_buf, validate_length, validate_length_fixed, DynamicSizeError, FixedSizeError, Parse, ParseExtend,
};

extern crate alloc;
use alloc::vec;

impl Parse for DigitalSignatureFixed {
    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_signature: buf.get_u32_le(),
            size_of_data:     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_u32_le(self.header_signature);
        buf.put_u16_le(self.size_of_data);
        Ok(())
    }
}

impl ParseExtend for DigitalSignature {
    type Error = DynamicSizeError;
    type Fixed = DigitalSignatureFixed;

    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.size_of_data as usize;
        let fixed = validate_length_fixed(buf.remaining(), total, fixed, DynamicSizeError::UnsufficientExactBytes)?;

        let mut signature_data = vec![0; fixed.size_of_data as usize];
        buf.copy_to_slice(&mut signature_data);

        Ok(Self { fixed, signature_data })
    }
}

impl Parse for DigitalSignature {
    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 = DigitalSignatureFixed::SIZE_IN_BYTES;
        validate_length(remaining, SIZE, DynamicSizeError::UnsufficientAtLeastBytes)?;
        const PEEK_START: usize = SIZE - 2;
        let chunk = buf.chunk();
        let size_of_data: u16 = preview_u16_from_buf(chunk, PEEK_START).ok_or(DynamicSizeError::NotContiguous(SIZE))?;
        let total = SIZE + size_of_data as usize;
        validate_length(remaining, total, DynamicSizeError::UnsufficientExactBytes)?;

        let fixed = DigitalSignatureFixed::from_buf(buf).map_err(FixedSizeError::in_dynamic)?;
        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 = DigitalSignatureFixed::SIZE_IN_BYTES + self.signature_data.len();
        validate_length(remaining, total, DynamicSizeError::UnsufficientExactBytes)?;
        self.fixed.to_buf(buf).map_err(FixedSizeError::in_dynamic)?;
        buf.put_slice(&self.signature_data);
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::{super::*, *};

    #[test]
    fn cycle_digital_signature() {
        let signature_data = vec![48, 49, 32, 50];
        let ds = DigitalSignature {
            fixed: DigitalSignatureFixed {
                header_signature: DigitalSignatureFixed::HEADER_SIGNATURE,
                size_of_data:     signature_data.len() as u16,
            },
            signature_data: signature_data.clone(),
        };
        let mut buf = vec![];
        ds.to_buf(&mut buf).unwrap();
        assert_eq!(buf.len(), DigitalSignatureFixed::SIZE_IN_BYTES + signature_data.len());
        let mut readbuf = buf.as_slice();
        let ds2 = DigitalSignature::from_buf(&mut readbuf).unwrap();
        assert_eq!(ds, ds2);
        assert_eq!(ds2.signature_data, signature_data);
    }

    #[test]
    fn parseextend_digital_signature() {
        let buf: Vec<u8> = vec![48, 49, 32, 50];
        let mut fixed = DigitalSignatureFixed {
            header_signature: DigitalSignatureFixed::HEADER_SIGNATURE,
            size_of_data:     buf.len() as u16,
        };
        assert!(DigitalSignature::from_buf_fixed(&mut buf.as_slice(), fixed.clone()).is_ok());
        fixed.size_of_data += 1;
        assert!(DigitalSignature::from_buf_fixed(&mut buf.as_slice(), fixed).is_err());
    }
}