use crate::error::{Result, SQLRiteError};
use crate::sql::pager::page::PAGE_SIZE;
pub const MAGIC: &[u8; 16] = b"SQLRiteFormat\0\0\0";
pub const FORMAT_VERSION: u16 = 4;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DbHeader {
pub page_count: u32,
pub schema_root_page: u32,
}
pub fn encode_header(h: &DbHeader) -> [u8; PAGE_SIZE] {
let mut buf = [0u8; PAGE_SIZE];
buf[0..16].copy_from_slice(MAGIC);
buf[16..18].copy_from_slice(&FORMAT_VERSION.to_le_bytes());
buf[18..20].copy_from_slice(&(PAGE_SIZE as u16).to_le_bytes());
buf[20..24].copy_from_slice(&h.page_count.to_le_bytes());
buf[24..28].copy_from_slice(&h.schema_root_page.to_le_bytes());
buf
}
pub fn decode_header(buf: &[u8]) -> Result<DbHeader> {
if buf.len() != PAGE_SIZE {
return Err(SQLRiteError::Internal(format!(
"header buffer length {} != PAGE_SIZE {PAGE_SIZE}",
buf.len()
)));
}
if &buf[0..16] != MAGIC {
return Err(SQLRiteError::General(
"file is not a SQLRite database (bad magic bytes)".to_string(),
));
}
let version = u16::from_le_bytes(buf[16..18].try_into().unwrap());
if version != FORMAT_VERSION {
return Err(SQLRiteError::General(format!(
"unsupported SQLRite format version {version}; this build understands {FORMAT_VERSION}"
)));
}
let page_size = u16::from_le_bytes(buf[18..20].try_into().unwrap()) as usize;
if page_size != PAGE_SIZE {
return Err(SQLRiteError::General(format!(
"unsupported page size {page_size}; this build expects {PAGE_SIZE}"
)));
}
let page_count = u32::from_le_bytes(buf[20..24].try_into().unwrap());
let schema_root_page = u32::from_le_bytes(buf[24..28].try_into().unwrap());
Ok(DbHeader {
page_count,
schema_root_page,
})
}