csv_base/src/page.rs
2025-02-20 21:43:28 +01:00

86 lines
2.4 KiB
Rust

use crate::record::Record;
use crate::value::Value;
use crate::varint;
use byteorder::{BigEndian, ByteOrder};
const PAGE_SIZE: usize = 4096;
#[derive(Debug)]
pub enum PageType {
Root,
Interior,
Leaf,
}
#[derive(Debug)]
pub struct Page {
pagetype: PageType,
id: usize, // rowid
start: Value, // first value in page
end: Value, // last value in page
data: Vec<u8>, // page data
index_pos: u16, // current write position for indexes (to the page data)
data_pos: u16, // current write position for data (written backwards from the end of the page)
key: usize, // ?
children: Vec<Page>, // child pages
n_records: usize, // nr of records in the page
}
impl Page {
pub fn new(pagetype: PageType, id: usize) -> Self {
Self {
pagetype,
id,
start: Value::null(),
end: Value::null(),
data: vec![0; PAGE_SIZE],
index_pos: 0,
data_pos: (PAGE_SIZE - 1) as u16,
key: 0,
children: vec![],
n_records: 0,
}
}
pub fn insert(&mut self, record: Record) {
let bytes: Vec<u8> = record.into();
self.insert_data(bytes);
self.insert_index(self.data_pos);
self.n_records += 1;
}
fn insert_data(&mut self, bytes: Vec<u8>) {
let end = self.data_pos as usize;
self.data_pos -= bytes.len() as u16;
self.data.splice(self.data_pos as usize..end, bytes);
}
fn insert_index(&mut self, value: u16) {
let bytes = u16_to_bytes(value);
let start = self.index_pos as usize;
self.index_pos += bytes.len() as u16;
self.data.splice(start..self.index_pos as usize, bytes);
}
pub fn get(&self, row_index: usize) -> Option<Record> {
if row_index < self.n_records {
let physical_index = BigEndian::read_u16(&self.data[row_index * 2..=row_index * 2 + 1]);
let (bytes_read, len) = varint::read(&self.data[physical_index as usize..]);
Some(
(
len,
&self.data[bytes_read + physical_index as usize..=bytes_read + physical_index as usize + len as usize],
)
.into(),
)
} else {
None
}
}
}
fn u16_to_bytes(value: u16) -> Vec<u8> {
let mut buf = vec![0; 2];
BigEndian::write_u16(&mut buf, value);
buf
}