ptero/
binary.rs

1use std::{convert::TryFrom, error::Error};
2use std::{fmt, vec::Vec};
3
4const MOST_SIGNIFICANT_BIT_PATTERN: u8 = 0b10000000;
5const CLEARED_PATTERN: u8 = 0b00000000;
6/// Type for representing a bit.
7#[derive(Debug, PartialOrd, PartialEq, Clone)]
8pub struct Bit(pub u8);
9
10/// Wrapper for `Vec<Bit>` used for implementing `From` trait.
11#[derive(Debug)]
12pub struct BitVec(Vec<Bit>);
13
14impl BitVec {
15    /// Constructs a BitVec of given `length` filled with `bit_val`.
16    ///
17    /// # Arguments
18    ///
19    /// * `bit_val` - value that will be set to the [Bit]
20    /// * `length` - length of the output vector
21    ///
22    /// # Examples
23    ///
24    /// ## Create a [BitVec] filled with 8 zero bits
25    /// ```
26    /// use ptero::binary::{Bit, BitVec};
27    ///
28    /// let vec: Vec<Bit> = BitVec::filled_with(0, 8).into();
29    /// assert_eq!(vec, &[Bit(0), Bit(0), Bit(0), Bit(0), Bit(0), Bit(0), Bit(0), Bit(0)]);    
30    /// ```
31    pub fn filled_with(bit_val: u8, length: usize) -> BitVec {
32        vec![bit_val]
33            .repeat(length)
34            .iter()
35            .map(|v| Bit(*v))
36            .collect::<Vec<Bit>>()
37            .into()
38    }
39}
40
41impl From<BitVec> for Vec<Bit> {
42    fn from(bit_vec: BitVec) -> Self {
43        bit_vec.0
44    }
45}
46
47impl From<Vec<Bit>> for BitVec {
48    fn from(bit_vec: Vec<Bit>) -> Self {
49        BitVec(bit_vec)
50    }
51}
52
53impl From<BitVec> for u32 {
54    /// Conversion implementation for `u32`.
55    /// Converts array of [Bits](Bit) to the corresponding number. The function
56    /// expects that the first element is the most significant bit.
57    ///
58    /// # Examples
59    ///
60    /// ## Convert 5 bits to number
61    /// ```
62    /// use ptero::binary::{Bit, BitVec};
63    ///
64    /// let array: BitVec = vec![1, 0, 1, 1, 1]
65    ///                         .iter()
66    ///                         .map(|v| Bit(*v))
67    ///                         .collect::<Vec<Bit>>()
68    ///                         .into();
69    /// let number: u32 = array.into();
70    /// assert_eq!(number, 23);
71    /// ```   
72    fn from(bit_vec: BitVec) -> Self {
73        let mut number: u32 = 0;
74        for bit in bit_vec.0.into_iter() {
75            number <<= 1;
76            number += u32::from(bit.0);
77        }
78        number
79    }
80}
81
82impl From<u32> for BitVec {
83    /// Conversion implementation for `u32`.
84    /// Converts `u32` number to the vector of [Bits](Bit).
85    /// The result vector has the most significant bit at the beginning.
86    ///
87    /// # Examples
88    ///
89    /// ## Convert the 65 number
90    /// ```
91    /// use ptero::binary::{Bit, BitVec};
92    ///
93    /// let array: BitVec = vec![1, 0, 1, 1, 1]
94    ///                         .iter()
95    ///                         .map(|v| Bit(*v))
96    ///                         .collect::<Vec<Bit>>()
97    ///                         .into();
98    /// let number: u32 = array.into();
99    /// assert_eq!(number, 23);
100    /// ```   
101    fn from(number: u32) -> Self {
102        let byte_array = [
103            ((number >> 24) & 0xff) as u8,
104            ((number >> 16) & 0xff) as u8,
105            ((number >> 8) & 0xff) as u8,
106            (number & 0xff) as u8,
107        ];
108        BitIterator::new(&byte_array).collect::<Vec<Bit>>().into()
109    }
110}
111
112impl TryFrom<BitVec> for Vec<u8> {
113    type Error = BinaryConversionError;
114
115    /// Tries to convert array of [Bits](Bit) to the array of bytes. The function
116    /// expects that each left most bit in byte-size boundary is the
117    /// most significant bit.
118    ///
119    /// # Arguments
120    ///
121    /// * `bits` - reference to array of bits `&[Bit]`
122    ///
123    /// # Behavior
124    ///
125    /// Function return [BinaryConversionError] when
126    /// array is not padded to byte-size boundary i.e. length to divisible by 8.
127    ///
128    /// # Examples
129    ///
130    /// ## Convert 16 bits to 2 bytes
131    /// ```
132    /// use ptero::binary::{Bit, BitVec, BinaryConversionError};
133    /// use std::convert::TryFrom;
134    ///
135    /// let array: BitVec = vec![0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1]
136    ///                             .iter()
137    ///                             .map(|v| Bit(*v))
138    ///                             .collect::<Vec<Bit>>()
139    ///                             .into();
140    /// let result: Result<Vec<u8>, BinaryConversionError> = TryFrom::try_from(array);
141    /// assert!(result.is_ok());
142    /// assert_eq!(result.unwrap(), vec![42, 129]);
143    /// ```      
144    ///
145    /// ## Return error if array is not in byte-size boundary
146    /// ```
147    /// use ptero::binary::{Bit, BinaryConversionError, BitVec};
148    /// use std::convert::TryFrom;
149    ///
150    /// let array: BitVec = vec![0, 0, 1]
151    ///                             .iter()
152    ///                             .map(|v| Bit(*v))
153    ///                             .collect::<Vec<Bit>>()
154    ///                             .into();
155    /// let result: Result<Vec<u8>, BinaryConversionError> = TryFrom::try_from(array);
156    /// assert!(!result.is_ok());
157    /// ```
158    fn try_from(bit_vec: BitVec) -> Result<Vec<u8>, Self::Error> {
159        let mut bytes = Vec::<u8>::default();
160        let mut index = 0;
161        if bit_vec.0.len() % 8 != 0 {
162            return Err(BinaryConversionError::new(
163                "Bit array length is not divisible by 8".to_string(),
164            ));
165        }
166        while index < bit_vec.0.len() {
167            let mut byte = 0;
168            for _ in 0..8 {
169                byte *= 2;
170                byte += bit_vec.0.get(index).unwrap().0;
171                index += 1;
172            }
173            bytes.push(byte);
174        }
175        Ok(bytes)
176    }
177}
178
179#[cfg(not(tarpaulin_include))]
180impl fmt::Display for Bit {
181    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
182        write!(f, "{}", self.0)
183    }
184}
185/// Error signaling binary conversion issues. Used in `From` trait implementation.
186#[derive(Debug, Clone)]
187pub struct BinaryConversionError {
188    message: String,
189}
190
191impl BinaryConversionError {
192    fn new(message: String) -> Self {
193        BinaryConversionError { message }
194    }
195}
196
197#[cfg(not(tarpaulin_include))]
198impl fmt::Display for BinaryConversionError {
199    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200        write!(f, "Binary conversion error")
201    }
202}
203
204impl Error for BinaryConversionError {}
205
206#[derive(Debug, Copy, Clone)]
207struct BinaryPattern(u8);
208
209impl BinaryPattern {
210    fn new() -> BinaryPattern {
211        BinaryPattern(MOST_SIGNIFICANT_BIT_PATTERN)
212    }
213
214    fn start(&mut self) {
215        self.0 = MOST_SIGNIFICANT_BIT_PATTERN;
216    }
217
218    fn is_cleared(&self) -> bool {
219        self.0 == CLEARED_PATTERN
220    }
221
222    fn shift(&mut self) {
223        self.0 >>= 1;
224    }
225
226    fn get(&self, byte: u8) -> Bit {
227        match byte & self.0 {
228            0 => Bit(0),
229            _ => Bit(1),
230        }
231    }
232}
233
234/// [Bit] sequence iterator.
235/// It enables user to read [Bits](Bit) from any iterator that provides bytes as `u8`.
236#[derive(Debug, Copy, Clone)]
237pub struct BitIterator<'a> {
238    bytes: &'a [u8],
239    index: usize,
240    fetch_pattern: BinaryPattern,
241}
242
243impl<'a> BitIterator<'a> {
244    /// Creates a [Bit] iterator for specified byte array.
245    ///
246    /// **Please note that it begins iteration from the MSB.**
247    ///
248    /// # Arguments
249    ///
250    /// * `array` - reference to array of bytes `&[u8]`
251    ///
252    /// # Examples
253    ///
254    /// ## Returns optional value
255    /// ```
256    /// use ptero::binary::{Bit, BitIterator};
257    ///
258    /// let array: Vec<u8> = vec!(1, 0, 2, 3);
259    /// let mut iterator = BitIterator::new(&array);
260    ///
261    /// let bit = iterator.next().unwrap();
262    /// let Bit(value) = bit;
263    /// assert_eq!(value, 0);
264    /// ```    
265    ///
266    /// ## Repeats itself after reaching the end
267    /// ```
268    /// use ptero::binary::{Bit, BitIterator};
269    ///
270    /// let array: Vec<u8> = vec!(0);
271    /// let mut iterator = BitIterator::new(&array);
272    ///
273    /// for v in &mut iterator {
274    ///     assert_eq!(v, Bit(0));
275    /// }
276    /// iterator.next();
277    /// for v in &mut iterator {
278    ///     assert_eq!(v, Bit(0));
279    /// }
280    /// ```    
281    ///
282    ///
283    pub fn new(array: &'a [u8]) -> Self {
284        // At the first execution we'll fetch the first value and then process it
285        BitIterator {
286            bytes: array,
287            index: 0,
288            fetch_pattern: BinaryPattern::new(),
289        }
290    }
291}
292
293impl<'a> Iterator for BitIterator<'a> {
294    type Item = Bit;
295
296    fn next(&mut self) -> Option<Self::Item> {
297        if self.fetch_pattern.is_cleared() {
298            self.fetch_pattern.start();
299            self.index += 1;
300        };
301        let byte = *self.bytes.get(self.index)?;
302        let bit = self.fetch_pattern.get(byte);
303        self.fetch_pattern.shift();
304        Some(bit)
305    }
306}