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}