zip/extra_fields/
custom_extra_field.rs1use crate::result::ZipResult;
4use crate::result::invalid;
5use std::io::Write;
6
7#[derive(Debug, PartialEq, Eq, Clone)]
9pub struct CustomExtraField {
10 pub(crate) central_only: bool,
12 pub header_id: u16,
14 pub data: Box<[u8]>,
16}
17
18impl CustomExtraField {
19 pub(crate) fn new(central_only: bool, header_id: u16, data: Box<[u8]>) -> Self {
20 Self {
21 central_only,
22 header_id,
23 data,
24 }
25 }
26
27 #[allow(unused)] pub(crate) fn new_from_raw(central_only: bool, data: &[u8]) -> ZipResult<Self> {
29 if data.len() < 2 {
30 return Err(invalid!("Cannot build a CustomExtraField: no header_id"));
31 }
32 if data.len() < 4 {
33 return Err(invalid!("Cannot build a CustomExtraField: no size"));
34 }
35 let header_id = u16::from_le_bytes([data[0], data[1]]);
36 let size = u16::from_le_bytes([data[2], data[3]]) as usize;
37 if size > (u16::MAX - 4) as usize {
38 return Err(invalid!("Cannot build a CustomExtraField: size too big"));
39 }
40 let data_rest = &data[4..];
41 if size != data_rest.len() {
42 return Err(invalid!("Cannot build a CustomExtraField: incorrect size"));
43 }
44 Ok(Self {
45 central_only,
46 header_id,
47 data: data_rest.to_vec().into_boxed_slice(),
48 })
49 }
50
51 pub(crate) fn full_size(&self, is_local_header: bool) -> usize {
52 if self.central_only && is_local_header {
53 return 0;
54 }
55 let size = self.data.len();
56 size_of::<u16>() + size_of::<u16>() + size
57 }
58
59 pub(crate) fn write<W: Write>(&self, write: &mut W, is_local_header: bool) -> ZipResult<()> {
60 if self.central_only && is_local_header {
61 return Ok(());
62 }
63 write.write_all(&self.header_id.to_le_bytes())?;
64 let size = self.data.len() as u16;
65 write.write_all(&size.to_le_bytes())?;
66 write.write_all(&self.data)?;
67 Ok(())
68 }
69}
70
71#[cfg(feature = "_arbitrary")]
72impl arbitrary::Arbitrary<'_> for CustomExtraField {
73 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
74 Ok(CustomExtraField {
75 central_only: u.arbitrary()?,
76 header_id: u.arbitrary()?,
77 data: u.arbitrary()?,
78 })
79 }
80}