Skip to main content

zip/extra_fields/
data_stream_alignment.rs

1//! Data stream alignment extra field
2
3use core::mem;
4use std::io::Write;
5
6use crate::extra_fields::UsedExtraField;
7
8/// Data stream alignment
9#[derive(Debug, Clone, PartialEq)]
10pub struct DataStreamAlignment {
11    /// alignment
12    alignment: u16,
13    /// padding length
14    pad_len: u16,
15}
16
17impl DataStreamAlignment {
18    /// create the alignment field using the full alignment len needed
19    #[must_use]
20    pub fn new(padding_len: u16, alignment: u16) -> Option<Self> {
21        if padding_len >= 6 {
22            Some(Self {
23                alignment,
24                pad_len: padding_len.saturating_sub(4),
25            })
26        } else {
27            None
28        }
29    }
30
31    pub(crate) fn full_size(&self, is_local_header: bool) -> usize {
32        if is_local_header {
33            mem::size_of::<u16>() + mem::size_of::<u16>() + self.pad_len as usize
34        } else {
35            // no padding in central header
36            0
37        }
38    }
39
40    pub(crate) fn write<W: Write>(
41        &self,
42        writer: &mut W,
43        is_local_header: bool,
44    ) -> std::io::Result<()> {
45        if !is_local_header {
46            // no padding in central header
47            return Ok(());
48        }
49        let magic = UsedExtraField::DataStreamAlignment.as_u16();
50        writer.write_all(&magic.to_le_bytes())?;
51        writer.write_all(&self.pad_len.to_le_bytes())?;
52        writer.write_all(&self.alignment.to_le_bytes())?;
53        let pad_len = self.pad_len.saturating_sub(2);
54        let zeros = [0u8; 1024];
55        let mut remaining = pad_len as usize;
56        while remaining > 0 {
57            let n = remaining.min(zeros.len());
58            writer.write_all(&zeros[..n])?;
59            remaining -= n;
60        }
61        Ok(())
62    }
63}