zip_core/raw/parse/
extensible_data.rs

1use crate::raw::{ExtensibleData, ExtensibleDataFixed};
2
3use super::{
4    preview_u16_from_buf, validate_length, validate_length_fixed, DynamicSizeError, FixedSizeError, Parse, ParseExtend,
5};
6
7extern crate alloc;
8use alloc::vec;
9
10impl Parse for ExtensibleDataFixed {
11    type Error = FixedSizeError;
12
13    fn from_buf<T: bytes::Buf>(buf: &mut T) -> Result<Self, Self::Error>
14    where
15        Self: Sized,
16    {
17        let remaining = buf.remaining();
18        validate_length(remaining, Self::SIZE_IN_BYTES, FixedSizeError::UnsufficientExactBytes)?;
19        Ok(Self {
20            header_id: buf.get_u16_le(),
21            data_size: buf.get_u16_le(),
22        })
23    }
24
25    fn to_buf<T: bytes::BufMut>(&self, buf: &mut T) -> Result<(), Self::Error> {
26        let remaining = buf.remaining_mut();
27        validate_length(remaining, Self::SIZE_IN_BYTES, FixedSizeError::UnsufficientExactBytes)?;
28        buf.put_u16_le(self.header_id);
29        buf.put_u16_le(self.data_size);
30        Ok(())
31    }
32}
33
34impl ParseExtend for ExtensibleData {
35    type Error = DynamicSizeError;
36    type Fixed = ExtensibleDataFixed;
37
38    fn from_buf_fixed<T: bytes::Buf>(buf: &mut T, fixed: Self::Fixed) -> Result<Self, (Self::Error, Self::Fixed)>
39    where
40        Self: Sized,
41    {
42        let total = fixed.data_size as usize;
43        let fixed = validate_length_fixed(buf.remaining(), total, fixed, DynamicSizeError::UnsufficientExactBytes)?;
44
45        let mut data = vec![0; fixed.data_size as usize];
46        buf.copy_to_slice(&mut data);
47
48        Ok(Self { fixed, data })
49    }
50}
51
52impl Parse for ExtensibleData {
53    type Error = DynamicSizeError;
54
55    fn from_buf<T: bytes::Buf>(buf: &mut T) -> Result<Self, Self::Error>
56    where
57        Self: Sized,
58    {
59        let remaining = buf.remaining();
60        const SIZE: usize = ExtensibleDataFixed::SIZE_IN_BYTES;
61        validate_length(remaining, SIZE, DynamicSizeError::UnsufficientAtLeastBytes)?;
62        const PEEK_START: usize = SIZE - 2;
63        let chunk = buf.chunk();
64        let data_length: u16 = preview_u16_from_buf(chunk, PEEK_START).ok_or(DynamicSizeError::NotContiguous(SIZE))?;
65        let total = SIZE + data_length as usize;
66        validate_length(remaining, total, DynamicSizeError::UnsufficientExactBytes)?;
67
68        let fixed = ExtensibleDataFixed::from_buf(buf).map_err(FixedSizeError::in_dynamic)?;
69        Self::from_buf_fixed(buf, fixed).map_err(|e| e.0)
70    }
71
72    fn to_buf<T: bytes::BufMut>(&self, buf: &mut T) -> Result<(), Self::Error> {
73        let remaining = buf.remaining_mut();
74        let total = ExtensibleDataFixed::SIZE_IN_BYTES + self.data.len();
75        validate_length(remaining, total, DynamicSizeError::UnsufficientExactBytes)?;
76        self.fixed.to_buf(buf).map_err(FixedSizeError::in_dynamic)?;
77        buf.put_slice(&self.data);
78        Ok(())
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::{super::*, *};
85
86    #[test]
87    fn cycle_extensible_data() {
88        let data = vec![48, 49, 32];
89        let ed = ExtensibleData {
90            fixed: ExtensibleDataFixed {
91                header_id: 0x0001,
92                data_size: data.len() as u16,
93            },
94            data:  data.clone(),
95        };
96        let mut buf = vec![];
97        ed.to_buf(&mut buf).unwrap();
98        assert_eq!(buf.len(), ExtensibleDataFixed::SIZE_IN_BYTES + data.len());
99        let mut readbuf = buf.as_slice();
100        let ed2 = ExtensibleData::from_buf(&mut readbuf).unwrap();
101        assert_eq!(ed, ed2);
102        assert_eq!(ed2.data, data);
103    }
104
105    #[test]
106    fn parseextend_extensible_data() {
107        let buf: Vec<u8> = vec![48, 49, 32, 50];
108        let mut fixed = ExtensibleDataFixed {
109            header_id: 0x0001,
110            data_size: buf.len() as u16,
111        };
112        assert!(ExtensibleData::from_buf_fixed(&mut buf.as_slice(), fixed.clone()).is_ok());
113        fixed.data_size += 1;
114        assert!(ExtensibleData::from_buf_fixed(&mut buf.as_slice(), fixed).is_err());
115    }
116}