1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
//! Crate for manipulating bit vectors and doing arithmetic on arbitrarily sized bit vectors. //! //! This crate emphasizes optimizing storage by providing alternative storage options. //! The module [`fixed`] contains implementations using unsigned integers as storage and thus //! has a fixed capacity. The module [`dynamic`] contains an implementation using dynamically //! allocated array of integers as storage and therefore has a dynamic capacity. The module //! [`auto`] contains an implementation capable of switching at runtime between a fixed or //! dynamic capacity implementation to try to minimize dynamic memory allocations. //! All of those implementations implement the [`BitVector`] trait and can be freely mixed together //! and converted into each other. //! //! The different bit vector types represent a vector of bits where the bit at index 0 is the least //! significant bit and the bit at index `.len() - 1` is the most significant bit. There is no //! notion of endianness for the bit vector themselves, endianness is only involved when reading or //! writing a bit vector to or from memory or storage. //! //! Arithmetic operation can be applied to bit vectors of different length. The result will always //! have the length of the longest operand and the smallest operand will be zero extended for the //! operation. This should match the most intuitive behavior in most cases except when manipulating //! bit vector supposed to have a sign bit. use std::fmt::{Binary, Display, Debug, LowerHex, UpperHex}; use std::io::{Read, Write}; use std::ops::Range; pub mod bit; pub mod fixed; pub mod dynamic; pub mod auto; use bit::Bit; /// A enumeration representing the endianness of an I/O or memory operation. pub enum Endianness { /// Little Endian ordering: bytes are stored from the least significant byte to the most significant byte. LE, /// big Endian ordering: bytes are stored from the most significant byte to the least significant byte. BE } /// A trait representing common bit vector operations. pub trait BitVector: Sized + Clone + Debug + PartialEq + Eq + Display + Binary + LowerHex + UpperHex { /// Construct a bit vector made of `length` 0 bits. /// Will panic if there is not enough capacity and it is a fixed variant. fn zeros(length: usize) -> Self; /// Construct a bit vector made of `length` 1 bits. /// Will panic if there is not enough capacity and it is a fixed variant. fn ones(length: usize) -> Self; /// Construct a bit vector from a binary string made of `'0'` and `'1'`. /// Return `None` if the string is invalid or exceed the maximum capacity. fn from_binary<S: AsRef<str>>(string: S) -> Option<Self>; /// Construct a bit vector from a hex string made of lower case or upper case hexadecimal /// characters (mixed case is accepted). /// Return `None` if the string is invalid or exceed the maximum capacity. fn from_hex<S: AsRef<str>>(string: S) -> Option<Self>; /// Construct a bit vector from `bytes` according to the specified `endianness`. /// Will panic if the length of `bytes` is larger than the maximum capacity. fn from_bytes<B: AsRef<[u8]>>(bytes: B, endianness: Endianness) -> Self; /// Construct a new vector of bytes from the bit vector according to the specified `endianness`. /// If the length is not a multiple of 8 bits, he highest weight bits will be padded with `'0'`. fn to_vec(&self, endianness: Endianness) -> Vec<u8>; /// Construct a bit vector by reading `length` bits from a type implementing `Read` and /// arrange them according to the specified `endianness`. If `length` is not a multiple of 8, /// the bits remaining in the most signigicant byte will be dropped. /// Will panic if there is not enough capacity and it is a fixed variant. fn read<R: Read>(reader: &mut R, length: usize, endianness: Endianness) -> std::io::Result<Self>; /// Write the bit vector to a type implementing `Write` and according to the specified /// `endianness`. If the length is not a multiple of 8 bits, the most significant byte will be /// padded with `'0'`. fn write<W: Write>(&self, writer: &mut W, endianness: Endianness) -> std::io::Result<()>; /// Return the bit at `index`. /// Will panic if `index` is out of bound. fn get(&self, index: usize) -> Bit; /// Set the bit at `index`. /// Will panic if `index` is out of bound. fn set(&mut self, index: usize, bit: Bit); /// Slice the bit vector using the specified range and copy those bits in a new bit vector. /// Will panic if `range` start or end are out of bound. fn copy_slice(&self, range: Range<usize>) -> Self; /// Push a bit at the end of the bit vector as the most significant bit. /// Will panic if there is not enough capacity and it is a fixed variant. fn push(&mut self, bit: Bit); /// Pop a bit from the end of the bit vector. /// Return None if the bit vector is empty. fn pop(&mut self) -> Option<Bit>; /// Resize the bit vector in place so that its length is equal to `new_length`. /// This will either truncate or extend the bit vector. If it is extended, new bits are filled /// with `bit`. /// Will panic if there is not enough capacity and it is a fixed variant. fn resize(&mut self, new_length: usize, bit: Bit); /// Shift the bits by one to the left. /// The rightmost bit is set to `bit` and the leftmost bit is returned. fn shl_in(&mut self, bit: Bit) -> Bit; /// Shift the bits by one to the right. /// The leftmost bit is set to `bit` and the rightmost bit is returned. fn shr_in(&mut self, bit: Bit) -> Bit; // Rotate the bits to the left by `rot` positions. // Will panic if the rotation amount is larger than this bit vector length. fn rotl(&mut self, rot: usize); // Rotate the bits to the right by `rot` positions. // Will panic if the rotation amount is larger than this bit vector length. fn rotr(&mut self, rot: usize); /// Return the length of the bit vector in bits. fn len(&self) -> usize; } #[cfg(test)] mod tests;