use std::str::from_utf8;
use bitvec::{field::BitField, order::Lsb0, slice::BitSlice as _BitSlice};
use self::types::BitVec;
use super::*;
pub type BitSlice = _BitSlice<u8, Lsb0>;
pub struct BitReader {
pub bytes: BitVec,
offset: usize,
}
impl BitReader {
pub fn new(bytes: &[u8]) -> Self {
BitReader {
bytes: BitVec::from_slice(bytes),
offset: 0,
}
}
pub fn read_1_bit(&mut self) -> bool {
let res = self.bytes[self.offset];
self.offset += 1;
res
}
pub fn read_n_bit(&mut self, n: usize) -> &BitSlice {
let range = self.offset + n;
let res: &BitSlice = &self.bytes[self.offset..range];
self.offset += n;
res
}
pub fn read_string(&mut self) -> &BitSlice {
let start = self.offset;
while self.peek_byte() != 0 {
self.offset += 8;
}
self.offset += 8;
&self.bytes[start..self.offset]
}
fn peek_byte(&self) -> u8 {
self.peek_n_bits(8).to_u8()
}
pub fn peek_n_bits(&self, n: usize) -> &BitSlice {
&self.bytes[self.offset..self.offset + n]
}
pub fn get_offset(&self) -> usize {
self.offset
}
pub fn get_consumed_bytes(&self) -> usize {
(self.get_offset() + 7) / 8
}
}
pub struct BitWriter {
pub data: BitVec,
pub offset: usize,
}
impl Default for BitWriter {
fn default() -> Self {
Self::new()
}
}
#[allow(dead_code)]
impl BitWriter {
pub fn new() -> Self {
Self {
data: BitVec::new(),
offset: 0,
}
}
fn offset(&mut self, i: usize) {
self.offset += i;
}
pub fn append_bit(&mut self, i: bool) {
self.data.push(i);
self.offset(1);
}
pub fn append_slice(&mut self, i: &BitSlice) {
self.data.extend(i);
self.offset(i.len());
}
pub fn append_vec(&mut self, i: &BitVec) {
self.append_slice(i.as_bitslice())
}
pub fn append_u8(&mut self, i: u8) {
let bits: BitVec = BitVec::from_element(i);
self.append_vec(&bits);
}
pub fn append_u32_range(&mut self, i: u32, end: u32) {
let bits: BitVec = i
.to_le_bytes()
.iter()
.flat_map(|byte| BitVec::from_element(*byte))
.collect();
self.append_slice(&bits[..end as usize]);
}
pub fn append_i32_range(&mut self, i: i32, end: u32) {
let bits: BitVec = i
.to_le_bytes()
.iter()
.flat_map(|byte| BitVec::from_element(*byte))
.collect();
self.append_slice(&bits[..end as usize]);
}
pub fn insert_bit(&mut self, i: bool, pos: usize) {
self.data.insert(pos, i);
self.offset(1);
}
pub fn insert_slice(&mut self, i: &BitSlice, pos: usize) {
for (offset, what) in i.iter().enumerate() {
self.insert_bit(*what, pos + offset);
}
}
pub fn insert_vec(&mut self, i: BitVec, pos: usize) {
self.insert_slice(i.as_bitslice(), pos);
}
pub fn insert_u8(&mut self, i: u8, pos: usize) {
let bits: BitVec = BitVec::from_element(i);
self.insert_slice(&bits, pos);
}
pub fn insert_u32_range(&mut self, i: u32, end: u32, pos: usize) {
let bits: BitVec = i
.to_le_bytes()
.iter()
.flat_map(|byte| BitVec::from_element(*byte))
.collect();
self.insert_slice(&bits[..end as usize], pos);
}
pub fn get_u8_vec(&mut self) -> Vec<u8> {
let mut what = self.data.to_owned();
what.force_align();
what.into_vec()
}
pub fn get_offset(&self) -> usize {
self.offset
}
}
#[allow(dead_code)]
pub trait BitSliceCast {
fn to_u8(&self) -> u8;
fn to_i8(&self) -> i8;
fn to_u16(&self) -> u16;
fn to_i16(&self) -> i16;
fn to_u32(&self) -> u32;
fn to_i32(&self) -> i32;
fn get_string(&self) -> String;
}
impl BitSliceCast for BitSlice {
fn to_u8(&self) -> u8 {
self.load::<u8>()
}
fn to_i8(&self) -> i8 {
self.load::<i8>()
}
fn to_u16(&self) -> u16 {
self.load::<u16>()
}
fn to_i16(&self) -> i16 {
self.load::<i16>()
}
fn to_u32(&self) -> u32 {
self.load::<u32>()
}
fn to_i32(&self) -> i32 {
self.load::<i32>()
}
fn get_string(&self) -> String {
let binding = self
.chunks(8)
.map(|chunk| chunk.to_i8() as u8)
.collect::<Vec<u8>>();
let s = from_utf8(binding.as_slice()).unwrap();
s.to_string()
}
}