bzip2_rs/header/
mod.rs

1//! bzip2 low-level header APIs
2
3pub use self::error::HeaderError;
4
5mod error;
6
7/// A bzip2 header
8#[derive(Clone)]
9pub struct Header {
10    raw_blocksize: u8,
11    max_blocksize: u32,
12}
13
14impl Header {
15    /// Parse a bzip2 header
16    pub fn parse(buf: [u8; 4]) -> Result<Self, HeaderError> {
17        let signature = &buf[..2];
18        if signature != b"BZ" {
19            return Err(HeaderError::InvalidSignature);
20        }
21
22        let version = buf[2];
23        if version != b'h' {
24            return Err(HeaderError::UnsupportedVersion);
25        }
26
27        let hundred_k_blocksize = buf[3];
28        match hundred_k_blocksize {
29            b'1'..=b'9' => {
30                let raw_blocksize = hundred_k_blocksize - b'0';
31                Self::from_raw_blocksize(raw_blocksize)
32            }
33            _ => Err(HeaderError::InvalidBlockSize),
34        }
35    }
36
37    /// Construct `Header` from the raw blocksize
38    ///
39    /// # Errors
40    ///
41    /// Returns [`HeaderError::InvalidBlockSize`] if `raw_blocksize`
42    /// isn't `1..=9`
43    pub fn from_raw_blocksize(raw_blocksize: u8) -> Result<Self, HeaderError> {
44        if raw_blocksize < 1 || raw_blocksize > 9 {
45            return Err(HeaderError::InvalidBlockSize);
46        }
47
48        let max_blocksize = 100 * 1000 * u32::from(raw_blocksize);
49        Ok(Self {
50            raw_blocksize,
51            max_blocksize,
52        })
53    }
54
55    /// The raw blocksize, as declared in the bzip2 header
56    ///
57    /// The returned value is always `1..=9`
58    pub fn raw_blocksize(&self) -> u8 {
59        self.raw_blocksize
60    }
61
62    /// The maximum blocksize
63    ///
64    /// The returned value is always `100000..=900000`
65    pub fn max_blocksize(&self) -> u32 {
66        self.max_blocksize
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn valid_9k() {
76        let header = Header::parse(*b"BZh9").unwrap();
77        assert_eq!(header.raw_blocksize(), 9);
78        assert_eq!(header.max_blocksize(), 900000);
79    }
80}