mysqlbinlog_network/mysql_binlog/
bit_set.rs1use std::error::Error;
2use std::fmt;
3
4pub struct BitSet {
9 num_elems: usize,
10 inner: Vec<u8>,
11}
12
13impl fmt::Debug for BitSet {
14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15 write!(f, "BitSet {{ num_elems: {} }}", self.num_elems)
16 }
17}
18
19#[derive(Debug)]
20pub enum BitSetError {
21 ItemOutOfRange,
22 SliceTooSmall,
23}
24
25impl fmt::Display for BitSetError {
26 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
27 <Self as fmt::Debug>::fmt(self, f)
28 }
29}
30
31impl Error for BitSetError {
32 fn description(&self) -> &'static str {
33 "bitset error"
34 }
35}
36
37impl BitSet {
38 pub fn new(num_elems: usize) -> Self {
39 let vec_len = (num_elems + 7) >> 3;
40 BitSet {
41 num_elems,
42 inner: vec![0u8; vec_len],
43 }
44 }
45
46 pub fn from_slice(num_elems: usize, slice: &[u8]) -> Result<Self, BitSetError> {
47 let vec_len = (num_elems + 7) >> 3;
48 if slice.len() < vec_len {
49 return Err(BitSetError::SliceTooSmall);
50 }
51 Ok(BitSet {
52 num_elems,
53 inner: slice[0..vec_len].to_owned(),
54 })
55 }
56
57 fn get_byte_offset(&self, item: usize) -> usize {
58 if item >= self.num_elems {
59 panic!(
60 "attempted to index bit_set out of range: {} >= {}",
61 item, self.num_elems
62 );
63 }
64 item >> 3
65 }
66
67 pub fn set_value(&mut self, item: usize, value: bool) -> () {
68 let offset = self.get_byte_offset(item);
69 if value {
70 self.inner[offset] |= 1 << (item & 0x07);
71 } else {
72 self.inner[offset] &= !(1 << (item & 0x07));
73 }
74 ()
75 }
76
77 pub fn set(&mut self, item: usize) -> () {
78 self.set_value(item, true)
79 }
80
81 pub fn unset(&mut self, item: usize) -> () {
82 self.set_value(item, false)
83 }
84
85 pub fn is_set(&self, item: usize) -> bool {
86 let byte = self.inner[self.get_byte_offset(item)];
87 byte & (1 << (item & 0x07)) != 0
88 }
89
90 pub fn as_vec(&self) -> Vec<bool> {
91 let mut out = Vec::new();
92 for i in 0..self.num_elems {
93 out.push(self.is_set(i));
94 }
95 out
96 }
97
98 pub fn bits_set(&self) -> usize {
99 self.inner.iter().map(|c| c.count_ones() as usize).sum()
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::BitSet;
106
107 #[test]
108 fn test_basic() {
109 assert_eq!(BitSet::new(24).inner.len(), 3);
110 assert_eq!(BitSet::new(25).inner.len(), 4);
111 let mut b = BitSet::new(25);
112 for i in 0..25 {
113 assert!(!b.is_set(i));
114 }
115 b.set(0);
116 assert!(b.is_set(0));
117 for i in 1..25 {
118 assert!(!b.is_set(i));
119 }
120 b.set(20);
121 assert!(!b.is_set(19));
122 assert!(b.is_set(20));
123 assert!(!b.is_set(21));
124 assert_eq!(b.bits_set(), 2);
125 }
126
127 #[test]
128 fn test_from_slice() {
129 let b = BitSet::from_slice(9, &[255u8, 0u8]).expect("should construct");
130 assert!(b.is_set(0));
131 assert!(!b.is_set(8));
132 }
133}