bv/traits/
bits_mut_ext.rs

1use BlockType;
2use super::{Bits, BitsMut};
3
4/// Extension trait for mutable operations on bit slices.
5pub trait BitsMutExt: BitsMut {
6    /// Assigns the bits of `other` to `self`.
7    ///
8    /// # Panics
9    ///
10    /// If `self.bit_len() != other.bit_len()`.
11    fn bit_assign<T: Bits<Block = Self::Block>>(&mut self, other: T) {
12        assert_eq!( self.bit_len(), other.bit_len(),
13                    "BitsMutExt::bit_assign: arguments have different lengths" );
14
15        let bit_len     = self.bit_len();
16        let full_blocks = Self::Block::div_nbits(bit_len);
17        let extra_bits  = Self::Block::mod_nbits(bit_len);
18
19        for i in 0 .. full_blocks {
20            let block = other.get_raw_block(i);
21            self.set_block(i, block);
22        }
23
24        if extra_bits > 0 {
25            let block = other.get_raw_block(full_blocks);
26            self.set_bits(bit_len - extra_bits as u64, extra_bits, block);
27        }
28    }
29
30    /// Assigns the bit-wise *and* of `self` and `other` to `self`.
31    ///
32    /// # Panics
33    ///
34    /// If `self.bit_len() != other.bit_len()`.
35    fn bit_and_assign<T: Bits<Block = Self::Block>>(&mut self, other: T) {
36        self.bit_zip_assign(other, |b1, b2| b1 & b2);
37    }
38
39    /// Assigns the bit-wise *or* of `self` and `other` to `self`.
40    ///
41    /// # Panics
42    ///
43    /// If `self.bit_len() != other.bit_len()`.
44    fn bit_or_assign<T: Bits<Block = Self::Block>>(&mut self, other: T) {
45        self.bit_zip_assign(other, |b1, b2| b1 | b2);
46    }
47
48    /// Assigns the bit-wise *xor* of `self` and `other` to `self`.
49    ///
50    /// # Panics
51    ///
52    /// If `self.bit_len() != other.bit_len()`.
53    fn bit_xor_assign<T: Bits<Block = Self::Block>>(&mut self, other: T) {
54        self.bit_zip_assign(other, |b1, b2| b1 ^ b2);
55    }
56
57    /// Performs an op-assignment from `other` to `self`.
58    ///
59    /// In particular, the given function is used to combine each
60    /// block of `self` with a block of `other`, assigning the result
61    /// back to `self`.
62    ///
63    /// # Panics
64    ///
65    /// If `self.bit_len() != other.bit_len()`.
66    fn bit_zip_assign<T, F>(&mut self, other: T, mut fun: F)
67        where T: Bits<Block = Self::Block>,
68              F: FnMut(Self::Block, Self::Block) -> Self::Block {
69
70        assert_eq!( self.bit_len(), other.bit_len(),
71                    "BitsMutExt::bit_zip_assign: arguments have different lengths" );
72
73        let bit_len     = self.bit_len();
74        let full_blocks = Self::Block::div_nbits(bit_len);
75        let extra_bits  = Self::Block::mod_nbits(bit_len);
76
77        for i in 0 .. full_blocks {
78            let self_block = self.get_raw_block(i);
79            let other_block = other.get_raw_block(i);
80            let combined_block = fun(self_block, other_block);
81            self.set_block(i, combined_block);
82        }
83
84        if extra_bits > 0 {
85            let self_block = self.get_block(full_blocks);
86            let other_block = other.get_block(full_blocks);
87            let combined_block = fun(self_block, other_block);
88            self.set_bits(bit_len - extra_bits as u64, extra_bits, combined_block);
89        }
90    }
91}
92
93impl<T: BitsMut> BitsMutExt for T {}
94
95#[cfg(test)]
96mod test {
97    use {BitVec, BitSliceable, BitSliceableMut};
98    use super::*;
99
100    #[test]
101    fn bit_and_assign() {
102        let mut bv1: BitVec = bit_vec![false, false, true, true];
103        let     bv2: BitVec = bit_vec![false, true, true, false];
104
105        bv1.bit_and_assign(&bv2);
106        assert_eq!( bv1, bit_vec![false, false, true, false] );
107    }
108
109    #[test]
110    #[should_panic]
111    fn bit_and_assign_bad_sizes() {
112        let mut bv1: BitVec = bit_vec![false, false, true, true, true];
113        let     bv2: BitVec = bit_vec![false, true, true, false];
114
115        bv1.bit_and_assign(&bv2);
116    }
117
118    #[test]
119    fn bit_xor_assign_slice() {
120        let mut v1 = vec![0b00_0011_11u8];
121        let     v2 = [0b0_1010_101u8];
122
123        v1.bit_slice_mut(2..6)
124            .bit_xor_assign(v2.bit_slice(3..7));
125
126        assert_eq!(v1, vec![0b00100111])
127    }
128}