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}