Skip to main content

plasma_prp/core/
bit_vector.rs

1//! hsBitVector — variable-length bit vector.
2//!
3//! Binary format: u32 count of u32 words, then that many u32 words.
4//!
5//! C++ ref: CoreLib/hsBitVector.h/.cpp
6
7use std::io::Read;
8
9use anyhow::Result;
10
11use crate::resource::prp::PlasmaRead;
12
13/// A variable-length bit vector, matching C++ hsBitVector.
14#[derive(Debug, Clone, Default)]
15pub struct BitVector {
16    pub words: Vec<u32>,
17}
18
19impl BitVector {
20    pub fn new() -> Self {
21        Self { words: Vec::new() }
22    }
23
24    pub fn is_bit_set(&self, bit: usize) -> bool {
25        let word_idx = bit / 32;
26        let bit_idx = bit % 32;
27        if word_idx >= self.words.len() {
28            return false;
29        }
30        (self.words[word_idx] & (1 << bit_idx)) != 0
31    }
32
33    pub fn set_bit(&mut self, bit: usize, on: bool) {
34        let word_idx = bit / 32;
35        let bit_idx = bit % 32;
36        while word_idx >= self.words.len() {
37            self.words.push(0);
38        }
39        if on {
40            self.words[word_idx] |= 1 << bit_idx;
41        } else {
42            self.words[word_idx] &= !(1 << bit_idx);
43        }
44    }
45
46    pub fn read(reader: &mut impl Read) -> Result<Self> {
47        let count = reader.read_u32()?;
48        let mut words = Vec::with_capacity(count as usize);
49        for _ in 0..count {
50            words.push(reader.read_u32()?);
51        }
52        Ok(Self { words })
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn test_empty() {
62        let bv = BitVector::new();
63        assert!(!bv.is_bit_set(0));
64        assert!(!bv.is_bit_set(100));
65    }
66
67    #[test]
68    fn test_set_get() {
69        let mut bv = BitVector::new();
70        bv.set_bit(5, true);
71        assert!(bv.is_bit_set(5));
72        assert!(!bv.is_bit_set(4));
73        bv.set_bit(33, true);
74        assert!(bv.is_bit_set(33));
75        assert_eq!(bv.words.len(), 2);
76    }
77
78    #[test]
79    fn test_read() {
80        use std::io::Cursor;
81        // 1 word, value = 0x00000005 (bits 0 and 2 set)
82        let data = [
83            0x01, 0x00, 0x00, 0x00, // count = 1
84            0x05, 0x00, 0x00, 0x00, // word = 5
85        ];
86        let mut cursor = Cursor::new(&data);
87        let bv = BitVector::read(&mut cursor).unwrap();
88        assert!(bv.is_bit_set(0));
89        assert!(!bv.is_bit_set(1));
90        assert!(bv.is_bit_set(2));
91    }
92}