use crate::*;
/// Storage of variable length values (varval).
struct VarValStore {
tv: (u64, u64),
}
impl VarValStore {
pub fn new(tv: (u64, u64)) -> Self {
Self { tv }
}
pub fn save(&self) -> (u64, u64) {
self.tv
}
/// Store a new varval, returns addr.
pub fn store(&mut self, user_data: &[u8], ps: &mut PageSet) -> u64 {
let mut tv = TreeVec::new(self.tv, ps);
let result = self.tv.1;
tv.write(result, user_data);
self.tv = tv.save();
result
}
/// Reads a stored varval with given addr and len into user_data.
///
/// Could have version that writes to any Writer ( struct implementing std::io::Write ).
pub fn get(&self, addr: u64, len: usize, user_data: &mut [u8], ps: &mut PageSet) {
assert!(user_data.len() >= len);
let mut tv = TreeVec::new(self.tv, ps);
tv.read(addr, user_data);
}
/// Delete a stored varval with given id and len.
pub fn delete(&mut self, _addr: u64, _len: usize, _ps: &mut PageSet) {
// ToDo : increase free space
}
/// Update a varval, returns new id.
///
/// Will re-use addr if length does not change.
pub fn update(&mut self, addr: u64, old_len: usize, user_data: &[u8], ps: &mut PageSet) -> u64 {
let mut tv = TreeVec::new(self.tv, ps);
if old_len == user_data.len() {
tv.write(addr, user_data);
addr
} else {
self.delete(addr, old_len, ps);
self.store(user_data, ps)
}
}
}
// ************** End VarVal
/// Address of stored variable length value ( varval ).
#[derive(Debug, Eq, PartialEq, Copy, Clone, Ord, PartialOrd)] // Comparison should really just be done on id.
pub struct VarValAddr {
/// This will eventually be more complicated, e,g, may be a TreeVec, or diferent VarValStores.
addr: u64,
len: u64,
}
impl VarValAddr {
pub fn new(dt: &DataType, v: &Value, ps: &mut PageSet) -> Self {
let bytes = dt.value_to_bytes(v);
let len = bytes.len() as u64;
let mut vv = VarValStore::new(ps.vvs); // Will be multiple stores eventually.
let addr = vv.store(&bytes, ps);
ps.vvs = vv.save();
Self { addr, len }
}
pub fn get(&self, dt: &DataType, ps: &mut PageSet) -> Value {
let vv = VarValStore::new(ps.vvs);
let mut buf = vec![0; self.len as usize];
vv.get(self.addr, self.len as usize, &mut buf, ps);
dt.bytes_to_value(&buf)
}
pub fn update(&self, dt: &DataType, v: &Value, ps: &mut PageSet) -> Self {
let mut vv = VarValStore::new(ps.vvs);
let bytes = dt.value_to_bytes(v);
let len = bytes.len() as u64;
let addr = vv.update(self.addr, self.len as usize, &bytes, ps);
ps.vvs = vv.save();
Self { addr, len }
}
pub fn delete(&self, ps: &mut PageSet) {
let mut vv = VarValStore::new(ps.vvs);
vv.delete(self.addr, self.len as usize, ps);
ps.vvs = vv.save();
}
}
impl SmallFixed for VarValAddr {
fn size() -> usize {
2 * 8
}
fn load(bytes: &[u8]) -> Self {
let addr = u64::from_le_bytes(bytes[0..8].try_into().unwrap());
let len = u64::from_le_bytes(bytes[8..16].try_into().unwrap());
Self { addr, len }
}
fn save(&self, bytes: &mut [u8]) {
bytes[0..8].copy_from_slice(&self.addr.to_le_bytes());
bytes[8..16].copy_from_slice(&self.len.to_le_bytes());
}
}
// ************** End VarValAddr
#[cfg(test)]
pub fn test_varval(ps: &mut PageSet) {
let tv = (ps.new_page(), 0);
let mut vv = VarValStore { tv };
let mut ids = Vec::new();
let d1 = b"Hello there George";
let d2 = b"Tuesday is lovely, so is Wednesday";
//let d2 = b"Tuesday is lovely! So is Wednesday. .............................................Saturday also.";
for _ in 0..1_000_000 {
let id = vv.store(d1, ps);
ids.push(id);
// println!("test varval stored {}", id);
// println!("");
}
//println!("ids={:?}", ids);
let mut buf = vec![0; d1.len()];
for id in &ids {
vv.get(*id, d1.len(), &mut buf, ps);
// println!("buf={}", tos(&buf));
assert_eq!(buf, d1);
}
let mut nids = Vec::new();
for id in &ids {
let nid = vv.update(*id, d1.len(), d2, ps);
nids.push(nid);
}
let mut buf = vec![0; d2.len()];
for id in &nids {
vv.get(*id, d2.len(), &mut buf, ps);
assert_eq!(buf, d2);
}
}