ps_buffer/implementations/
bitwise.rs

1use std::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
2
3// Macro for element-wise bitwise operations with &[u8]
4macro_rules! impl_bitwise_op_slice {
5    ($trait:ident, $method:ident, $op:tt) => {
6        impl $trait<&[u8]> for crate::Buffer {
7            fn $method(&mut self, rhs: &[u8]) {
8                let len = self.len().min(rhs.len());
9                for i in 0..len {
10                    (*self)[i] $op rhs[i];
11                }
12            }
13        }
14    };
15}
16
17// Macro for bitwise operations with u8
18macro_rules! impl_bitwise_op_u8 {
19    ($trait:ident, $method:ident, $op:tt) => {
20        impl $trait<u8> for crate::Buffer {
21            fn $method(&mut self, rhs: u8) {
22                for byte in self.iter_mut() {
23                    *byte $op rhs;
24                }
25            }
26        }
27    };
28}
29
30// Macro for bitwise operations with &u8
31macro_rules! impl_bitwise_op_ref_u8 {
32    ($trait:ident, $method:ident, $op:tt) => {
33        impl $trait<&u8> for crate::Buffer {
34            fn $method(&mut self, rhs: &u8) {
35                for byte in self.iter_mut() {
36                    *byte $op *rhs;
37                }
38            }
39        }
40    };
41}
42
43// Bitwise operations
44impl_bitwise_op_slice!(BitAndAssign, bitand_assign, &=);
45impl_bitwise_op_slice!(BitOrAssign, bitor_assign, |=);
46impl_bitwise_op_slice!(BitXorAssign, bitxor_assign, ^=);
47
48impl_bitwise_op_u8!(BitAndAssign, bitand_assign, &=);
49impl_bitwise_op_u8!(BitOrAssign, bitor_assign, |=);
50impl_bitwise_op_u8!(BitXorAssign, bitxor_assign, ^=);
51
52impl_bitwise_op_ref_u8!(BitAndAssign, bitand_assign, &=);
53impl_bitwise_op_ref_u8!(BitOrAssign, bitor_assign, |=);
54impl_bitwise_op_ref_u8!(BitXorAssign, bitxor_assign, ^=);
55
56// Shift operations for u8 only
57impl ShlAssign<u8> for crate::Buffer {
58    fn shl_assign(&mut self, rhs: u8) {
59        for byte in self.iter_mut() {
60            *byte <<= rhs;
61        }
62    }
63}
64
65impl ShrAssign<u8> for crate::Buffer {
66    fn shr_assign(&mut self, rhs: u8) {
67        for byte in self.iter_mut() {
68            *byte >>= rhs;
69        }
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    #[test]
76    fn test_bitand_assign_slice() -> Result<(), crate::BufferError> {
77        let mut buf = crate::Buffer::from_slice([0b1010, 0b1100])?;
78        let rhs = [0b1100, 0b1010];
79        buf &= &rhs[..];
80        assert_eq!(&*buf, &[0b1000, 0b1000]);
81        Ok(())
82    }
83
84    #[test]
85    fn test_bitand_assign_u8() -> Result<(), crate::BufferError> {
86        let mut buf = crate::Buffer::from_slice([0b1010, 0b1100])?;
87        buf &= 0b1100u8;
88        assert_eq!(&*buf, &[0b1000, 0b1100]);
89        Ok(())
90    }
91
92    #[test]
93    fn test_bitand_assign_ref_u8() -> Result<(), crate::BufferError> {
94        let mut buf = crate::Buffer::from_slice([0b1010, 0b1100])?;
95        buf &= &0b1100u8;
96        assert_eq!(&*buf, &[0b1000, 0b1100]);
97        Ok(())
98    }
99
100    #[test]
101    fn test_bitor_assign_slice() -> Result<(), crate::BufferError> {
102        let mut buf = crate::Buffer::from_slice([0b1010, 0b1100])?;
103        let rhs = [0b1100, 0b1010];
104        buf |= &rhs[..];
105        assert_eq!(&*buf, &[0b1110, 0b1110]);
106        Ok(())
107    }
108
109    #[test]
110    fn test_bitor_assign_u8() -> Result<(), crate::BufferError> {
111        let mut buf = crate::Buffer::from_slice([0b1010, 0b1100])?;
112        buf |= 0b1010u8;
113        assert_eq!(&*buf, &[0b1010, 0b1110]);
114        Ok(())
115    }
116
117    #[test]
118    fn test_bitor_assign_ref_u8() -> Result<(), crate::BufferError> {
119        let mut buf = crate::Buffer::from_slice([0b1010, 0b1100])?;
120        buf |= &0b1010u8;
121        assert_eq!(&*buf, &[0b1010, 0b1110]);
122        Ok(())
123    }
124
125    #[test]
126    fn test_bitxor_assign_slice() -> Result<(), crate::BufferError> {
127        let mut buf = crate::Buffer::from_slice([0b1010, 0b1100])?;
128        let rhs = [0b1100, 0b1010];
129        buf ^= &rhs[..];
130        assert_eq!(&*buf, &[0b0110, 0b0110]);
131        Ok(())
132    }
133
134    #[test]
135    fn test_bitxor_assign_u8() -> Result<(), crate::BufferError> {
136        let mut buf = crate::Buffer::from_slice([0b1010, 0b1100])?;
137        buf ^= 0b1111u8;
138        assert_eq!(&*buf, &[0b0101, 0b0011]);
139        Ok(())
140    }
141
142    #[test]
143    fn test_bitxor_assign_ref_u8() -> Result<(), crate::BufferError> {
144        let mut buf = crate::Buffer::from_slice([0b1010, 0b1100])?;
145        buf ^= &0b1111u8;
146        assert_eq!(&*buf, &[0b0101, 0b0011]);
147        Ok(())
148    }
149
150    #[test]
151    fn test_shl_assign_u8() -> Result<(), crate::BufferError> {
152        let mut buf = crate::Buffer::from_slice([1, 2, 3])?;
153        buf <<= 2u8;
154        assert_eq!(&*buf, &[4, 8, 12]);
155        Ok(())
156    }
157
158    #[test]
159    fn test_shr_assign_u8() -> Result<(), crate::BufferError> {
160        let mut buf = crate::Buffer::from_slice([4, 8, 12])?;
161        buf >>= 2u8;
162        assert_eq!(&*buf, &[1, 2, 3]);
163        Ok(())
164    }
165
166    #[test]
167    fn test_different_lengths_slice() -> Result<(), crate::BufferError> {
168        let mut buf = crate::Buffer::from_slice([0b1010, 0b1100, 0b1111])?;
169        let rhs = [0b1100, 0b1010];
170        buf &= &rhs[..];
171        assert_eq!(&*buf, &[0b1000, 0b1000, 0b1111]);
172        Ok(())
173    }
174}