added the builder

This commit is contained in:
Sander Hautvast 2022-10-28 16:35:55 +02:00
parent 686a7b9ebb
commit a50934393e
6 changed files with 104 additions and 27 deletions

44
src/builder.rs Normal file
View file

@ -0,0 +1,44 @@
use std::mem;
use crate::page::{self, Page};
use crate::record::Record;
struct Builder {
current_page: Page,
n_records_on_current_page: u16,
leaf_pages: Vec<Page>,
}
impl Builder {
pub fn new() -> Self {
Self {
current_page: Page::new_leaf(),
n_records_on_current_page: 0,
leaf_pages: Vec::new(),
}
}
pub fn add_record(&mut self, record: Record) {
if self.current_page_is_full(&record) {
self.finish_current_page();
self.leaf_pages.push(mem::replace(&mut self.current_page, Page::new_leaf()));
self.n_records_on_current_page = 0;
}
self.current_page.key = record.rowid; //clone?
self.current_page.put_vec_u8_bw(record.to_bytes());
self.current_page.put_u16(self.current_page.get_bw_position() as u16);
self.n_records_on_current_page += 1;
}
fn current_page_is_full(&self, record: &Record) -> bool {
self.current_page.get_bw_position() - record.get_length() <= self.current_page.get_fw_position() + 5
}
fn finish_current_page(&mut self) {
self.current_page.set_fw_position(page::POSITION_CELL_COUNT);
self.current_page.put_u16(self.n_records_on_current_page);
self.current_page.put_u16(self.current_page.get_bw_position());
}
}

View file

@ -6,14 +6,14 @@ use byteorder::{BigEndian, ByteOrder};
/// - big endian only /// - big endian only
pub struct ByteBuffer { pub struct ByteBuffer {
pub data: Vec<u8>, pub data: Vec<u8>,
pub fw_position: usize, pub fw_position: u16,
pub bw_position: usize, pub bw_position: u16,
} }
impl ByteBuffer { impl ByteBuffer {
pub fn new(size: usize) -> Self { pub fn new(size: u16) -> Self {
Self { Self {
data: vec![0; size], data: vec![0; size as usize],
fw_position: 0, fw_position: 0,
bw_position: size, bw_position: size,
} }
@ -22,23 +22,31 @@ impl ByteBuffer {
/// forward put unsigned byte array /// forward put unsigned byte array
pub fn put_u8a(&mut self, bytes: &[u8]) { pub fn put_u8a(&mut self, bytes: &[u8]) {
for v in bytes { for v in bytes {
self.data[self.fw_position] = *v; self.data[self.fw_position as usize] = *v;
self.fw_position += 1; self.fw_position += 1;
} }
} }
pub fn put_u8v(&mut self, bytes: &Vec<u8>) { pub fn put_u8v(&mut self, bytes: &Vec<u8>) {
for v in bytes { for v in bytes {
self.data[self.fw_position] = *v; self.data[self.fw_position as usize] = *v;
self.fw_position += 1; self.fw_position += 1;
} }
} }
/// backward put unsigned byte array /// backward put unsigned byte array
pub fn put_u8a_bw(&mut self, bytes: &[u8]) { pub fn put_u8a_bw(&mut self, bytes: &[u8]) {
self.bw_position -= bytes.len(); self.bw_position -= bytes.len() as u16;
for v in bytes { for v in bytes {
self.data[self.bw_position] = *v; self.data[self.bw_position as usize] = *v;
self.bw_position += 1;
}
}
pub fn put_vec_u8_bw(&mut self, bytes: Vec<u8>) {
self.bw_position -= bytes.len() as u16;
for v in bytes {
self.data[self.bw_position as usize] = v;
self.bw_position += 1; self.bw_position += 1;
} }
} }

View file

@ -4,7 +4,7 @@ mod bytebuffer;
mod values; mod values;
mod varint; mod varint;
mod record; mod record;
mod builder;
#[cfg(test)] #[cfg(test)]

View file

@ -1,6 +1,7 @@
use crate::bytebuffer::ByteBuffer; use crate::bytebuffer::ByteBuffer;
use crate::database; use crate::database;
const POSITION_CELL_COUNT: u32 = 3;
pub const POSITION_CELL_COUNT: u16 = 3;
const START_OF_CONTENT_AREA: u32 = 5; const START_OF_CONTENT_AREA: u32 = 5;
pub enum PageType { pub enum PageType {
@ -11,16 +12,16 @@ pub enum PageType {
/// Represents an SQLite page /// Represents an SQLite page
pub struct Page { pub struct Page {
data: ByteBuffer, data: ByteBuffer,
key: i64, pub key: u64,
children: Vec<Page>, children: Vec<Page>,
number: u32, number: u32,
page_type: PageType, page_type: PageType,
} }
impl Page { impl Page {
fn with_capacity(size: u16, page_type: PageType) -> Self { pub fn with_capacity(size: u16, page_type: PageType) -> Self {
Self { Self {
data: ByteBuffer::new(size as usize), data: ByteBuffer::new(size as u16),
key: 0, key: 0,
children: Vec::new(), children: Vec::new(),
number: 0, number: 0,
@ -28,13 +29,13 @@ impl Page {
} }
} }
fn new_leaf() -> Self { pub fn new_leaf() -> Self {
let mut page = Page::with_capacity(database::DEFAULT_PAGE_SIZE, PageType::Leaf); let mut page = Page::with_capacity(database::DEFAULT_PAGE_SIZE, PageType::Leaf);
page.put_u8(database::TABLE_LEAF_PAGE); page.put_u8(database::TABLE_LEAF_PAGE);
page page
} }
fn new_interior() -> Self { pub fn new_interior() -> Self {
let mut page = Page::with_capacity(database::DEFAULT_PAGE_SIZE, PageType::Interior); let mut page = Page::with_capacity(database::DEFAULT_PAGE_SIZE, PageType::Interior);
page.put_u8(database::TABLE_LEAF_PAGE); page.put_u8(database::TABLE_LEAF_PAGE);
page page
@ -44,22 +45,41 @@ impl Page {
self.children.push(child); self.children.push(child);
} }
pub fn fw_position(&mut self, new_position: usize) { pub fn set_fw_position(&mut self, new_position: u16) {
self.data.fw_position = new_position; self.data.fw_position = new_position;
} }
pub fn bw_position(&mut self, new_position: usize) { pub fn get_fw_position(&self) -> u16 {
self.data.fw_position
}
pub fn set_bw_position(&mut self, new_position: u16) {
self.data.bw_position = new_position; self.data.bw_position = new_position;
} }
pub fn get_bw_position(&self) -> u16 {
self.data.bw_position
}
pub fn put_u8a(&mut self, value: &[u8]) { pub fn put_u8a(&mut self, value: &[u8]) {
self.data.put_u8a(value); self.data.put_u8a(value);
} }
pub fn put_u8a_bw(&mut self, value: &[u8]) {
self.data.put_u8a_bw(value);
}
pub fn put_vec_u8_bw(&mut self, value: Vec<u8>) {
self.data.put_vec_u8_bw(value);
}
pub fn put_u8(&mut self, value: u8) { pub fn put_u8(&mut self, value: u8) {
self.data.put_u8(value); self.data.put_u8(value);
} }
pub fn put_u8_bw(&mut self, value: u8) {
self.data.put_u8_bw(value);
}
pub fn put_u16(&mut self, value: u16) { pub fn put_u16(&mut self, value: u16) {
self.data.put_u16(value); self.data.put_u16(value);
} }
@ -70,6 +90,6 @@ impl Page {
// may panic // may panic
pub fn get_page_nr_last_child(self) -> u32 { pub fn get_page_nr_last_child(self) -> u32 {
self.children[self.children.len()-1].number self.children[self.children.len() - 1].number
} }
} }

View file

@ -2,8 +2,8 @@ use crate::bytebuffer::ByteBuffer;
use crate::values::*; use crate::values::*;
use crate::varint; use crate::varint;
struct Record { pub struct Record {
rowid: u64, pub rowid: u64,
//or should it be i64?? //or should it be i64??
values: Vec<Value>, values: Vec<Value>,
} }
@ -20,14 +20,12 @@ impl Record {
self.values.push(value); self.values.push(value);
} }
fn to_bytes(&self) -> Vec<u8> { pub fn to_bytes(&self) -> Vec<u8> {
let record_length: usize = self.values.iter() let record_length = self.get_length();
.map(|v| v.get_length())
.sum();
let length_bytes = varint::write(record_length as u64); let length_bytes = varint::write(record_length as u64);
let rowid_bytes = varint::write(self.rowid); let rowid_bytes = varint::write(self.rowid);
let mut buffer = ByteBuffer::new(length_bytes.len() + rowid_bytes.len() + record_length); let mut buffer = ByteBuffer::new(length_bytes.len() as u16 + rowid_bytes.len() as u16 + record_length);
buffer.put_u8v(&length_bytes); buffer.put_u8v(&length_bytes);
buffer.put_u8v(&rowid_bytes); buffer.put_u8v(&rowid_bytes);
@ -48,6 +46,13 @@ impl Record {
} }
buffer.data buffer.data
} }
pub fn get_length(&self) -> u16 {
let record_length: u16 = self.values.iter()
.map(|v| v.get_length())
.sum();
record_length
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -8,8 +8,8 @@ pub struct Value {
impl Value { impl Value {
pub fn get_length(&self) -> usize { pub fn get_length(&self) -> u16 {
self.datatype.len() + self.data.len() (self.datatype.len() + self.data.len()) as u16
} }
} }