nibble8 0.2.0

Yet another Rust implementation of a Chip-8 interpreter, using sdl2.
use crate::bit_utils::get_bit_from_byte;

pub struct DisplayState {
    raw: Vec<u8>,
    cols: usize,
    rows: usize,
}

impl DisplayState {
    pub fn new(cols: usize, rows: usize) -> Self {
        let raw: Vec<u8> = vec![0x00; cols * rows / 8];
        DisplayState { cols, rows, raw }
    }

    pub fn clear(&mut self) {
        self.raw = vec![0x00; self.cols * self.rows / 8];
    }

    fn identify(&self, x: usize, y: usize) -> (usize, usize) {
        let bit_idx = y * self.cols + x;
        let byte_idx = bit_idx / 8;
        let bit_in_byte = bit_idx % 8;
        (byte_idx, bit_in_byte)
    }

    pub fn is_on(&mut self, x: usize, y: usize) -> bool {
        let (byte_idx, bit_idx) = self.identify(x, y);
        get_bit_from_byte(bit_idx, &self.raw[byte_idx])
    }

    pub fn flip(&mut self, x: usize, y: usize) {
        let (byte_idx, bit_idx) = self.identify(x, y);
        let mask = 0b10000000 >> bit_idx;
        self.raw[byte_idx] ^= mask;
    }

    pub fn as_bytes(&self) -> &[u8] {
        &self.raw
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn flip() {
        let mut s = DisplayState::new(8, 1);
        s.flip(4, 0);
        assert_eq!(s.as_bytes()[0], 0b0001000);

        s.flip(4, 0);
        assert_eq!(s.as_bytes()[0], 0b0000000);
    }

    #[test]
    fn identify() {
        let s = DisplayState::new(64, 32);

        let (byte, bit) = s.identify(0, 0);
        assert_eq!(byte, 0);
        assert_eq!(bit, 0);

        let (byte, bit) = s.identify(5, 0);
        assert_eq!(byte, 0);
        assert_eq!(bit, 5);

        let (byte, bit) = s.identify(0, 1);
        assert_eq!(byte, 8);
        assert_eq!(bit, 0);
    }
}