#[cfg(all(feature = "alloc", feature = "set"))]
use bstack::{BStack, BStackAllocator, BStackSlice, FirstFitBStackAllocator};
#[cfg(all(feature = "alloc", feature = "set"))]
use std::io;
#[cfg(all(feature = "alloc", feature = "set"))]
const RECORD_SIZE: u64 = 64;
#[cfg(all(feature = "alloc", feature = "set"))]
const VALUE_SIZE: usize = 56;
#[cfg(all(feature = "alloc", feature = "set"))]
struct Record {
key: u64,
value: [u8; VALUE_SIZE],
}
#[cfg(all(feature = "alloc", feature = "set"))]
impl Record {
fn to_bytes(&self) -> [u8; RECORD_SIZE as usize] {
let mut buf = [0u8; RECORD_SIZE as usize];
buf[..8].copy_from_slice(&self.key.to_le_bytes());
buf[8..8 + VALUE_SIZE].copy_from_slice(&self.value);
buf
}
fn from_bytes(buf: &[u8]) -> Self {
let key = u64::from_le_bytes(buf[..8].try_into().unwrap());
let mut value = [0u8; VALUE_SIZE];
value.copy_from_slice(&buf[8..8 + VALUE_SIZE]);
Record { key, value }
}
}
#[cfg(all(feature = "alloc", feature = "set"))]
fn insert(alloc: &FirstFitBStackAllocator, record: &Record) -> io::Result<[u8; 16]> {
let slice = alloc.alloc(RECORD_SIZE)?;
slice.write(&record.to_bytes())?;
Ok(<[u8; 16]>::from(slice))
}
#[cfg(all(feature = "alloc", feature = "set"))]
fn read(alloc: &FirstFitBStackAllocator, token: &[u8; 16]) -> io::Result<Record> {
let slice = BStackSlice::from_bytes(alloc, *token);
let buf = slice.read()?;
Ok(Record::from_bytes(&buf))
}
#[cfg(all(feature = "alloc", feature = "set"))]
fn update(alloc: &FirstFitBStackAllocator, token: &[u8; 16], record: &Record) -> io::Result<()> {
let slice = BStackSlice::from_bytes(alloc, *token);
slice.write(&record.to_bytes())
}
#[cfg(all(feature = "alloc", feature = "set"))]
fn delete(alloc: &FirstFitBStackAllocator, token: &[u8; 16]) -> io::Result<()> {
let slice = BStackSlice::from_bytes(alloc, *token);
alloc.dealloc(slice)
}
#[cfg(all(feature = "alloc", feature = "set"))]
fn main() -> io::Result<()> {
let path = "alloc_typed_example.bstack";
let tokens: Vec<[u8; 16]>;
{
let alloc = FirstFitBStackAllocator::new(BStack::open(path)?)?;
let mut t = Vec::new();
for i in 0u64..3 {
let mut value = [0u8; VALUE_SIZE];
let msg = format!("entry {i}");
value[..msg.len()].copy_from_slice(msg.as_bytes());
t.push(insert(&alloc, &Record { key: i, value })?);
println!("inserted key={i} at token {:?}", &t.last().unwrap()[..8]);
}
tokens = t;
drop(alloc.into_stack());
}
{
let alloc = FirstFitBStackAllocator::new(BStack::open(path)?)?;
println!("\nsession 2 — reading all records:");
for tok in &tokens {
let r = read(&alloc, tok)?;
println!(
" key={} value={:?}",
r.key,
String::from_utf8_lossy(r.value.split(|&b| b == 0).next().unwrap_or(&[]))
);
}
let mut new_value = [0u8; VALUE_SIZE];
new_value[..7].copy_from_slice(b"updated");
update(
&alloc,
&tokens[1],
&Record {
key: 1,
value: new_value,
},
)?;
println!("\nupdated key=1");
delete(&alloc, &tokens[0])?;
println!("deleted key=0");
let r1 = read(&alloc, &tokens[1])?;
println!(
"key=1 now: {:?}",
String::from_utf8_lossy(r1.value.split(|&b| b == 0).next().unwrap_or(&[]))
);
let new_slot = alloc.alloc(RECORD_SIZE)?;
println!(
"new alloc at offset {} (deleted key=0 was at offset {})",
new_slot.start(),
BStackSlice::from_bytes(&alloc, tokens[0]).start(),
);
let _ = new_slot;
drop(alloc.into_stack());
}
std::fs::remove_file(path).ok();
Ok(())
}
#[cfg(not(all(feature = "alloc", feature = "set")))]
fn main() {
println!("This example requires the 'alloc' and 'set' features.");
}