pub use atom_file::Data;
use std::hash::Hash;
pub mod pageset;
pub use pageset::*;
pub mod buckmap;
pub use buckmap::*;
pub mod vbuckmap;
pub use vbuckmap::*;
pub mod varval;
pub use varval::*;
pub mod sys;
pub use sys::*;
pub mod datatype;
pub use datatype::*;
pub mod value;
pub use value::*;
mod pagetree;
use pagetree::*;
pub mod treevec;
use treevec::*;
mod bucket;
pub mod vbucket;
const PAGE_SIZE: u64 = 3952;
use pstd::localalloc::Local;
pub type LString = pstd::StringA<Local>;
pub type LVec<T> = pstd::VecA<T, Local>;
pub type LBox<T> = pstd::BoxA<T, Local>;
pub use pstd::rc::Rc;
pub use std::sync::Arc;
mod test;
#[cfg(test)]
fn tos(s: &[u8]) -> &str {
str::from_utf8(s).unwrap()
}
pub struct Exp {
pub inner: ExpInner,
}
pub enum ExpInner {
LocalVarRef(usize),
Binary(LBox<Exp>, LBox<Exp>),
}
pub trait Row {
fn size(&self) -> usize;
fn compare(&self, data: &[u8]) -> Ordering;
fn store(&self, data: &mut [u8]);
}
use std::cmp::Ordering;
use std::marker::PhantomData;
pub struct OpenPage<T: Row> {
pub data: Data,
pub pd: PhantomData<T>,
}
impl<T: Row> OpenPage<T> {
pub fn new(n: usize) -> Self {
let data = Arc::new(vec![0; n]);
Self {
data,
pd: PhantomData,
}
}
pub fn rows(&self) -> usize {
self.data[0] as usize
}
pub fn space(&self) -> usize {
self.data.len() - self.rows() * 2 - self.alloc()
}
pub fn insert(&mut self, r: &T) -> bool {
let n = r.size();
if self.space() < n + 2 {
return false;
}
let ipos = self.search(r);
println!("ipos={}", ipos);
let end = self.alloc();
let rows = self.rows();
let md = Arc::make_mut(&mut self.data);
let start = if ipos < rows {
let start = Self::row_off(md, ipos);
for i in 0..end - start {
md[end + n - i - 1] = md[end - i - 1];
}
let mut x = rows;
while x != ipos {
let off = Self::row_off(md, x - 1);
Self::set_row_off(md, x, off + n);
x -= 1;
}
start
} else {
end
};
r.store(&mut md[start..start + n]);
Self::set_row_off(md, ipos, start);
Self::set_rows(md, rows + 1);
Self::set_alloc(md, end + n);
true
}
pub fn slice(&self, i: usize) -> &[u8] {
let off = Self::row_off(&self.data, i);
let end = if i + 1 == self.rows() {
self.alloc()
} else {
Self::row_off(&self.data, i + 1)
};
&self.data[off..end]
}
fn search(&self, r: &T) -> usize {
let mut i = 0;
let mut j = self.rows();
while i != j {
let m = (i + j) / 2;
let s = self.slice(m);
match r.compare(s) {
Ordering::Equal => panic!("duplicate"),
Ordering::Greater => i = m + 1,
Ordering::Less => j = m,
}
}
i
}
fn set_rows(md: &mut [u8], to: usize) {
md[0] = to as u8;
}
fn alloc(&self) -> usize {
3 + self.data[1] as usize + (self.data[2] as usize * 256)
}
fn set_alloc(md: &mut [u8], to: usize) {
let to = to - 3;
md[1] = (to % 256) as u8;
md[2] = ((to / 256) % 256) as u8;
}
fn row_off(d: &[u8], i: usize) -> usize {
let x = d.len() - (i + 1) * 2;
d[x] as usize + (d[x + 1] as usize) * 256
}
fn set_row_off(md: &mut [u8], i: usize, to: usize) {
let x = md.len() - (i + 1) * 2;
md[x] = (to % 256) as u8;
md[x + 1] = ((to / 256) % 256) as u8;
}
}
#[derive(Debug)]
pub struct TestRow {
s: String,
}
impl Row for TestRow {
fn size(&self) -> usize {
self.s.len()
}
fn compare(&self, data: &[u8]) -> Ordering {
self.s.as_bytes().cmp(data)
}
fn store(&self, data: &mut [u8]) {
data.copy_from_slice(self.s.as_bytes());
}
}
#[cfg(test)]
fn insert(op: &mut OpenPage<TestRow>, s: &str) {
let r = TestRow { s: s.to_string() };
op.insert(&r);
println!("space={} data={:?}", op.space(), op.data);
}
#[test]
fn test_openpage() {
let mut op = OpenPage::<TestRow>::new(300);
let p = &mut op;
insert(p, "hello george");
insert(p, "zzzz");
insert(p, "aaa");
insert(p, "ddddd");
insert(p, "yyy");
for i in 0..op.rows() {
println!("i={} r={:?}", i, tos(op.slice(i)));
}
println!("Ok George");
}