use crate::*;
pub struct Store<'a> {
pub data: Data,
pub ps: &'a mut PageSet, }
#[derive(Debug)]
pub enum AllocErr {
Id,
Data
}
impl<'a> Store<'a> {
pub fn new(ps: &'a mut PageSet) -> Self
{
let mut md = Vec::new();
let noff = 255;
md.resize( DATA + 2 * noff, 0 );
md[NOFF] = noff as u8;
let data = Arc::new(md);
Self{ ps, data }
}
pub fn write(&mut self, user_data: &[u8]) -> Result<u8,AllocErr> {
let md = &mut Arc::make_mut(&mut self.data);
let id = alloc_id(md)?;
let len = user_data.len();
let off = alloc_inline(md, len+1)?;
md[off] = len as u8;
let loc = &mut md[off+1..off+1+len];
loc.copy_from_slice(user_data);
set_off(md, id, off);
Ok(id)
}
pub fn size(&self, id: u8) -> usize {
let off = self.get_off(id);
let len = self.data[off] as usize;
len
}
pub fn read(&self, id: u8) -> Vec<u8> {
let off = self.get_off(id);
let len = self.data[off] as usize;
let loc = &self.data[off+1..off+1+len];
let mut result = Vec::new();
result.extend_from_slice(loc);
result
}
pub fn update(&mut self, _id: u8, _data: &[u8]) {
todo!()
}
pub fn delete(&mut self, id: u8) {
let md = &mut Arc::make_mut(&mut self.data);
let x = md[FFID];
md[FFID] = id;
set_off( md, id, x as usize);
}
pub fn space(&self) -> usize
{
todo!()
}
pub fn pack(&mut self)
{
todo!()
}
fn get_off(&self, id:u8) -> usize
{
let off = DATA + ( (id-1) as usize ) * 2;
self.data[off] as usize + 256 * ( self.data[off+1] as usize )
}
pub fn ids(&self) -> Vec<u8> {
let mut bitmap = [0u8; 16];
let mut fid = self.data[FFID];
while fid != 0
{
let i = ( fid - 1 ) as usize;
bitmap[ i / 8 ] |= 1 << ( i % 8 );
fid = self.get_off(fid) as u8;
}
let mut result = Vec::new();
let n = self.data[IDNX];
for id in 1..=n {
let i = ( id - 1 ) as usize;
if bitmap[ i / 8 ] & ( 1 << ( i % 8 ) ) == 0
{
result.push(id);
}
}
result
}
}
const NOFF : usize = 0; const IDNX : usize = 1; const FFID : usize = 2; const _DTOT : usize = 3; const _FTOT : usize = 5; const DATA : usize = 7;
fn alloc_id(md: &mut [u8]) -> Result<u8,AllocErr>
{
let mut id : u8 = md[FFID];
if id == 0
{
id = md[IDNX];
if id == md[NOFF] { return Err(AllocErr::Id); } md[IDNX] = id + 1;
}
else
{
md[FFID] = get_off(md,id) as u8;
}
Ok(id+1)
}
fn alloc_inline(v: &mut Vec<u8>, len: usize) -> Result<usize,AllocErr>
{
let result = v.len();
v.resize( result + len, 0);
Ok(result)
}
fn get_off(md: &mut [u8], id: u8) -> usize
{
let off = DATA + ( (id-1) as usize ) * 2;
md[off] as usize + 256 * ( md[off+1] as usize )
}
fn set_off(md: &mut [u8], id: u8, val: usize)
{
let off = DATA + ( (id-1) as usize ) * 2;
md[off] = ( val % 256 ) as u8;
md[off+1] = ( val / 256 ) as u8;
}
#[cfg(test)]
pub fn test_store(ps: &mut PageSet)
{
let td1 = b"Hello George";
let td2 = b"Marilyn";
let mut s = Store::new(ps);
let id1 = s.write( td1 ).unwrap();
let id2 = s.write( td2 ).unwrap();
let x1 = s.read(id1);
let x2 = s.read(id2);
assert_eq!( x1, td1 );
assert_eq!( x2, td2 );
s.delete( id1 );
let ids = s.ids();
println!("ids={:?}", ids);
let root = s.ps.new_page();
s.ps.note( root, s.data, true );
}