diff --git a/Cargo.toml b/Cargo.toml index 287f2ee..1e13cba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -byteorder = "1.4.3" \ No newline at end of file +byteorder = "1.4.3" + +[lib] +name = "sqlighters" +crate-type = ["lib"] \ No newline at end of file diff --git a/src/builder.rs b/src/builder.rs index 3e1b4c5..c34069f 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,4 +1,5 @@ use std::mem; +use crate::database::{Database, SchemaRecord}; use crate::page::{self, Page}; use crate::record::Record; @@ -6,6 +7,7 @@ struct Builder { current_page: Page, n_records_on_current_page: u16, leaf_pages: Vec, + schema: Option, } @@ -15,6 +17,7 @@ impl Builder { current_page: Page::new_leaf(), n_records_on_current_page: 0, leaf_pages: Vec::new(), + schema: None, } } @@ -31,6 +34,23 @@ impl Builder { self.n_records_on_current_page += 1; } + pub fn schema(&mut self, schema: SchemaRecord) { + self.schema = Some(schema); + } + + pub fn build(mut self) -> Database { + self.current_page.set_fw_position(page::POSITION_CELL_COUNT); + self.current_page.put_u16(self.n_records_on_current_page); + + if self.n_records_on_current_page > 0 { + self.current_page.put_u16(self.current_page.get_bw_position()); + } else { + self.current_page.put_u16(self.current_page.get_bw_position() - 1); + } + + Database::new(self.schema.unwrap(), self.leaf_pages) //panics is schema is not set + } + 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 } diff --git a/src/bytebuffer.rs b/src/bytebuffer.rs index 9490de3..512ff92 100644 --- a/src/bytebuffer.rs +++ b/src/bytebuffer.rs @@ -20,14 +20,7 @@ impl ByteBuffer { } /// forward put unsigned byte array - pub fn put_u8a(&mut self, bytes: &[u8]) { - for v in bytes { - self.data[self.fw_position as usize] = *v; - self.fw_position += 1; - } - } - - pub fn put_u8v(&mut self, bytes: &Vec) { + pub fn put_bytes(&mut self, bytes: &[u8]) { for v in bytes { self.data[self.fw_position as usize] = *v; self.fw_position += 1; @@ -35,7 +28,7 @@ impl ByteBuffer { } /// backward put unsigned byte array - pub fn put_u8a_bw(&mut self, bytes: &[u8]) { + pub fn put_bytes_bw(&mut self, bytes: &[u8]) { self.bw_position -= bytes.len() as u16; for v in bytes { self.data[self.bw_position as usize] = *v; @@ -43,50 +36,42 @@ impl ByteBuffer { } } - 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; - } - } - /// forward put unsigned byte pub fn put_u8(&mut self, byte: u8) { - self.put_u8a(&[byte]); + self.put_bytes(&[byte]); } /// backward put unsigned byte pub fn put_u8_bw(&mut self, byte: u8) { - self.put_u8a_bw(&[byte]); + self.put_bytes_bw(&[byte]); } /// forward put unsigned 16bit integer pub fn put_u16(&mut self, val: u16) { let mut buf = [0; 2]; BigEndian::write_u16(&mut buf, val); - self.put_u8a(&buf); + self.put_bytes(&buf); } /// backward put unsigned 16bit integer pub fn put_u16_bw(&mut self, val: u16) { let mut buf = [0; 2]; BigEndian::write_u16(&mut buf, val); - self.put_u8a_bw(&buf); + self.put_bytes_bw(&buf); } /// forward put unsigned 16bit integer pub fn put_u32(&mut self, val: u32) { let mut buf = [0; 4]; BigEndian::write_u32(&mut buf, val); - self.put_u8a(&buf); + self.put_bytes(&buf); } /// backward put unsigned 32bit integer pub fn put_u32_bw(&mut self, val: u32) { let mut buf = [0; 4]; BigEndian::write_u32(&mut buf, val); - self.put_u8a_bw(&buf); + self.put_bytes_bw(&buf); } } @@ -104,7 +89,7 @@ mod tests { #[test] fn test_u8a() { let mut b = ByteBuffer::new(2); - b.put_u8a(&[1, 2]); + b.put_bytes(&[1, 2]); assert_eq!(b.data[0], 1); assert_eq!(b.data[1], 2); } diff --git a/src/database.rs b/src/database.rs index 12ef7b5..ad2db64 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,5 +1,21 @@ use crate::page::Page; +pub struct Database { + schema: SchemaRecord, + leaf_pages: Vec, +} + +impl Database { + pub fn new(schema: SchemaRecord, leaf_pages: Vec) -> Self { + Self { + schema, + leaf_pages, + } + } +} + +pub struct SchemaRecord {} + fn write_header(mut rootpage: Page, n_pages: u32) { rootpage.put_u8a(&MAGIC_HEADER); diff --git a/src/lib.rs b/src/lib.rs index 9a14b38..05edccd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + mod page; mod database; mod bytebuffer; diff --git a/src/page.rs b/src/page.rs index 9710d2b..074325b 100644 --- a/src/page.rs +++ b/src/page.rs @@ -61,15 +61,15 @@ impl Page { } pub fn put_u8a(&mut self, value: &[u8]) { - self.data.put_u8a(value); + self.data.put_bytes(value); } pub fn put_u8a_bw(&mut self, value: &[u8]) { - self.data.put_u8a_bw(value); + self.data.put_bytes_bw(value); } pub fn put_vec_u8_bw(&mut self, value: Vec) { - self.data.put_vec_u8_bw(value); + self.data.put_bytes_bw(&value); } pub fn put_u8(&mut self, value: u8) { diff --git a/src/record.rs b/src/record.rs index dd720b3..2ade232 100644 --- a/src/record.rs +++ b/src/record.rs @@ -26,23 +26,23 @@ impl Record { let rowid_bytes = varint::write(self.rowid); 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); + buffer.put_bytes(&length_bytes); + buffer.put_bytes(&rowid_bytes); // 'The initial portion of the payload that does not spill to overflow pages.' let length_of_encoded_column_types: usize = self.values.iter() .map(|v| v.datatype.len()) .sum(); - buffer.put_u8v(&varint::write((length_of_encoded_column_types + 1) as u64)); + buffer.put_bytes(&varint::write((length_of_encoded_column_types + 1) as u64)); //write all types for v in self.values.iter() { - buffer.put_u8v(&v.datatype) + buffer.put_bytes(&v.datatype) } // write all values for v in self.values.iter() { - buffer.put_u8v(&v.data) //copies individual bytes into a buffer...should I avoid copying? + buffer.put_bytes(&v.data) //copies individual bytes into a buffer...should I avoid copying? } buffer.data } diff --git a/src/values.rs b/src/values.rs index e942b60..b26b3f2 100644 --- a/src/values.rs +++ b/src/values.rs @@ -27,7 +27,7 @@ pub fn integer(value: i64) -> Value { } pub fn float(value: f64) -> Value { - let mut buffer = [0 as u8; 8]; + let mut buffer = [0_u8; 8]; BigEndian::write_f64(&mut buffer, value); Value { datatype: vec![7], data: buffer.to_vec() } } @@ -42,14 +42,14 @@ fn sqlite_integer_to_bytes(value: i64) -> Vec { if value == 0 || value == 1 { vec![] } else { - return i64_to_bytes(value, get_length_of_byte_encoding(value)); + i64_to_bytes(value, get_length_of_byte_encoding(value)) } } fn i64_to_bytes(n: i64, nbytes: u8) -> Vec { let mut bytes = vec![]; for i in 0..nbytes { - bytes.push(((n >> (nbytes - i - 1) * 8) & 0xFF) as u8); + bytes.push(((n >> ((nbytes - i - 1) * 8)) & 0xFF) as u8); } bytes