brdb/wrapper/
bits.rs

1use crate::{
2    errors::BrdbSchemaError,
3    schema::{
4        BrdbValue,
5        as_brdb::{AsBrdbIter, AsBrdbValue, BrdbArrayIter},
6    },
7};
8
9#[derive(Default, Debug, Clone, PartialEq, PartialOrd)]
10pub struct BitFlags {
11    vec: Vec<u8>,
12    bits: usize,
13}
14
15impl BitFlags {
16    pub fn new(bits: usize) -> Self {
17        Self {
18            vec: vec![0; (bits + 7) / 8],
19            bits,
20        }
21    }
22
23    pub fn new_full(bits: usize) -> Self {
24        let mut vec = vec![0xFF; (bits + 7) / 8];
25        if bits % 8 != 0 {
26            let last_byte = vec.len() - 1;
27            let mask = (1 << (bits % 8)) - 1;
28            vec[last_byte] &= mask;
29        }
30        Self { vec, bits }
31    }
32
33    pub fn get_from_brdb_array(vec: &BrdbValue, bit: usize) -> Result<bool, BrdbSchemaError> {
34        let byte = vec
35            .index(bit / 8)?
36            .map(|v| v.as_brdb_u8())
37            .transpose()?
38            .unwrap_or_default();
39        let mask = 1 << (bit & 7);
40        Ok(byte & mask > 0)
41    }
42
43    pub fn get_from_vec(vec: &[u8], bit: usize) -> bool {
44        let byte = vec.as_ref().get(bit / 8).map(|v| *v).unwrap_or_default();
45        let mask = 1 << (bit & 7);
46        byte & mask > 0
47    }
48
49    pub fn get(&self, bit: usize) -> bool {
50        Self::get_from_vec(&self.vec, bit)
51    }
52
53    pub fn set(&mut self, bit: usize, val: bool) {
54        let Some(byte) = self.vec.get_mut(bit / 8) else {
55            return;
56        };
57        let mask = 1 << (bit & 7);
58        if val {
59            *byte |= mask;
60        } else {
61            *byte &= !mask;
62        }
63    }
64
65    // Push a single bit value to the end of the vector.
66    pub fn push(&mut self, val: bool) {
67        if self.bits >= self.vec.len() * 8 {
68            self.vec.push(0);
69        }
70        self.set(self.bits, val);
71        self.bits += 1;
72    }
73}
74
75impl AsBrdbValue for BitFlags {
76    fn as_brdb_struct_prop_array(
77        &self,
78        _schema: &crate::schema::BrdbSchema,
79        _struct_name: crate::schema::BrdbInterned,
80        _prop_name: crate::schema::BrdbInterned,
81    ) -> Result<BrdbArrayIter, crate::errors::BrdbSchemaError> {
82        Ok(self.vec.as_brdb_iter())
83    }
84}
85
86impl TryFrom<&BrdbValue> for BitFlags {
87    type Error = crate::errors::BrdbSchemaError;
88
89    fn try_from(value: &BrdbValue) -> Result<Self, Self::Error> {
90        let vec: Vec<u8> = value.prop("Flags")?.try_into()?;
91        let len = vec.len();
92        Ok(Self { vec, bits: len * 8 })
93    }
94}