use crate::page::PAGE_SIZE;
pub const SA_MAGIC: u32 = 0xDA7A_BA5E;
pub const SA_COPYRIGHT_MARKER: &[u8] = b"SAP SE, Copyright (c)2015 17.0.4.";
#[derive(Debug, Clone, Copy)]
pub struct Superblock {
pub flags_06: u8,
pub file_id_lo: u32,
pub format_major: u32,
pub magic: u32,
pub version_a: u16,
pub version_b: u16,
pub page_count_hint: u32,
pub sa_marker_present: bool,
}
impl Superblock {
pub fn parse(page0: &[u8]) -> Self {
assert_eq!(page0.len(), PAGE_SIZE, "page 0 must be exactly 4096 bytes");
let flags_06 = page0[0x06];
let file_id_lo = u32::from_le_bytes(page0[0x08..0x0C].try_into().unwrap());
let format_major = u32::from_le_bytes(page0[0x10..0x14].try_into().unwrap());
let magic = u32::from_le_bytes(page0[0x14..0x18].try_into().unwrap());
let version_a = u16::from_le_bytes(page0[0x18..0x1A].try_into().unwrap());
let version_b = u16::from_le_bytes(page0[0x1A..0x1C].try_into().unwrap());
let page_count_hint = u32::from_le_bytes(page0[0x1C..0x20].try_into().unwrap());
let sa_marker_present = memmem(page0, SA_COPYRIGHT_MARKER).is_some();
Superblock {
flags_06,
file_id_lo,
format_major,
magic,
version_a,
version_b,
page_count_hint,
sa_marker_present,
}
}
#[inline]
pub fn magic_ok(&self) -> bool {
self.magic == SA_MAGIC
}
}
fn memmem(haystack: &[u8], needle: &[u8]) -> Option<usize> {
if needle.is_empty() || haystack.len() < needle.len() {
return None;
}
haystack.windows(needle.len()).position(|w| w == needle)
}