pub const V2_MAGIC: [u8; 8] = [b'S', b'Q', b'L', b'T', b'G', b'F', 0, 0];
pub const V2_FORMAT_VERSION: u32 = 3;
pub const V3_MAGIC: [u8; 8] = [b'S', b'Q', b'L', b'T', b'G', b'F', 0, 3];
pub const V3_FORMAT_VERSION: u32 = 4;
pub const V3_HEADER_SIZE: u64 = 112;
pub const DEFAULT_PAGE_SIZE: u64 = 4096;
pub const MAX_BTREE_HEIGHT: u32 = 4;
pub const PAGE_HEADER_SIZE: usize = 32;
pub const USABLE_PAGE_SIZE: usize = DEFAULT_PAGE_SIZE as usize - PAGE_HEADER_SIZE;
pub const MAX_KEYS_PER_PAGE: usize = 254;
pub const MAX_ENTRIES_PER_LEAF: usize = 254;
pub const MAX_CHILDREN_PER_PAGE: usize = MAX_KEYS_PER_PAGE + 1;
pub const DEFAULT_V3_FEATURE_FLAGS: u32 =
crate::backend::native::constants::DEFAULT_FEATURE_FLAGS | v3_flags::FLAG_V3_BTREE_INDEX;
pub const DEFAULT_SCHEMA_VERSION: u32 = 1;
pub mod v3_flags {
use crate::backend::native::constants;
pub use constants::FLAG_V2_FRAMED_RECORDS;
pub use constants::FLAG_V2_ATOMIC_COMMIT;
pub const FLAG_V3_BTREE_INDEX: u32 = 0x0000_0004;
pub const FLAG_V3_DYNAMIC_ALLOCATION: u32 = 0x0000_0008;
pub const DEFAULT: u32 = FLAG_V2_FRAMED_RECORDS
| FLAG_V2_ATOMIC_COMMIT
| FLAG_V3_BTREE_INDEX
| FLAG_V3_DYNAMIC_ALLOCATION;
}
pub mod checksum {
pub const XOR_SEED: u64 = 0x5A5A5A5A5A5A5A5A;
pub fn xor_checksum(data: &[u8]) -> u64 {
let mut checksum = XOR_SEED;
for (i, &byte) in data.iter().enumerate() {
checksum ^= (byte as u64) ^ (i as u64);
}
checksum
}
}
pub mod compression {
pub const MAX_ID_DELTA: u32 = u32::MAX;
pub const MAX_VARINT_BYTES: usize = 10;
pub const SINGLE_BYTE_VARINT_MAX: u64 = 0x7F;
pub const DELTA_ENCODING_SAVINGS: usize = 4;
pub const VARINT_SMALL_VALUE_SAVINGS: usize = 1;
}
pub mod page_size {
pub const DEFAULT_PAGE_SIZE: u32 = 4096;
pub const HDD_PAGE_SIZE: u32 = 16384;
pub const SSD_PAGE_SIZE: u32 = 4096;
pub const MIN_PAGE_SIZE: u32 = 2048;
pub const MAX_PAGE_SIZE: u32 = 65536;
}
pub mod node_cache {
pub const DEFAULT_CACHE_CAPACITY: usize = 1000;
pub const MAX_CACHE_CAPACITY: usize = 10000;
pub const MIN_CACHE_CAPACITY: usize = 100;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_v3_magic_distinguishes_from_v2() {
assert_eq!(V2_MAGIC[7], 0, "V2 magic should have 0 at position 7");
assert_eq!(V3_MAGIC[7], 3, "V3 magic should have 3 at position 7");
assert_eq!(
V3_MAGIC[0..7],
V2_MAGIC[0..7],
"V3 should preserve V2 magic prefix"
);
}
#[test]
fn test_v3_format_version_greater_than_v2() {
assert!(
V3_FORMAT_VERSION > V2_FORMAT_VERSION,
"V3 format version ({}) should be greater than V2 ({})",
V3_FORMAT_VERSION,
V2_FORMAT_VERSION
);
}
#[test]
fn test_v3_header_size() {
let v2_header_size = crate::backend::native::constants::HEADER_SIZE;
assert_eq!(v2_header_size, 80, "V2 header should be 80 bytes");
assert_eq!(V3_HEADER_SIZE, 112, "V3 header should be 112 bytes");
assert_eq!(
V3_HEADER_SIZE,
v2_header_size + 32,
"V3 should extend V2 by 32 bytes"
);
}
#[test]
fn test_page_size_calculation() {
assert_eq!(DEFAULT_PAGE_SIZE, 4096, "Default page size should be 4KB");
assert_eq!(
PAGE_HEADER_SIZE + USABLE_PAGE_SIZE,
DEFAULT_PAGE_SIZE as usize,
"Page header + usable should equal total page size"
);
}
#[test]
fn test_btree_capacity() {
assert!(
MAX_BTREE_HEIGHT >= 4,
"Max B+Tree height should be at least 4"
);
assert!(MAX_KEYS_PER_PAGE == 254, "Max keys per page should be 254");
assert!(
MAX_CHILDREN_PER_PAGE == MAX_KEYS_PER_PAGE + 1,
"Max children should be max keys + 1"
);
}
#[test]
fn test_checksum_deterministic() {
let data = b"Hello, V3!";
let checksum1 = checksum::xor_checksum(data);
let checksum2 = checksum::xor_checksum(data);
assert_eq!(checksum1, checksum2, "Checksum should be deterministic");
let different_data = b"Hello, V2!";
let checksum3 = checksum::xor_checksum(different_data);
assert_ne!(
checksum1, checksum3,
"Different data should produce different checksums"
);
}
}