#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::{vec, vec::Vec};
use bitvec::order::Msb0;
use bitvec::vec::BitVec;
use core::{default::Default, option::Option, panic};
pub fn encode(start: usize, end: usize, target: usize) -> BitVec<u8, Msb0> {
if start >= end {
panic!("Invalid range: start ({}) >= end ({})", start, end);
}
if !(start <= target && target < end) {
panic!("target ({}) out of bounds [{}, {})", target, start, end);
}
let mut path = BitVec::<u8, Msb0>::new();
let mut lo = start;
let mut hi = end;
loop {
let mid = (lo + hi) / 2;
if target == mid {
break;
}
if target < mid {
path.push(false);
hi = mid;
} else {
path.push(true);
lo = mid;
}
if hi - lo == 1 {
break;
}
}
path
}
pub fn encode_from(start: usize, end: usize, target: usize, midpoint: usize) -> BitVec<u8, Msb0> {
if start >= end {
panic!("Invalid range: start ({}) >= end ({})", start, end);
}
if !(start <= target && target < end) {
panic!("target ({}) out of bounds [{}, {})", target, start, end);
}
if !(start < midpoint && midpoint < end) {
panic!(
"midpoint ({}) must be within (start={}, end={})",
midpoint, start, end
);
}
let mut path = BitVec::<u8, Msb0>::new();
let mut lo = start;
let mut hi = end;
let mut mid = midpoint;
loop {
if target == mid {
break;
}
if target < mid {
path.push(false);
hi = mid;
} else {
path.push(true);
lo = mid;
}
if hi - lo == 1 {
break;
}
mid = (lo + hi) / 2;
}
path
}
pub fn decode(start: usize, end: usize, path: &BitVec<u8, Msb0>) -> usize {
let mut lo = start;
let mut hi = end;
for bit in path.iter() {
let mid = (lo + hi) / 2;
if *bit {
lo = mid;
} else {
hi = mid;
}
}
(lo + hi) / 2
}
pub fn decode_from(start: usize, end: usize, path: &BitVec<u8, Msb0>, midpoint: usize) -> usize {
if path.is_empty() {
return midpoint;
}
let mut lo = start;
let mut hi = end;
let mut mid = midpoint;
for bit in path.iter() {
if *bit {
lo = mid;
} else {
hi = mid;
}
if hi - lo == 1 {
break;
}
mid = (lo + hi) / 2;
}
(lo + hi) / 2
}
pub struct BBSEStack {
pub entries: Vec<BitVec<u8, Msb0>>,
}
impl Default for BBSEStack {
fn default() -> Self {
Self::new()
}
}
impl BBSEStack {
pub fn new() -> Self {
Self { entries: vec![] }
}
pub fn push(&mut self, path: BitVec<u8, Msb0>) {
self.entries.push(path);
}
pub fn pop(&mut self) -> Option<BitVec<u8, Msb0>> {
self.entries.pop()
}
pub fn decode_all(&self, start: usize, end: usize) -> Vec<usize> {
self.entries.iter().map(|p| decode(start, end, p)).collect()
}
#[cfg(feature = "std")]
pub fn print_all(&self) {
self.entries.iter().for_each(|f| println!("encoded: {}", f));
}
}