xz-rs 0.1.0

A pure-Rust implementation of xz-utils
Documentation
use crate::block::BlockDecodeError;
use crate::decode::{Decode, DecodeError};
use crate::encode::Encode;

#[derive(Debug, Clone)]
pub struct BlockFlags {
    pub filter_count: u8,
    pub has_compressed_size: bool,
    pub has_uncompressed_size: bool,
}

const FILTER_COUNT_MASK: u8 = 0x03;
const RESERVED_MASK: u8 = 0x3C;
const HAS_COMPRESSED_SIZE_MASK: u8 = 0x40;
const HAS_UNCOMPRESSED_SIZE_MASK: u8 = 0x80;

impl Encode for BlockFlags {
    fn encoding(&self) -> Vec<u8> {
        let filter_count = (self.filter_count - 1) & FILTER_COUNT_MASK;

        let has_compressed_size = if self.has_compressed_size {
            HAS_COMPRESSED_SIZE_MASK
        } else {
            0
        };

        let has_uncompressed_size = if self.has_uncompressed_size {
            HAS_UNCOMPRESSED_SIZE_MASK
        } else {
            0
        };

        vec![filter_count | has_compressed_size | has_uncompressed_size]
    }
}

impl Decode for BlockFlags {
    fn decode<R: std::io::Read>(src: &mut R) -> Result<Self, DecodeError> {
        let mut bytes = [0u8];
        src.read_exact(&mut bytes)?;
        let byte = bytes[0];

        let filter_count = (byte & FILTER_COUNT_MASK) + 1;
        let reserved = byte & RESERVED_MASK;
        let has_compressed_size = (byte & HAS_COMPRESSED_SIZE_MASK) > 0;
        let has_uncompressed_size = (byte & HAS_UNCOMPRESSED_SIZE_MASK) > 0;

        if reserved > 0 {
            return Err(DecodeError::BlockError(BlockDecodeError::InvalidHeader));
        }
        Ok(Self {
            filter_count,
            has_compressed_size,
            has_uncompressed_size,
        })
    }
}