nostd_bv/traits/
bits_mut_ext.rs1use super::{Bits, BitsMut};
2use crate::BlockType;
3
4pub trait BitsMutExt: BitsMut {
6 fn bit_assign<T: Bits<Block = Self::Block>>(&mut self, other: T) {
12 assert_eq!(
13 self.bit_len(),
14 other.bit_len(),
15 "BitsMutExt::bit_assign: arguments have different lengths"
16 );
17
18 let bit_len = self.bit_len();
19 let full_blocks = Self::Block::div_nbits(bit_len);
20 let extra_bits = Self::Block::mod_nbits(bit_len);
21
22 for i in 0..full_blocks {
23 let block = other.get_raw_block(i);
24 self.set_block(i, block);
25 }
26
27 if extra_bits > 0 {
28 let block = other.get_raw_block(full_blocks);
29 self.set_bits(bit_len - extra_bits as u64, extra_bits, block);
30 }
31 }
32
33 fn bit_and_assign<T: Bits<Block = Self::Block>>(&mut self, other: T) {
39 self.bit_zip_assign(other, |b1, b2| b1 & b2);
40 }
41
42 fn bit_or_assign<T: Bits<Block = Self::Block>>(&mut self, other: T) {
48 self.bit_zip_assign(other, |b1, b2| b1 | b2);
49 }
50
51 fn bit_xor_assign<T: Bits<Block = Self::Block>>(&mut self, other: T) {
57 self.bit_zip_assign(other, |b1, b2| b1 ^ b2);
58 }
59
60 fn bit_zip_assign<T, F>(&mut self, other: T, mut fun: F)
70 where
71 T: Bits<Block = Self::Block>,
72 F: FnMut(Self::Block, Self::Block) -> Self::Block,
73 {
74 assert_eq!(
75 self.bit_len(),
76 other.bit_len(),
77 "BitsMutExt::bit_zip_assign: arguments have different lengths"
78 );
79
80 let bit_len = self.bit_len();
81 let full_blocks = Self::Block::div_nbits(bit_len);
82 let extra_bits = Self::Block::mod_nbits(bit_len);
83
84 for i in 0..full_blocks {
85 let self_block = self.get_raw_block(i);
86 let other_block = other.get_raw_block(i);
87 let combined_block = fun(self_block, other_block);
88 self.set_block(i, combined_block);
89 }
90
91 if extra_bits > 0 {
92 let self_block = self.get_block(full_blocks);
93 let other_block = other.get_block(full_blocks);
94 let combined_block = fun(self_block, other_block);
95 self.set_bits(bit_len - extra_bits as u64, extra_bits, combined_block);
96 }
97 }
98}
99
100impl<T: BitsMut> BitsMutExt for T {}
101
102#[cfg(test)]
103mod test {
104 use super::*;
105 use crate::{BitSliceable, BitSliceableMut, BitVec};
106 use alloc::vec;
107
108 #[test]
109 fn bit_and_assign() {
110 let mut bv1: BitVec = bit_vec![false, false, true, true];
111 let bv2: BitVec = bit_vec![false, true, true, false];
112
113 bv1.bit_and_assign(&bv2);
114 assert_eq!(bv1, bit_vec![false, false, true, false]);
115 }
116
117 #[test]
118 #[should_panic]
119 fn bit_and_assign_bad_sizes() {
120 let mut bv1: BitVec = bit_vec![false, false, true, true, true];
121 let bv2: BitVec = bit_vec![false, true, true, false];
122
123 bv1.bit_and_assign(&bv2);
124 }
125
126 #[test]
127 fn bit_xor_assign_slice() {
128 let mut v1 = vec![0b0000_1111_u8];
129 let v2 = [0b0101_0101_u8];
130
131 v1.bit_slice_mut(2..6).bit_xor_assign(v2.bit_slice(3..7));
132
133 assert_eq!(v1, vec![0b00100111])
134 }
135}