#![allow(dead_code)]
use std::rc::Rc;
pub struct DatabaseBuilder {}
impl DatabaseBuilder {
pub fn new() -> Self {
DatabaseBuilder {}
}
pub fn build(&self) -> Database {
Database::new()
}
}
pub struct Database {}
impl Database {
pub fn new() -> Self {
Database {}
}
pub fn begin(&mut self) -> Transaction {
Transaction::new()
}
}
type TransactionId = u64;
pub struct Transaction {}
impl Transaction {
pub fn new() -> Self {
Transaction {}
}
pub fn commit(&mut self) {}
pub fn rollback(&mut self) {}
}
pub struct TransactionStats {}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct BucketInner {
root: PageId,
sequence: u64,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct Meta {
magic: u32,
version: u32,
page_size: u32,
flags: u32,
root: BucketInner,
freelist: PageId,
page_id: PageId,
tx_id: TransactionId,
checksum: u64,
}
impl Meta {
fn validate(&self) {}
}
const PAGE_FLAG_BRANCH: u16 = 0x01;
const PAGE_FLAG_LEAF: u16 = 0x02;
const PAGE_FLAG_META: u16 = 0x04;
const PAGE_FLAG_FREELIST: u16 = 0x10;
const PAGE_HEADER_SIZE: usize = std::mem::size_of::<Page>();
type PageId = u64;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct Page {
id: PageId,
flags: u16,
count: u16,
overflow: u32,
}
impl Page {
fn page_type(&self) -> PageType {
if (self.flags & PAGE_FLAG_BRANCH) != 0 {
PageType::Branch
} else if (self.flags & PAGE_FLAG_LEAF) != 0 {
PageType::Leaf
} else if (self.flags & PAGE_FLAG_META) != 0 {
PageType::Meta
} else if (self.flags & PAGE_FLAG_FREELIST) != 0 {
PageType::Freelist
} else {
PageType::Unknown(self.flags)
}
}
unsafe fn meta(&self) -> &Meta {
let ptr: *const u8 = std::mem::transmute(self);
let offset = PAGE_HEADER_SIZE as isize;
std::mem::transmute(ptr.offset(offset))
}
unsafe fn element<T>(&self, index: usize) -> &T {
let ptr: *const u8 = std::mem::transmute(self);
let offset = (PAGE_HEADER_SIZE + std::mem::size_of::<T>() * index) as isize;
std::mem::transmute(ptr.offset(offset))
}
unsafe fn elements<T>(&self) -> Option<Vec<T>> where T: Clone {
let length = self.count as usize;
if length == 0 {
return None;
}
let ptr: *const u8 = std::mem::transmute(self);
let offset = PAGE_HEADER_SIZE as isize;
let ptr: *const T = std::mem::transmute(ptr.offset(offset));
Some(std::slice::from_raw_parts(ptr, length).to_vec())
}
}
#[derive(Debug, Copy, Clone)]
enum PageType {
Branch,
Leaf,
Meta,
Freelist,
Unknown(u16),
}
impl std::fmt::Display for PageType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PageType::Branch => write!(f, "branch"),
PageType::Leaf => write!(f, "leaf"),
PageType::Meta => write!(f, "meta"),
PageType::Freelist => write!(f, "freelist"),
PageType::Unknown(flags) => write!(f, "unknown<{}>", flags)
}
}
}
#[derive(Debug, Copy, Clone)]
struct PageInfo {
id: i32,
page_type: PageType,
count: i32,
overflow_count: i32,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct BranchPageElement {
position: u32,
k_size: u32,
page_id: PageId,
}
impl BranchPageElement {
unsafe fn key(&self) -> Vec<u8> {
let ptr: *const u8 = std::mem::transmute(self);
std::slice::from_raw_parts(ptr.offset(self.position as isize), self.k_size as usize).to_vec()
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct LeafPageElement {
flags: u32,
position: u32,
k_size: u32,
v_size: u32,
}
impl LeafPageElement {
unsafe fn key(&self) -> Vec<u8> {
let ptr: *const u8 = std::mem::transmute(self);
std::slice::from_raw_parts(ptr.offset(self.position as isize), self.k_size as usize).to_vec()
}
unsafe fn value(&self) -> Vec<u8> {
let ptr: *const u8 = std::mem::transmute(self);
std::slice::from_raw_parts(ptr.offset((self.position + self.k_size) as isize), self.k_size as usize).to_vec()
}
}
#[derive(Debug)]
struct Node {
is_leaf: bool,
unbalanced: bool,
spilled: bool,
key: Vec<u8>,
page_id: PageId,
parent: Option<Rc<Box<Node>>>,
children: Vec<Rc<Box<Node>>>,
inodes: Vec<INode>,
}
impl Node {
fn root(node: Rc<Box<Node>>) -> Rc<Box<Node>> {
match node.parent.clone() {
Some(p) => Node::root(p),
None => node,
}
}
fn min_keys(&self) -> i32 {
if self.is_leaf { 1 } else { 2 }
}
}
#[derive(Debug)]
struct INode {
flags: u32,
page_id: PageId,
key: Vec<u8>,
value: Vec<u8>,
}
mod tests {
#[allow(unused_imports)]
use crate::*;
#[test]
fn test_page_meta() {
let meta = Meta {
magic: 0,
version: 1,
page_size: 2,
flags: 3,
root: BucketInner {
root: 4,
sequence: 5,
},
freelist: 6,
page_id: 7,
tx_id: 8,
checksum: 9,
};
let ptr: *const u8 = unsafe { std::mem::transmute(&meta) };
let mut meta_bytes = unsafe { std::slice::from_raw_parts(ptr, std::mem::size_of::<Meta>()).to_vec() };
let mut page_bytes = vec![0u8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0];
page_bytes.append(&mut meta_bytes);
let page: &Page = unsafe { std::mem::transmute(page_bytes.as_ptr()) };
let meta = unsafe { page.meta() };
assert!(if let PageType::Branch = page.page_type() { true } else { false });
assert_eq!(meta.magic, 0);
assert_eq!(meta.version, 1);
assert_eq!(meta.page_size, 2);
assert_eq!(meta.flags, 3);
assert_eq!(meta.root.root, 4);
assert_eq!(meta.root.sequence, 5);
assert_eq!(meta.freelist, 6);
assert_eq!(meta.page_id, 7);
assert_eq!(meta.tx_id, 8);
assert_eq!(meta.checksum, 9);
}
#[test]
fn test_page_element() {
let page_bytes = vec![0u8, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 6, 7, 8, 9];
let page: &Page = unsafe { std::mem::transmute(page_bytes.as_ptr()) };
assert!(if let PageType::Leaf = page.page_type() { true } else { false });
assert_eq!(unsafe { *page.element::<u8>(0) as usize }, 6);
assert_eq!(unsafe { *page.element::<u8>(1) as usize }, 7);
assert_eq!(unsafe { *page.element::<u8>(2) as usize }, 8);
assert_eq!(unsafe { *page.element::<u8>(3) as usize }, 9);
}
#[test]
fn test_page_elements() {
let page_bytes = vec![0u8, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 6, 7, 8, 9];
let page: &Page = unsafe { std::mem::transmute(page_bytes.as_ptr()) };
let elements = unsafe { page.elements::<u8>().unwrap() };
assert!(if let PageType::Leaf = page.page_type() { true } else { false });
assert_eq!(elements[0] as usize, 6);
assert_eq!(elements[1] as usize, 7);
assert_eq!(elements[2] as usize, 8);
assert_eq!(elements[3] as usize, 9);
}
#[test]
fn test_node_root() {
let node = Rc::new(Box::new(Node {
is_leaf: false,
unbalanced: false,
spilled: false,
key: vec![],
page_id: 0,
parent: Some(Rc::new(Box::new(Node {
is_leaf: false,
unbalanced: false,
spilled: false,
key: vec![],
page_id: 0,
parent: Some(Rc::new(Box::new(Node {
is_leaf: true,
unbalanced: false,
spilled: false,
key: vec![],
page_id: 0,
parent: None,
children: vec![],
inodes: vec![],
}))),
children: vec![],
inodes: vec![],
}))),
children: vec![],
inodes: vec![],
}));
let root = Node::root(node);
println!("{:?}", root.is_leaf);
}
}