use crate::constants::ROOT_MANIFEST_MAGIC;
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct EntrypointPtr {
pub seg_offset: u64,
pub block_offset: u32,
pub count: u32,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct TopLayerPtr {
pub seg_offset: u64,
pub block_offset: u32,
pub node_count: u32,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct CentroidPtr {
pub seg_offset: u64,
pub block_offset: u32,
pub count: u32,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct QuantDictPtr {
pub seg_offset: u64,
pub block_offset: u32,
pub size: u32,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct HotCachePtr {
pub seg_offset: u64,
pub block_offset: u32,
pub vector_count: u32,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct PrefetchMapPtr {
pub offset: u64,
pub entries: u32,
pub _pad: u32,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct Level0Root {
pub magic: u32,
pub version: u16,
pub flags: u16,
pub l1_manifest_offset: u64,
pub l1_manifest_length: u64,
pub total_vector_count: u64,
pub dimension: u16,
pub base_dtype: u8,
pub profile_id: u8,
pub epoch: u32,
pub created_ns: u64,
pub modified_ns: u64,
pub entrypoint: EntrypointPtr,
pub toplayer: TopLayerPtr,
pub centroid: CentroidPtr,
pub quantdict: QuantDictPtr,
pub hot_cache: HotCachePtr,
pub prefetch_map: PrefetchMapPtr,
pub sig_algo: u16,
pub sig_length: u16,
pub signature_buf: [u8; Self::SIG_BUF_SIZE],
pub reserved: [u8; 252],
pub root_checksum: u32,
}
const _: () = assert!(core::mem::size_of::<Level0Root>() == 4096);
impl Level0Root {
pub const SIG_BUF_SIZE: usize = 3684;
pub const fn zeroed() -> Self {
Self {
magic: ROOT_MANIFEST_MAGIC,
version: 0,
flags: 0,
l1_manifest_offset: 0,
l1_manifest_length: 0,
total_vector_count: 0,
dimension: 0,
base_dtype: 0,
profile_id: 0,
epoch: 0,
created_ns: 0,
modified_ns: 0,
entrypoint: EntrypointPtr {
seg_offset: 0,
block_offset: 0,
count: 0,
},
toplayer: TopLayerPtr {
seg_offset: 0,
block_offset: 0,
node_count: 0,
},
centroid: CentroidPtr {
seg_offset: 0,
block_offset: 0,
count: 0,
},
quantdict: QuantDictPtr {
seg_offset: 0,
block_offset: 0,
size: 0,
},
hot_cache: HotCachePtr {
seg_offset: 0,
block_offset: 0,
vector_count: 0,
},
prefetch_map: PrefetchMapPtr {
offset: 0,
entries: 0,
_pad: 0,
},
sig_algo: 0,
sig_length: 0,
signature_buf: [0u8; Self::SIG_BUF_SIZE],
reserved: [0u8; 252],
root_checksum: 0,
}
}
#[inline]
pub const fn is_valid_magic(&self) -> bool {
self.magic == ROOT_MANIFEST_MAGIC
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn level0_root_size_is_4096() {
assert_eq!(core::mem::size_of::<Level0Root>(), 4096);
}
#[test]
fn zeroed_has_valid_magic() {
let root = Level0Root::zeroed();
assert!(root.is_valid_magic());
}
#[test]
fn field_offsets() {
let root = Level0Root::zeroed();
let base = core::ptr::addr_of!(root) as usize;
let magic_off = core::ptr::addr_of!(root.magic) as usize - base;
let version_off = core::ptr::addr_of!(root.version) as usize - base;
let flags_off = core::ptr::addr_of!(root.flags) as usize - base;
let l1_offset_off = core::ptr::addr_of!(root.l1_manifest_offset) as usize - base;
let l1_length_off = core::ptr::addr_of!(root.l1_manifest_length) as usize - base;
let total_vec_off = core::ptr::addr_of!(root.total_vector_count) as usize - base;
let dim_off = core::ptr::addr_of!(root.dimension) as usize - base;
let dtype_off = core::ptr::addr_of!(root.base_dtype) as usize - base;
let profile_off = core::ptr::addr_of!(root.profile_id) as usize - base;
let epoch_off = core::ptr::addr_of!(root.epoch) as usize - base;
let created_off = core::ptr::addr_of!(root.created_ns) as usize - base;
let modified_off = core::ptr::addr_of!(root.modified_ns) as usize - base;
let entry_off = core::ptr::addr_of!(root.entrypoint) as usize - base;
let toplayer_off = core::ptr::addr_of!(root.toplayer) as usize - base;
let centroid_off = core::ptr::addr_of!(root.centroid) as usize - base;
let quantdict_off = core::ptr::addr_of!(root.quantdict) as usize - base;
let hot_cache_off = core::ptr::addr_of!(root.hot_cache) as usize - base;
let prefetch_off = core::ptr::addr_of!(root.prefetch_map) as usize - base;
let sig_algo_off = core::ptr::addr_of!(root.sig_algo) as usize - base;
let sig_len_off = core::ptr::addr_of!(root.sig_length) as usize - base;
let sig_buf_off = core::ptr::addr_of!(root.signature_buf) as usize - base;
let reserved_off = core::ptr::addr_of!(root.reserved) as usize - base;
let checksum_off = core::ptr::addr_of!(root.root_checksum) as usize - base;
assert_eq!(magic_off, 0x000);
assert_eq!(version_off, 0x004);
assert_eq!(flags_off, 0x006);
assert_eq!(l1_offset_off, 0x008);
assert_eq!(l1_length_off, 0x010);
assert_eq!(total_vec_off, 0x018);
assert_eq!(dim_off, 0x020);
assert_eq!(dtype_off, 0x022);
assert_eq!(profile_off, 0x023);
assert_eq!(epoch_off, 0x024);
assert_eq!(created_off, 0x028);
assert_eq!(modified_off, 0x030);
assert_eq!(entry_off, 0x038);
assert_eq!(toplayer_off, 0x048);
assert_eq!(centroid_off, 0x058);
assert_eq!(quantdict_off, 0x068);
assert_eq!(hot_cache_off, 0x078);
assert_eq!(prefetch_off, 0x088);
assert_eq!(sig_algo_off, 0x098);
assert_eq!(sig_len_off, 0x09A);
assert_eq!(sig_buf_off, 0x09C);
assert_eq!(reserved_off, 0xF00);
assert_eq!(checksum_off, 0xFFC);
}
#[test]
fn hotset_pointer_sizes() {
assert_eq!(core::mem::size_of::<EntrypointPtr>(), 16);
assert_eq!(core::mem::size_of::<TopLayerPtr>(), 16);
assert_eq!(core::mem::size_of::<CentroidPtr>(), 16);
assert_eq!(core::mem::size_of::<QuantDictPtr>(), 16);
assert_eq!(core::mem::size_of::<HotCachePtr>(), 16);
assert_eq!(core::mem::size_of::<PrefetchMapPtr>(), 16);
}
}