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 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}