aboutsummaryrefslogtreecommitdiff
path: root/src/bits.rs
blob: 0f944ca16b751171fc98143f36b1bd6a975f92a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#[derive(Clone)]
pub struct BitSet {
    pub data: Vec<u8>,
    pub len: usize,
}

impl BitSet {
    pub fn new() -> BitSet {
        BitSet { data: Vec::new(), len: 0 }
    }

    pub fn push_front_bit(&mut self, bit: u8) {
        if bit != 0 && bit != 1 {
            panic!("bit should be 1 or 0");
        }
        *self >>= 1;
        self.data[0] |= bit << 7;
    }

    fn shift_right_once(&mut self) {
        if self.len == self.data.len() * 8 {
            self.data.push(0);
        }
        for i in (1..self.data.len()).rev() {
            self.data[i] >>= 1;
            self.data[i] |= (self.data[i - 1] & 1) << 7;
        }
        self.data[0] >>= 1;
        self.len += 1;
    }

    pub fn concat(&mut self, other: &BitSet) {
        if self.len % 8 == 0 {
            self.data.extend(other.data.iter());
            self.len += other.len;
            return;
        }

        let mut other_mut = other.clone();
        let len_pre_shift = other_mut.len;
        other_mut >>= self.len % 8;
        *self.data.last_mut().unwrap() |= other_mut.data[0];
        self.data.extend(other_mut.data.iter().skip(1));
        self.len += len_pre_shift;
    }
}

use std::ops;

impl ops::ShrAssign<usize> for BitSet {
    fn shr_assign(&mut self, shift_size: usize) {
        for _ in 0..shift_size {
            self.shift_right_once();
        }
    }
}

use std::fmt;

impl fmt::Debug for BitSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "len: {:2} data: ", self.len)?;
        for chunk in &self.data {
            write!(f, "{:08b} ", chunk)?;
        }
        Ok(())
    }
}