bloock_types/traits.rs
1use crate::error::TypeError;
2use std::cmp;
3use std::cmp::Ordering;
4use rand::Rng;
5
6
7/// Trait that manages bitwise comparison operations on the implemented type.
8///
9/// # How can I implement Bitwise?
10/// Bitwise requieres the methods get_bit, cmp_bits and get_first_different_bit
11/// to be implemented.
12/// ```
13/// use std::cmp;
14/// use std::cmp::Ordering;
15///
16/// pub trait Bitwise {
17/// fn get_bit(&self, bit: u16) -> bool;
18/// fn cmp_bits(a: &[u8], b: &[u8], from: &u16, to: &u16) -> Ordering;
19/// fn get_first_different_bit(a: &[u8], b: &[u8]) -> usize;
20/// }
21/// impl Bitwise for [u8] {
22/// fn get_bit(&self, bit: u16) -> bool {
23/// if (bit / 8) >= self.len() as u16 {
24/// panic!(
25/// "Overflow [get_bit({:?}, {:?})]: Bit must be lower than {:?}.",
26/// self,
27/// bit,
28/// self.len() * 8
29/// );
30/// }
31/// (self[bit as usize / 8] & (1 << (7 - (bit % 8)))) > 0
32/// }
33///
34/// fn cmp_bits(a: &[u8], b: &[u8], from: &u16, to: &u16) -> Ordering {
35/// for depth in *from..*to {
36/// if b.get_bit(depth) && !a.get_bit(depth) {
37/// return Ordering::Less;
38/// } else if !b.get_bit(depth) && a.get_bit(depth) {
39/// return Ordering::Greater;
40/// }
41/// }
42/// return Ordering::Equal;
43/// }
44///
45/// fn get_first_different_bit(a: &[u8], b: &[u8]) -> usize {
46/// let n = cmp::min(a.len(), b.len());
47/// let mut bit: usize = 0;
48///
49/// for i in 0..n {
50/// if a[i] != b[i] {
51/// let xor = a[i] ^ b[i];
52/// let lg_xor = 8 - xor.leading_zeros() - 1; // nbits - leading_zeros - 1 is equivalent to lg
53/// bit += 7 - (lg_xor as usize);
54/// return bit;
55/// }
56/// bit += 8;
57/// }
58/// bit
59/// }
60/// }
61/// ```
62pub trait Bitwise {
63 type Error;
64 /// Returns the bit at position `bit`.
65 ///
66 /// # Arguments
67 /// * `self` - The object we want to read from
68 /// * `bit` - An u16 representing the bit position to be read, being 0 the
69 /// the value of the highest bit in the first byte.
70 ///
71 /// # Panics
72 /// * If the `bit` value is higher than the object lenght.
73 ///
74 fn get_bit(&self, bit: u16) -> Result<bool, Self::Error>;
75
76 /// Returns the and Ordering indicating wether `self` bits in the interval [`from`, `to`) is Higher, Lower or Equal than `slice` bits in the same interval.
77 ///
78 /// # Arguments
79 /// * `a` - The object that's going to be compared.
80 /// * `b` - The object that's going to be compare against.
81 /// * `from` - The index of the first bit to be compared (inclusive).
82 /// * `to`- The index of the last bit to be compared (exclusive).
83 ///
84 /// # Panics
85 /// * If the `from` value is higher than the object length or than `to`.
86 /// * If the `to` value is higher than the object length or lower than `from`.
87 fn cmp_bits(a: &[u8], b: &[u8], from: &u16, to: &u16) -> Result<Ordering, Self::Error>;
88
89 /// Returns the index of the first different bit between `a` and `slice`.
90 ///
91 /// # Arguments
92 /// * `a` - The object that's going to be compared.
93 /// * `b` - The object that's going to be compare against.
94 fn get_first_different_bit(a: &[u8], b: &[u8]) -> usize;
95}
96
97/// Trait that manages the object creation for the implemented type with random values.
98pub trait Random {
99 /// Returns an object of the implemented type filled with random values.
100 fn random() -> Self;
101}
102
103impl Bitwise for [u8] {
104 type Error = TypeError;
105 fn get_bit(&self, bit: u16) -> Result<bool, Self::Error> {
106 if (bit / 8) >= self.len() as u16 {
107 return Err(TypeError::BitOverflow {
108 key: format!("{:?}", self),
109 bit,
110 maxbit: self.len() * 8usize,
111 });
112 }
113 Ok((self[bit as usize / 8] & (1 << (7 - (bit % 8)))) > 0)
114 }
115
116 fn cmp_bits(a: &[u8], b: &[u8], from: &u16, to: &u16) -> Result<Ordering, Self::Error> {
117 // s'ha de poder fer més eficient
118 for depth in *from..*to {
119 if b.get_bit(depth)? && !a.get_bit(depth)? {
120 return Ok(Ordering::Less);
121 } else if !b.get_bit(depth)? && a.get_bit(depth)? {
122 return Ok(Ordering::Greater);
123 }
124 }
125 Ok(Ordering::Equal)
126 }
127
128 fn get_first_different_bit(a: &[u8], b: &[u8]) -> usize {
129 let n = cmp::min(a.len(), b.len());
130 let mut bit: usize = 0;
131
132 for i in 0..n {
133 if a[i] != b[i] {
134 let xor = a[i] ^ b[i];
135 let lg_xor = 8 - xor.leading_zeros() - 1; // nbits - leading_zeros - 1 is equivalent to lg
136 bit += 7 - (lg_xor as usize);
137 return bit;
138 }
139 bit += 8;
140 }
141 bit
142 }
143}
144
145#[cfg(test)]
146mod tests {
147
148 use super::*;
149
150 #[test]
151 fn test_first_different_bit_first_byte_first_bit() {
152 let a: [u8; 1] = [128];
153 let b: [u8; 1] = [64];
154 assert_eq!(0, <[u8]>::get_first_different_bit(&a[..], &b[..]));
155 }
156
157 #[test]
158 fn test_first_different_bit_first_byte_last_bit() {
159 let a: [u8; 1] = [128];
160 let b: [u8; 1] = [129];
161 assert_eq!(7, <[u8]>::get_first_different_bit(&a[..], &b[..]));
162 }
163
164 #[test]
165 fn test_first_different_bit_second_byte_first_bit() {
166 let a: [u8; 2] = [0, 128];
167 let b: [u8; 2] = [0, 64];
168 assert_eq!(8, <[u8]>::get_first_different_bit(&a[..], &b[..]));
169 }
170
171 #[test]
172 fn test_first_different_bit_second_byte_last_bit() {
173 let a: [u8; 2] = [0, 128];
174 let b: [u8; 2] = [0, 129];
175 assert_eq!(15, <[u8]>::get_first_different_bit(&a[..], &b[..]));
176 }
177
178 #[test]
179 fn test_first_different_bit_different_lenghts() {
180 let a: [u8; 1] = [0];
181 let b: [u8; 2] = [0, 129];
182 assert_eq!(8, <[u8]>::get_first_different_bit(&a[..], &b[..]));
183 }
184
185 #[test]
186 fn test_first_different_bit_multiple_different_bytes() {
187 let a: [u8; 3] = [0, 128, 1];
188 let b: [u8; 3] = [0, 129, 255];
189 assert_eq!(15, <[u8]>::get_first_different_bit(&a[..], &b[..]));
190 }
191
192 #[test]
193 fn test_first_different_bit_distant_difference() {
194 let a: [u8; 32] = [
195 1, 4, 255, 4, 183, 75, 225, 169, 26, 216, 79, 149, 29, 195, 120, 173, 46, 167, 91, 31,
196 187, 141, 101, 53, 137, 34, 143, 106, 45, 167, 226, 120,
197 ];
198 let b: [u8; 32] = [
199 1, 4, 255, 4, 183, 75, 225, 169, 26, 216, 79, 149, 29, 195, 120, 173, 46, 167, 91, 31,
200 187, 141, 101, 53, 137, 34, 143, 106, 45, 167, 226, 121,
201 ];
202 assert_eq!(255, <[u8]>::get_first_different_bit(&a[..], &b[..]));
203 }
204
205 #[test]
206 fn test_get_bit_error() {
207 let a: [u8; 1] = [8u8];
208 assert_eq!(
209 a.get_bit(8).err().unwrap(),
210 TypeError::BitOverflow {
211 key: format!("{:?}", [8u8]),
212 bit: 8,
213 maxbit: 8
214 },
215 "Error types differ"
216 );
217 }
218}