#![warn(missing_docs)]
#![allow(
clippy::suspicious_arithmetic_impl,
clippy::suspicious_op_assign_impl,
clippy::comparison_chain,
clippy::needless_range_loop
)]
use std::fmt::{Binary, Debug, Display, LowerHex, Octal, UpperHex};
use std::hash::Hash;
use std::io::{Read, Write};
use std::ops::Range;
mod auto;
mod bit;
mod dynamic;
mod fixed;
mod iter;
mod utils;
pub use auto::Bv;
pub use bit::Bit;
pub use dynamic::Bvd;
pub use fixed::{Bv128, Bv16, Bv192, Bv256, Bv32, Bv320, Bv384, Bv448, Bv512, Bv64, Bv8, Bvf};
pub use iter::BitIterator;
use utils::{IArray, IArrayMut};
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Endianness {
Little,
Big,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ConvertionError {
NotEnoughCapacity,
InvalidFormat(usize),
}
impl Display for ConvertionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ConvertionError::NotEnoughCapacity => write!(
f,
"The bit vector did not have enough capacity to perform the convertion"
),
ConvertionError::InvalidFormat(pos) => write!(
f,
"The bit vector convertion method encountered an error at index {}",
pos
),
}
}
}
impl std::error::Error for ConvertionError {}
pub trait BitVector:
Binary
+ Clone
+ Debug
+ Display
+ Eq
+ Hash
+ IArray
+ IArrayMut
+ LowerHex
+ Octal
+ Ord
+ PartialEq
+ PartialOrd
+ Sized
+ UpperHex
{
fn with_capacity(length: usize) -> Self;
fn zeros(length: usize) -> Self;
fn ones(length: usize) -> Self;
fn repeat(bit: Bit, length: usize) -> Self {
if bit == Bit::Zero {
Self::zeros(length)
} else {
Self::ones(length)
}
}
fn capacity(&self) -> usize;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn from_binary<S: AsRef<str>>(string: S) -> Result<Self, ConvertionError>;
fn from_hex<S: AsRef<str>>(string: S) -> Result<Self, ConvertionError>;
fn from_bytes<B: AsRef<[u8]>>(
bytes: B,
endianness: Endianness,
) -> Result<Self, ConvertionError>;
fn to_vec(&self, endianness: Endianness) -> Vec<u8>;
fn read<R: Read>(
reader: &mut R,
length: usize,
endianness: Endianness,
) -> std::io::Result<Self>;
fn write<W: Write>(&self, writer: &mut W, endianness: Endianness) -> std::io::Result<()>;
fn get(&self, index: usize) -> Bit;
fn set(&mut self, index: usize, bit: Bit);
fn first(&self) -> Option<Bit> {
if self.len() > 0 {
Some(self.get(0))
} else {
None
}
}
fn last(&self) -> Option<Bit> {
if self.len() > 0 {
Some(self.get(self.len() - 1))
} else {
None
}
}
fn copy_range(&self, range: Range<usize>) -> Self;
fn push(&mut self, bit: Bit);
fn pop(&mut self) -> Option<Bit>;
fn resize(&mut self, new_length: usize, bit: Bit);
fn sign_extend(&mut self, new_length: usize) {
if new_length > self.len() {
let sign = match self.len() {
0 => Bit::Zero,
l => self.get(l - 1),
};
self.resize(new_length, sign);
}
}
fn append<B: BitVector>(&mut self, suffix: &B);
fn prepend<B: BitVector>(&mut self, prefix: &B);
fn shl_in(&mut self, bit: Bit) -> Bit;
fn shr_in(&mut self, bit: Bit) -> Bit;
fn rotl(&mut self, rot: usize);
fn rotr(&mut self, rot: usize);
fn leading_zeros(&self) -> usize;
fn leading_ones(&self) -> usize;
fn trailing_zeros(&self) -> usize;
fn trailing_ones(&self) -> usize;
fn significant_bits(&self) -> usize {
self.len() - self.leading_zeros()
}
fn is_zero(&self) -> bool;
fn div_rem<B: BitVector>(&self, divisor: &B) -> (Self, Self)
where
Self: for<'a> TryFrom<&'a B, Error: std::fmt::Debug>;
fn iter(&self) -> BitIterator<'_, Self>;
}
#[cfg(test)]
mod tests;