brs 0.1.0

Read and write Brickadia save files.
Documentation
// Currently panics on EOF.
// Needs improvement.

use std::io::{self, prelude::*};

pub struct BitReader {
    buf: Vec<u8>,
    pos: usize,
}

impl BitReader {
    pub fn new(buf: Vec<u8>) -> Self {
        Self { buf, pos: 0 }
    }

    // ReadBit
    #[inline(always)]
    pub fn read_bit(&mut self) -> bool {
        let bit = (self.buf[self.pos >> 3] & (1 << (self.pos & 7))) != 0;
        self.pos += 1;
        bit
    }

    // SerializeBits
    pub fn read_bits(&mut self, dst: &mut [u8], len: usize) {
        for bit in 0..len {
            let byte = &mut dst[bit >> 3];
            let shift = bit & 7;
            *byte = (*byte & !(1 << shift)) | (u8::from(self.read_bit()) << shift);
        }
        self.pos += len;
    }

    // SerializeInt
    pub fn read_int(&mut self, max: u32) -> u32 {
        let mut value = 0;
        let mut mask = 1;

        while (value + mask) < max && mask != 0 {
            if self.read_bit() {
                value |= mask;
            }
            mask *= 2;
        }

        value
    }

    // SerializeIntPacked
    pub fn read_int_packed(&mut self) -> u32 {
        /*
        let mut src = &self.buf[..];
        let bit_count_used_in_byte = self.pos & 7;
        let bit_count_left_in_byte = 8 - (self.pos & 7);
        let src_mask_byte_0 = ((1 << bit_count_left_in_byte) - 1) as u8;
        let src_mask_byte_1 = ((1 << bit_count_used_in_byte) - 1) as u8;
        let next_src_index = (bit_count_used_in_byte != 0) as usize;

        let mut value: u32 = 0;

        let mut it = 0;
        let mut shift_count = 0;

        while it < 5 {
            self.pos += 8;

            let byte = ((src[0] >> bit_count_used_in_byte) & src_mask_byte_0)
                | ((src[next_src_index] & src_mask_byte_1) << (bit_count_left_in_byte & 7));
            let next_byte_indicator = byte & 1;
            let byte_as_word = (byte >> 1) as u32;
            value = (byte_as_word << shift_count) | value;
            src = &src[1..];

            if next_byte_indicator == 0 {
                break;
            }

            it += 1;
            shift_count += 7;
        }

        value
        */

        let mut value = 0;

        for i in 0..5 {
            let has_next = self.read_bit();
            let mut part = 0;
            for bit_shift in 0..7 {
                part |= (self.read_bit() as u32) << bit_shift;
            }
            value |= part << (7 * i);
            if !has_next {
                break;
            }
        }

        value
    }

    // EatByteAlign
    pub fn eat_byte_align(&mut self) {
        self.pos = (self.pos + 7) & !0x07;
    }

    // SerializeIntVectorPacked
    pub fn read_int_vector_packed(&mut self) -> (i32, i32, i32) {
        (self.rivp_item(), self.rivp_item(), self.rivp_item())
    }

    #[inline(always)]
    fn rivp_item(&mut self) -> i32 {
        let value = self.read_int_packed();
        (value >> 1) as i32 * if value & 1 != 0 { 1 } else { -1 }
    }

    // SerializePositiveIntVectorPacked
    pub fn read_positive_int_vector_packed(&mut self) -> (u32, u32, u32) {
        (
            self.read_int_packed(),
            self.read_int_packed(),
            self.read_int_packed(),
        )
    }
}

impl Read for BitReader {
    fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
        self.read_bits(dst, dst.len() * 8);
        Ok(dst.len())
    }
}