use crate::backend::native::NativeBackendError;
use crate::backend::native::NativeResult;
use crate::backend::native::v3::constants as v3_constants;
mod serde_support;
#[cfg(test)]
mod tests;
pub mod constants {
pub const PAGE_HEADER_SIZE: usize = 32;
pub const PAGE_ID_OFFSET: usize = 0;
pub const IS_LEAF_OFFSET: usize = 8;
pub const IS_ROOT_OFFSET: usize = 9;
pub const COUNT_OFFSET: usize = 10;
pub const CHECKSUM_OFFSET: usize = 12;
pub const PADDING_OFFSET: usize = 16;
pub const DATA_START_OFFSET: usize = PAGE_HEADER_SIZE;
}
pub const MAX_KEYS: usize = 252;
pub const MIN_KEYS: usize = 125;
pub const MAX_ENTRIES: usize = 252;
pub const MIN_ENTRIES: usize = 126;
pub const MAX_CHILDREN: usize = MAX_KEYS + 1;
pub const KEY_SIZE: usize = 8;
pub const PAGE_ID_SIZE: usize = 8;
pub const ENTRY_SIZE: usize = KEY_SIZE + PAGE_ID_SIZE;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum IndexPageType {
Internal,
Leaf,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum IndexPage {
Internal {
page_id: u64,
keys: Vec<u64>,
children: Vec<u64>,
checksum: u32,
is_root: bool,
},
Leaf {
page_id: u64,
entries: Vec<(u64, u64)>,
next_leaf: u64,
checksum: u32,
is_root: bool,
},
}
impl IndexPage {
pub fn page_id(&self) -> u64 {
match self {
IndexPage::Internal { page_id, .. } => *page_id,
IndexPage::Leaf { page_id, .. } => *page_id,
}
}
pub fn page_type(&self) -> IndexPageType {
match self {
IndexPage::Internal { .. } => IndexPageType::Internal,
IndexPage::Leaf { .. } => IndexPageType::Leaf,
}
}
pub fn count(&self) -> usize {
match self {
IndexPage::Internal { keys, .. } => keys.len(),
IndexPage::Leaf { entries, .. } => entries.len(),
}
}
pub fn new_internal(page_id: u64) -> Self {
IndexPage::Internal {
page_id,
keys: Vec::new(),
children: Vec::new(),
checksum: 0,
is_root: false,
}
}
pub fn new_internal_root(page_id: u64) -> Self {
IndexPage::Internal {
page_id,
keys: Vec::new(),
children: Vec::new(),
checksum: 0,
is_root: true,
}
}
pub fn new_leaf(page_id: u64) -> Self {
IndexPage::Leaf {
page_id,
entries: Vec::new(),
next_leaf: 0,
checksum: 0,
is_root: false,
}
}
pub fn new_leaf_root(page_id: u64) -> Self {
IndexPage::Leaf {
page_id,
entries: Vec::new(),
next_leaf: 0,
checksum: 0,
is_root: true,
}
}
pub fn is_root(&self) -> bool {
match self {
IndexPage::Internal { is_root, .. } => *is_root,
IndexPage::Leaf { is_root, .. } => *is_root,
}
}
pub fn set_root(&mut self, root: bool) {
match self {
IndexPage::Internal { is_root, .. } => *is_root = root,
IndexPage::Leaf { is_root, .. } => *is_root = root,
}
}
pub fn is_full_internal(&self) -> bool {
match self {
IndexPage::Internal { keys, .. } => keys.len() >= MAX_KEYS,
_ => false,
}
}
pub fn is_full_leaf(&self) -> bool {
match self {
IndexPage::Leaf { entries, .. } => entries.len() >= MAX_ENTRIES,
_ => false,
}
}
pub fn needs_split_internal(&self) -> bool {
match self {
IndexPage::Internal { keys, .. } => keys.len() >= MAX_KEYS,
_ => false,
}
}
pub fn needs_split_leaf(&self) -> bool {
match self {
IndexPage::Leaf { entries, .. } => entries.len() >= MAX_ENTRIES,
_ => false,
}
}
pub fn binary_search_leaf(entries: &[(u64, u64)], target: u64) -> Result<usize, usize> {
entries.binary_search_by_key(&target, |&(node_id, _)| node_id)
}
pub fn find_child_index(keys: &[u64], target: u64) -> usize {
match keys.binary_search(&target) {
Ok(idx) => idx + 1,
Err(idx) => idx,
}
}
}