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
pub struct ByteBuffer {
pub data: Vec<u8>,
pub fw_position: usize,
pub bw_position: usize,
pub fw_position: u16,
pub bw_position: u16,
}
impl ByteBuffer {
pub fn new(size: usize) -> Self {
pub fn new(size: u16) -> Self {
Self {
data: vec![0; size],
data: vec![0; size as usize],
fw_position: 0,
bw_position: size,
}
@ -22,23 +22,31 @@ impl ByteBuffer {
/// forward put unsigned byte array
pub fn put_u8a(&mut self, bytes: &[u8]) {
for v in bytes {
self.data[self.fw_position] = *v;
self.data[self.fw_position as usize] = *v;
self.fw_position += 1;
}
}
pub fn put_u8v(&mut self, bytes: &Vec<u8>) {
for v in bytes {
self.data[self.fw_position] = *v;
self.data[self.fw_position as usize] = *v;
self.fw_position += 1;
}
}
/// backward put unsigned byte array
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 {
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;
}
}

View file

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

View file

@ -1,6 +1,7 @@
use crate::bytebuffer::ByteBuffer;
use crate::database;
const POSITION_CELL_COUNT: u32 = 3;
pub const POSITION_CELL_COUNT: u16 = 3;
const START_OF_CONTENT_AREA: u32 = 5;
pub enum PageType {
@ -11,16 +12,16 @@ pub enum PageType {
/// Represents an SQLite page
pub struct Page {
data: ByteBuffer,
key: i64,
pub key: u64,
children: Vec<Page>,
number: u32,
page_type: PageType,
}
impl Page {
fn with_capacity(size: u16, page_type: PageType) -> Self {
pub fn with_capacity(size: u16, page_type: PageType) -> Self {
Self {
data: ByteBuffer::new(size as usize),
data: ByteBuffer::new(size as u16),
key: 0,
children: Vec::new(),
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);
page.put_u8(database::TABLE_LEAF_PAGE);
page
}
fn new_interior() -> Self {
pub fn new_interior() -> Self {
let mut page = Page::with_capacity(database::DEFAULT_PAGE_SIZE, PageType::Interior);
page.put_u8(database::TABLE_LEAF_PAGE);
page
@ -44,22 +45,41 @@ impl Page {
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;
}
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;
}
pub fn get_bw_position(&self) -> u16 {
self.data.bw_position
}
pub fn put_u8a(&mut self, value: &[u8]) {
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) {
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) {
self.data.put_u16(value);
}
@ -70,6 +90,6 @@ impl Page {
// may panic
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::varint;
struct Record {
rowid: u64,
pub struct Record {
pub rowid: u64,
//or should it be i64??
values: Vec<Value>,
}
@ -20,14 +20,12 @@ impl Record {
self.values.push(value);
}
fn to_bytes(&self) -> Vec<u8> {
let record_length: usize = self.values.iter()
.map(|v| v.get_length())
.sum();
pub fn to_bytes(&self) -> Vec<u8> {
let record_length = self.get_length();
let length_bytes = varint::write(record_length as u64);
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(&rowid_bytes);
@ -48,6 +46,13 @@ impl Record {
}
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)]

View file

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