From a50934393ec9abfe13aa9e322aa069ce7b45d5ca Mon Sep 17 00:00:00 2001 From: Sander Hautvast Date: Fri, 28 Oct 2022 16:35:55 +0200 Subject: [PATCH] added the builder --- src/builder.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/bytebuffer.rs | 24 ++++++++++++++++-------- src/lib.rs | 2 +- src/page.rs | 38 +++++++++++++++++++++++++++++--------- src/record.rs | 19 ++++++++++++------- src/values.rs | 4 ++-- 6 files changed, 104 insertions(+), 27 deletions(-) create mode 100644 src/builder.rs diff --git a/src/builder.rs b/src/builder.rs new file mode 100644 index 0000000..3e1b4c5 --- /dev/null +++ b/src/builder.rs @@ -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, +} + + +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()); + } +} + diff --git a/src/bytebuffer.rs b/src/bytebuffer.rs index 235f416..9490de3 100644 --- a/src/bytebuffer.rs +++ b/src/bytebuffer.rs @@ -6,14 +6,14 @@ use byteorder::{BigEndian, ByteOrder}; /// - big endian only pub struct ByteBuffer { pub data: Vec, - 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) { 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) { + self.bw_position -= bytes.len() as u16; + for v in bytes { + self.data[self.bw_position as usize] = v; self.bw_position += 1; } } diff --git a/src/lib.rs b/src/lib.rs index 5b0ccc0..9a14b38 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ mod bytebuffer; mod values; mod varint; mod record; - +mod builder; #[cfg(test)] diff --git a/src/page.rs b/src/page.rs index b2f5a7b..9710d2b 100644 --- a/src/page.rs +++ b/src/page.rs @@ -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, 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) { + 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 } } \ No newline at end of file diff --git a/src/record.rs b/src/record.rs index 3386375..dd720b3 100644 --- a/src/record.rs +++ b/src/record.rs @@ -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, } @@ -20,14 +20,12 @@ impl Record { self.values.push(value); } - fn to_bytes(&self) -> Vec { - let record_length: usize = self.values.iter() - .map(|v| v.get_length()) - .sum(); + pub fn to_bytes(&self) -> Vec { + 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)] diff --git a/src/values.rs b/src/values.rs index 204fe83..e942b60 100644 --- a/src/values.rs +++ b/src/values.rs @@ -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 } }