use crate::io::{self, Read};
use bit_vec::BitVec;
use std::ops::Index;
pub struct BitRingIter<'a> {
ring: &'a BitRing,
cursor: usize,
limit: Option<usize>, }
impl Iterator for BitRingIter<'_> {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
if let Some(limit) = self.limit {
if self.cursor >= limit {
return None;
}
}
let bit = self.ring.bits[self.cursor];
self.cursor += 1;
Some(bit)
}
}
pub struct BitRing {
bits: BitVec,
wrap: usize,
cursor: usize,
wrap_value: Option<bool>,
}
impl From<BitVec> for BitRing {
fn from(bits: BitVec) -> BitRing {
let wrap = bits.len();
BitRing {
bits,
wrap,
cursor: 0,
wrap_value: None,
}
}
}
impl From<&[u8]> for BitRing {
fn from(bytes: &[u8]) -> BitRing {
let bits = BitVec::from_bytes(bytes);
let wrap = bits.len();
BitRing {
bits,
wrap,
cursor: 0,
wrap_value: None,
}
}
}
#[allow(dead_code)]
impl BitRing {
pub fn iter(&self) -> BitRingIter {
BitRingIter {
ring: self,
cursor: 0,
limit: None,
}
}
pub fn iter_revolution(&self) -> BitRingIter {
BitRingIter {
ring: self,
cursor: 0,
limit: Some(self.wrap),
}
}
pub fn from_bytes(bytes: &[u8]) -> BitRing {
BitRing::from(bytes)
}
pub fn from_elem(len: usize, elem: bool) -> BitRing {
BitRing {
bits: BitVec::from_elem(len, elem),
wrap: len,
cursor: 0,
wrap_value: None,
}
}
#[inline]
pub fn len(&self) -> usize {
self.bits.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.bits.is_empty()
}
#[inline]
pub fn wrap_len(&self) -> usize {
self.wrap
}
#[inline]
pub fn bits(&self) -> &BitVec {
&self.bits
}
#[inline]
pub fn bits_mut(&mut self) -> &mut BitVec {
&mut self.bits
}
#[inline]
pub fn to_bytes(&self) -> Vec<u8> {
self.bits.to_bytes()
}
#[inline]
pub fn set(&mut self, index: usize, bit: bool) {
if index < self.wrap {
self.bits.set(index, bit);
}
else {
self.bits.set(index % self.wrap, bit);
}
}
pub fn set_wrap(&mut self, wrap_len: usize) {
self.wrap = std::cmp::min(wrap_len, self.bits.len());
}
pub fn set_wrap_value(&mut self, wrap_value: impl Into<Option<bool>>) {
self.wrap_value = wrap_value.into();
}
#[inline]
fn incr_cursor(&mut self) {
self.cursor = self.wrap_cursor(self.cursor + 1);
}
#[inline]
fn wrap_cursor(&self, cursor: usize) -> usize {
if cursor != cursor % self.wrap {
log::warn!("Cursor wrapped around at {}", cursor);
}
cursor % self.wrap
}
}
impl Iterator for BitRing {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
let bit = self.bits[self.cursor];
self.incr_cursor();
Some(bit)
}
}
impl Read for BitRing {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut read = 0;
for buf_byte in buf.iter_mut() {
let mut byte = 0;
for _ in 0..8 {
byte = (byte << 1) | (self.bits[self.cursor] as u8);
self.incr_cursor();
}
*buf_byte = byte;
read += 1;
}
Ok(read)
}
}
impl Index<usize> for BitRing {
type Output = bool;
fn index(&self, index: usize) -> &Self::Output {
if index < self.wrap {
&self.bits[index]
}
else {
if index == self.wrap {
}
self.wrap_value
.as_ref()
.unwrap_or_else(|| &self.bits[index % self.wrap])
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use bit_vec::BitVec;
#[test]
fn test_from_bitvec() {
let bits = BitVec::from_bytes(&[0b1010_1010]);
let ring = BitRing::from(bits.clone());
assert_eq!(ring.len(), bits.len());
for i in 0..bits.len() {
assert_eq!(ring[i], bits[i]);
}
}
#[test]
fn test_from_bytes() {
let bytes = &[0b1010_1010, 0b1100_1100];
let ring = BitRing::from_bytes(bytes);
let expected_bits = BitVec::from_bytes(bytes);
for i in 0..expected_bits.len() {
assert_eq!(ring[i], expected_bits[i]);
}
}
#[test]
fn test_wrap_behavior_no_wrap_value() {
let bits = BitVec::from_bytes(&[0b1010_1010]); let mut ring = BitRing::from(bits.clone());
ring.set_wrap(8);
for i in 0..16 {
assert_eq!(ring[i], bits[i % 8]);
}
}
#[test]
fn test_wrap_behavior_with_wrap_value() {
let bits = BitVec::from_bytes(&[0b1010_1010]); let mut ring = BitRing::from(bits);
ring.set_wrap(8);
ring.set_wrap_value(Some(false));
for i in 0..8 {
assert_eq!(ring[i], ring.bits[i]);
}
for i in 8..16 {
assert!(!ring[i]);
}
}
#[test]
fn test_iterate_over_bits() {
let bytes = &[0b1010_1010];
let ring = BitRing::from_bytes(bytes);
let collected: Vec<bool> = Iterator::take(ring, 9).collect();
let expected = vec![true, false, true, false, true, false, true, false, true];
assert_eq!(collected, expected);
}
#[test]
fn test_read_to_buffer() {
let bytes = &[0b1010_1010];
let mut ring = BitRing::from_bytes(bytes);
let mut buf = [0; 1];
let read_bytes = ring.read(&mut buf).expect("Failed to read from BitRing");
assert_eq!(read_bytes, 1);
assert_eq!(buf[0], 0b1010_1010);
}
#[test]
fn test_custom_wrap_len() {
let bits = BitVec::from_bytes(&[0b1010_1010, 0b1100_1100]); let mut ring = BitRing::from(bits);
ring.set_wrap(8);
for i in 0..16 {
assert_eq!(ring[i], ring.bits[i % 8]);
}
}
#[test]
fn test_iter_revolution_length() {
let bits = BitVec::from_bytes(&[0b1010_1010, 0b1100_1100]); let ring = BitRing::from(bits.clone());
let revolution: Vec<bool> = ring.iter_revolution().collect();
assert_eq!(
revolution.len(),
ring.len(),
"iter_revolution should return exactly len() elements"
);
for i in 0..ring.len() {
assert_eq!(
revolution[i], ring.bits[i],
"Mismatch at index {} in iter_revolution",
i
);
}
}
}