use std::fs::File;
use std::io::{BufRead, BufReader, Read};
use std::ptr;
use crate::page::*;
use crate::record::*;
use crate::Error;
#[derive(Debug, Clone)]
pub struct DataPage {
pub pag: Page,
pub sequence: u32,
pub relation: u16,
pub count: u16,
pub records: Vec<DataPageRecord>,
pub raw: Vec<u8>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct DataPageRep {
pub pag: Page,
pub sequence: u32,
pub relation: u16,
pub count: u16,
pub records: [DataPageRecord; 512], }
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct DataPageRecord {
pub offset: u16,
pub length: u16,
}
impl DataPage {
pub fn from_bytes(bytes: Vec<u8>) -> Result<DataPage, Error> {
if bytes[0] != 0x05 {
return Err(Error::InvalidPage {
tpe: bytes[0],
expected: 0x05,
desc: "data".to_string(),
});
}
let rdata: DataPageRep = unsafe { ptr::read(bytes.as_ptr() as *const _) };
if rdata.count > 512 {
return Err(Error::Overflow {
limit: 512,
value: rdata.count as usize,
msg: "supported records".to_string(),
});
}
let mut records = rdata.records.to_vec();
records.truncate(rdata.count as usize);
let data = DataPage {
pag: rdata.pag,
sequence: rdata.sequence,
relation: rdata.relation,
count: rdata.count,
records,
raw: bytes,
};
Ok(data)
}
pub fn load(header: HeaderPage, buffer: &mut BufReader<File>) -> Result<Vec<DataPage>, Error> {
let mut pgt = [0 as u8; 1];
let mut pages = vec![];
while buffer.read(&mut pgt)? > 0 {
if pgt[0] == 0x05 {
buffer.seek_relative(-1)?;
let mut poip = vec![0 as u8; header.page_size.into()];
buffer.read_exact(&mut poip)?;
let data = DataPage::from_bytes(poip.clone())?;
pages.push(data);
} else {
buffer.consume((header.page_size - 1).into());
}
}
Ok(pages)
}
pub fn get_records(&self) -> Result<Vec<RecordHeader>, Error> {
let mut records = vec![];
for idx in self.records.clone() {
let orec = self.get_record(idx)?;
if let Some(rec) = orec {
records.push(rec);
}
}
Ok(records)
}
pub fn get_record(&self, idx: DataPageRecord) -> Result<Option<RecordHeader>, Error> {
if idx.length == 0 {
return Ok(None);
}
let rpoip = self.raw[idx.offset as usize..(idx.offset + idx.length) as usize].to_vec();
let rec = RecordHeader::from_bytes(rpoip)?;
Ok(Some(rec))
}
}