to_binary/
lib.rs

1
2/// # To-Binary: A Binary String Conversion Library
3/// There are two types of Binary Strings that are present:
4/// - "Binary String (0bString)"
5/// - "Binary Whitespace String (0bWString)"
6///
7// TODO| Use ByteOrder
8use hex::FromHexError;
9use std::fmt;
10
11
12/// # `BinaryString` Error-Handling
13/// This is a enum that is used specifically for **Error-Handling**
14#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Hash)]
15pub enum BinaryError {
16    InvalidCharacters,
17    AlreadyHasWhitespace,
18    InvalidByteSize,
19    UnknownError,
20}
21
22/// # BinaryString (`0bString` + `0bWString`)
23/// This Struct is the Main Struct for Dealing with **Binary Strings** and **Binary Whitespace Strings**.
24///
25/// It is a **Tuple Struct** that only has a **Single, Public Field** which is a `String` and can be accessed with `self.0`.
26///
27/// ## How To Access The `String` Field
28/// ```
29/// use to_binary::BinaryString;
30///
31/// // Generate Binary String From &str
32/// let x = BinaryString::from("Hello");
33///
34/// // Access The Public "String" Field And Assign It To bin_string using field
35/// let bin_string: String = x.0;
36///
37/// // Print Out Information
38/// println!("{}",bin_string);
39/// ```
40#[derive(Clone, Debug, PartialEq, PartialOrd, Hash, Default)]
41pub struct BinaryString(pub String);
42
43/// # Binary Usage
44/// The `BinaryUsage` Struct is used to perform functions or actions on `Binary Strings`, such as:
45///
46/// - Adding/Removing Whitespace
47/// - Asserting Binary Strings
48/// - Asserting Binary Whitespace Strings
49/// - Asserting Bytes
50/// - Counting Bits
51/// - Counting Bytes
52#[deprecated]
53pub struct BinaryUsage;
54
55// &str
56impl From<&str> for BinaryString {
57    fn from(n: &str) -> Self {
58        let bytes = n.as_bytes();
59
60        let mut bin_string: String = String::new();
61
62        for byte in bytes {
63            bin_string.push_str(&format!("{:08b}", byte));
64        }
65        return BinaryString(bin_string);
66    }
67}
68// String
69impl From<String> for BinaryString {
70    fn from(n: String) -> Self {
71        // Get Vector of Bytes From String
72        let bytes: Vec<u8> = n.into_bytes();
73
74        // Init a Binary String
75        let mut bin_string: String = String::new();
76
77        for byte in bytes {
78            bin_string.push_str(&format!("{:08b}", byte));
79        }
80        return BinaryString(bin_string);
81    }
82}
83// u8 slice
84impl From<&[u8]> for BinaryString {
85    fn from(byte_slice: &[u8]) -> Self {
86        let bytes: Vec<u8> = byte_slice.to_vec();
87
88        let mut bin_string: String = String::new();
89
90        for byte in bytes {
91            bin_string.push_str(&format!("{:08b}", byte));
92        }
93        return BinaryString(bin_string);
94    }
95}
96// u8 array of 32
97impl From<[u8; 32]> for BinaryString {
98    fn from(array: [u8; 32]) -> Self {
99        let mut bin_string: String = String::new();
100
101        for byte in &array {
102            bin_string.push_str(&format!("{:08b}", byte));
103        }
104        return BinaryString(bin_string);
105    }
106}
107// u8 vector
108impl From<Vec<u8>> for BinaryString {
109    fn from(bytes: Vec<u8>) -> BinaryString {
110        let mut bin_string: String = String::new();
111
112        for byte in bytes {
113            bin_string.push_str(&format!("{:08b}", byte));
114        }
115        return BinaryString(bin_string);
116    }
117}
118// u8 byte
119impl From<u8> for BinaryString {
120    fn from(byte: u8) -> BinaryString {
121        let mut bin_string: String = String::new();
122        
123        bin_string.push_str(&format!("{:08b}", byte));
124        return BinaryString(bin_string);
125    }
126}
127
128// Other Conversions
129impl BinaryString {
130    /// Takes as input hexadecimal and outputs a Result containing a `BinaryString` and on Error, `FromHexError`
131    pub fn from_hex<T: AsRef<[u8]>>(n: T) -> Result<BinaryString, FromHexError> {
132        // Decode as Hexadecimal and Unwrap
133        let bytes: Vec<u8> = hex::decode(n).unwrap();
134
135        // Init a Binary String
136        let mut bin_string: String = String::new();
137
138        for byte in bytes {
139            bin_string.push_str(&format!("{:08b}", byte));
140        }
141        return Ok(BinaryString(bin_string));
142    }
143}
144
145impl fmt::Display for BinaryString {
146    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147        write!(f, "{}", self.0)
148    }
149}
150
151impl BinaryString {
152    /// Asserts The Input Is A `Binary String`, or a string with only:
153    ///
154    /// - `0`
155    /// - `1`
156    ///
157    /// This function is the same as `assert_binary_string()` just with a different name
158    pub fn assert_binary(&self) -> bool {
159        for x in self.0.chars() {
160            if x == '0' || x == '1' {
161            } else {
162                return false;
163            }
164        }
165        return true;
166    }
167    /// Asserts the Input Is A `Binary String`, or a String with only:
168    /// - `0`
169    /// - `1`
170    /// - No Whitespace
171    pub fn assert_binary_string(&self) -> bool {
172        for x in self.0.chars() {
173            if x == '0' || x == '1' {
174            } else {
175                return false;
176            }
177        }
178        return true;
179    }
180    /// Asserts The Input Is A `Binary Whitespace String`, or a String with only:
181    /// - `0`
182    /// - `1`
183    /// - `whitespace`
184    ///
185    /// TODO: Add a check for whitespace to be every 8th character
186    pub fn assert_binary_whitespace(&self) -> bool {
187        for x in self.0.chars() {
188            if x == '0' || x == '1' || x == ' ' {
189            } else {
190                return false;
191            }
192        }
193        return true;
194    }
195    /// Asserts The Input Has (`8` * `n`) bits or contains full bytes using the remainder function
196    ///
197    /// This function calls the `bits()` method to retrieve the number of bits then does operation `%` 8 and compares it against 0
198    pub fn assert_bytes(&self) -> bool {
199        if self.bits().unwrap() % 8usize == 0usize {
200            return true;
201        } else {
202            return false;
203        }
204    }
205    /// Asserts The Number of Bits In The String
206    ///
207    /// The function `bits()` is called to compare to the parameter
208    pub fn assert_bit_length(&self, len: usize) -> bool {
209        if self.bits().unwrap() == len {
210            return true;
211        } else {
212            return false;
213        }
214    }
215    /// Asserts The Number of Bytes In The String
216    ///
217    /// The function `bytes()` is called to compare to the parameter
218    pub fn assert_byte_length(&self, len: usize) -> bool {
219        if self.bytes().unwrap() == len {
220            return true;
221        } else {
222            return false;
223        }
224    }
225    /// Count number of bits for both a "Binary String" and "Binary Whitespace String" and returns a Result of either a `usize` or a `BinaryError`
226    pub fn bits(&self) -> Result<usize, BinaryError> {
227        if self.assert_binary_string() == true {
228            return Ok(self.0.len());
229        } else if self.assert_binary_whitespace() == true {
230            let no_spaces = self.remove_spaces();
231            return Ok(no_spaces.0.len());
232        } else {
233            return Err(BinaryError::InvalidCharacters);
234        }
235    }
236    /// Count number of bytes for both a "Binary String" and "Binary Whitespace String" and returns a Result of either a `usize` or on error, empty response
237    pub fn bytes(&self) -> Result<usize, BinaryError> {
238        if self.assert_bytes() == true {
239            return Ok(self.bits().unwrap() / 8usize);
240        } else if self.assert_bytes() == false {
241            return Err(BinaryError::InvalidByteSize);
242        } else {
243            Err(BinaryError::UnknownError)
244        }
245    }
246    /// Removes All Whitespace From Binary String And Returns A `BinaryString`
247    pub fn remove_spaces(&self) -> BinaryString {
248        BinaryString(self.0.chars().filter(|c| !c.is_whitespace()).collect())
249    }
250    /// Adds Whitespace Between Every **Byte** (8 bits)
251    /// 
252    /// ## Example Usage
253    /// ```
254    /// // Imports
255    /// use to_binary::{BinaryString,BinaryError};
256    /// 
257    /// // Generate `BinaryString` from &str "Test String"
258    /// let x = BinaryString::from("Test String");
259    /// 
260    /// // Returns a `BinaryString` With Spaces Between Every Byte (8 bits)
261    /// let bin_with_spaces = x.add_spaces().unwrap();
262    /// 
263    /// ```
264    pub fn add_spaces(&self) -> Result<BinaryString, BinaryError> {
265        // Checks to See If Its A Binary String (0bString)
266        if self.assert_binary_string() == true && self.assert_bytes() {
267            // Init Binary String With Spaces
268            let mut binary_string_with_spaces = self.0.clone();
269
270            // Get Byte Count
271            let bytes_to_index: usize = self.bytes().unwrap() - 1usize;
272
273            // Start Index Counter at 8
274            let mut counter: usize = 8;
275
276            // Add Spaces At Index 8 + (9 * (bytes - 1))
277            for _ in 0..bytes_to_index {
278                binary_string_with_spaces.insert(counter, ' ');
279                counter = counter + 9usize;
280            }
281
282            return Ok(BinaryString(binary_string_with_spaces));
283        } else if self.assert_binary_whitespace() == true {
284            return Err(BinaryError::AlreadyHasWhitespace);
285        } else {
286            Err(BinaryError::InvalidCharacters)
287        }
288    }
289}
290
291// Keep For Now
292#[allow(deprecated)]
293impl BinaryUsage {
294    /// Asserts The Input Is A `Binary String`, or a string with only:
295    ///
296    /// - `0`
297    /// - `1`
298    ///
299    /// This function is the same as `assert_binary_string()` just with a different name
300    pub fn assert_binary(bin: String) -> bool {
301        for x in bin.chars() {
302            if x == '0' || x == '1' {
303            } else {
304                return false;
305            }
306        }
307        return true;
308    }
309    /// Asserts the Input Is A `Binary String`, or a String with only:
310    /// - `0`
311    /// - `1`
312    /// - No Whitespace
313    pub fn assert_binary_string(bin: String) -> bool {
314        for x in bin.chars() {
315            if x == '0' || x == '1' {
316            } else {
317                return false;
318            }
319        }
320        return true;
321    }
322    /// Asserts The Input Is A `Binary Whitespace String`, or a String with only:
323    /// - `0`
324    /// - `1`
325    /// - `whitespace`
326    ///
327    /// TODO: Add a check for whitespace to be every 9nth character
328    pub fn assert_binary_whitespace(bin: String) -> bool {
329        for x in bin.chars() {
330            if x == '0' || x == '1' || x == ' ' {
331            } else {
332                return false;
333            }
334        }
335        return true;
336    }
337    /// Asserts The Input Has (`8` * `n`) bits or contains full bytes using the remainder function
338    pub fn assert_bytes(bin: String) -> bool {
339        if BinaryUsage::count_bits(bin).unwrap() % 8usize == 0usize {
340            return true;
341        } else {
342            return false;
343        }
344    }
345    /// Count number of bits for both a "Binary String" and "Binary Whitespace String" and returns a Result of either a `usize` or on error, empty response
346    pub fn count_bits(bin: String) -> Result<usize, ()> {
347        if BinaryUsage::assert_binary_string(bin.clone()) == true {
348            return Ok(bin.len());
349        } else if BinaryUsage::assert_binary_whitespace(bin.clone()) == true {
350            return Ok(BinaryUsage::remove_spaces(bin).len());
351        } else {
352            return Err(());
353        }
354    }
355    /// Count number of bytes for both a "Binary String" and "Binary Whitespace String" and returns a Result of either a `usize` or on error, empty response
356    pub fn count_bytes(bin: String) -> Result<usize, ()> {
357        if BinaryUsage::assert_bytes(bin.clone()) == true {
358            return Ok(BinaryUsage::count_bits(bin).unwrap() / 8usize);
359        } else {
360            Err(())
361        }
362    }
363    pub fn add_spaces(bin: String) -> Result<String, ()> {
364        // Checks to See If Its A Binary String (0bString)
365        if BinaryUsage::assert_binary_string(bin.clone()) == true
366            && BinaryUsage::assert_bytes(bin.clone())
367        {
368            // Init Binary String With Spaces
369            let mut binary_string_with_spaces = bin.clone();
370
371            // Get Byte Count
372            let bytes_to_index: usize = BinaryUsage::count_bytes(bin).unwrap() - 1usize;
373
374            // Start Index Counter
375            let mut counter: usize = 8;
376
377            // Add Spaces At Index 8 + (9 * (bytes - 1))
378            for _ in 0..bytes_to_index {
379                binary_string_with_spaces.insert(counter, ' ');
380                counter = counter + 9usize;
381            }
382            return Ok(binary_string_with_spaces);
383        } else if BinaryUsage::assert_binary_whitespace(bin.clone()) == true {
384            return Ok(bin);
385        } else {
386            Err(())
387        }
388    }
389    /// Removes All Whitespace From String And Returns String
390    pub fn remove_spaces(bin: String) -> String {
391        bin.chars().filter(|c| !c.is_whitespace()).collect()
392    }
393}