#![allow(clippy::module_inception)]
use codec::{Compact, Decode, Encode};
#[macro_export]
macro_rules! bits {
($($val:tt),* $(,)*) => {{
#[allow(unused_mut)]
let mut bits = $crate::bits::Bits::new();
$crate::bits!(__internal__ bits: $($val),*);
bits
}};
(__internal__ $bits:ident: 1 $(,$rest:tt)* $(,)?) => {{
$bits.push(true);
$crate::bits!(__internal__ $bits: $($rest,)*);
}};
(__internal__ $bits:ident: 0 $(,$rest:tt)* $(,)?) => {{
$bits.push(false);
$crate::bits!(__internal__ $bits: $($rest,)*);
}};
(__internal__ $bits:ident: $bool:expr $(,$rest:tt)* $(,)?) => {{
$bits.push($bool);
$crate::bits!(__internal__ $bits: $($rest,)*);
}};
(__internal__ $bits:ident: $(,)?) => {{
}};
}
#[derive(Clone, PartialEq, Eq, Debug, Default)]
pub struct Bits {
pub(crate) storage: Vec<u8>,
pub(crate) bits_in_last_byte: usize,
}
impl Bits {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(num_bits: usize) -> Self {
let mut num_bytes = num_bits / 8;
let is_exact_multiple_of_8 = num_bits & 0b111 == 0;
if !is_exact_multiple_of_8 {
num_bytes += 1;
}
Bits { storage: Vec::with_capacity(num_bytes), bits_in_last_byte: 0 }
}
pub fn is_empty(&self) -> bool {
self.storage.is_empty()
}
pub fn len(&self) -> usize {
let len = self.storage.len();
if len == 0 {
return 0;
}
(len - 1) * 8 + self.bits_in_last_byte
}
pub fn push(&mut self, b: bool) {
let bit_val: u8 = match b {
true => 1,
false => 0,
};
match self.bits_in_last_byte {
0 | 8 => {
self.storage.push(bit_val);
self.bits_in_last_byte = 1;
}
n => {
let byte = self.storage.last_mut().expect("should be a byte");
*byte |= bit_val << n;
self.bits_in_last_byte += 1;
}
}
}
pub fn pop(&mut self) -> Option<bool> {
let last_byte = self.storage.last_mut()?;
let right_shift_amount = self.bits_in_last_byte - 1;
let res = match (*last_byte >> right_shift_amount) & 1 {
1 => true,
0 => false,
_ => unreachable!("Can only be 0 or 1 owing to &1"),
};
*last_byte ^= 1 << right_shift_amount;
self.bits_in_last_byte -= 1;
if self.bits_in_last_byte == 0 {
self.storage.pop();
if self.storage.is_empty() {
self.bits_in_last_byte = 0;
} else {
self.bits_in_last_byte = 8;
}
}
Some(res)
}
pub fn get(&self, idx: usize) -> Option<bool> {
if self.storage.is_empty() {
return None;
}
let byte_idx = idx / 8;
let bit_in_byte = idx & 0b111;
if byte_idx == self.storage.len() - 1 && bit_in_byte >= self.bits_in_last_byte {
return None;
}
let byte = *self.storage.get(byte_idx)?;
match (byte >> bit_in_byte) & 1 {
0 => Some(false),
1 => Some(true),
_ => unreachable!("Can only be 0 or 1 owing to &1"),
}
}
pub fn iter(&'_ self) -> BitsIter<'_> {
BitsIter { pos: 0, bits: self }
}
pub fn to_vec(self) -> Vec<bool> {
self.into_iter().collect()
}
}
impl std::iter::IntoIterator for Bits {
type Item = bool;
type IntoIter = BitsIntoIter;
fn into_iter(self) -> Self::IntoIter {
BitsIntoIter { pos: 0, bits: self }
}
}
#[derive(Clone, Debug)]
pub struct BitsIntoIter {
pos: usize,
bits: Bits,
}
impl Iterator for BitsIntoIter {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
let next = self.bits.get(self.pos)?;
self.pos += 1;
Some(next)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.bits.len() - self.pos;
(len, Some(len))
}
}
impl ExactSizeIterator for BitsIntoIter {}
#[derive(Copy, Clone, Debug)]
pub struct BitsIter<'a> {
pos: usize,
bits: &'a Bits,
}
impl<'a> Iterator for BitsIter<'a> {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
let next = self.bits.get(self.pos)?;
self.pos += 1;
Some(next)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.bits.len() - self.pos;
(len, Some(len))
}
}
impl<'a> ExactSizeIterator for BitsIter<'a> {}
impl std::iter::FromIterator<bool> for Bits {
fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
let iter = iter.into_iter();
let num_bits_to_alloc_for = match iter.size_hint() {
(_, Some(max)) => max,
(min, None) => min,
};
let mut bits = Bits::with_capacity(num_bits_to_alloc_for);
for b in iter {
bits.push(b);
}
bits
}
}
impl Decode for Bits {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
let len_bits = Compact::<u32>::decode(input)?.0 as usize;
let remainder = len_bits & 0b111;
let len = len_bits / 8 + if remainder > 0 { 1 } else { 0 };
const MAX_PRE_ALLOC_BYTES: usize = 1024;
let prealloc_len = len.min(MAX_PRE_ALLOC_BYTES);
let mut storage = Vec::with_capacity(prealloc_len);
for _ in 0..len {
let byte = input.read_byte()?;
storage.push(byte);
}
let bits_in_last_byte = if !storage.is_empty() && remainder == 0 { 8 } else { remainder };
Ok(Bits { storage, bits_in_last_byte })
}
}
impl Encode for Bits {
fn size_hint(&self) -> usize {
self.encoded_size()
}
fn encode(&self) -> Vec<u8> {
let mut r = Vec::with_capacity(self.size_hint());
Compact(self.len() as u32).encode_to(&mut r);
for byte in &self.storage {
r.push(*byte);
}
r
}
fn encoded_size(&self) -> usize {
let compact_byte_len = Compact(self.len() as u32).encoded_size();
compact_byte_len + self.storage.len()
}
}
#[cfg(feature = "scale-info")]
mod type_info {
use scale_info::{build::Fields, Path, Type, TypeDefBitSequence, TypeInfo};
impl TypeInfo for super::Bits {
type Identity = Self;
fn type_info() -> Type {
enum Lsb0 {}
impl TypeInfo for Lsb0 {
type Identity = Self;
fn type_info() -> Type {
Type::builder()
.path(Path::new("Lsb0", "bitvec::order"))
.composite(Fields::unit())
}
}
TypeDefBitSequence::new::<u8, Lsb0>().into()
}
}
}