1use crate::constants::ROOT_MANIFEST_MAGIC;
7
8#[derive(Clone, Copy, Debug)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13#[repr(C)]
14pub struct EntrypointPtr {
15 pub seg_offset: u64,
17 pub block_offset: u32,
19 pub count: u32,
21}
22
23#[derive(Clone, Copy, Debug)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28#[repr(C)]
29pub struct TopLayerPtr {
30 pub seg_offset: u64,
32 pub block_offset: u32,
34 pub node_count: u32,
36}
37
38#[derive(Clone, Copy, Debug)]
42#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
43#[repr(C)]
44pub struct CentroidPtr {
45 pub seg_offset: u64,
47 pub block_offset: u32,
49 pub count: u32,
51}
52
53#[derive(Clone, Copy, Debug)]
57#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
58#[repr(C)]
59pub struct QuantDictPtr {
60 pub seg_offset: u64,
62 pub block_offset: u32,
64 pub size: u32,
66}
67
68#[derive(Clone, Copy, Debug)]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73#[repr(C)]
74pub struct HotCachePtr {
75 pub seg_offset: u64,
77 pub block_offset: u32,
79 pub vector_count: u32,
81}
82
83#[derive(Clone, Copy, Debug)]
87#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
88#[repr(C)]
89pub struct PrefetchMapPtr {
90 pub offset: u64,
92 pub entries: u32,
94 pub _pad: u32,
96}
97
98#[derive(Clone, Copy, Debug)]
131#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
132#[repr(C)]
133pub struct Level0Root {
134 pub magic: u32,
137 pub version: u16,
139 pub flags: u16,
141 pub l1_manifest_offset: u64,
143 pub l1_manifest_length: u64,
145 pub total_vector_count: u64,
147 pub dimension: u16,
149 pub base_dtype: u8,
151 pub profile_id: u8,
153 pub epoch: u32,
155 pub created_ns: u64,
157 pub modified_ns: u64,
159
160 pub entrypoint: EntrypointPtr,
163 pub toplayer: TopLayerPtr,
165 pub centroid: CentroidPtr,
167 pub quantdict: QuantDictPtr,
169 pub hot_cache: HotCachePtr,
171 pub prefetch_map: PrefetchMapPtr,
173
174 pub sig_algo: u16,
177 pub sig_length: u16,
179 pub signature_buf: [u8; Self::SIG_BUF_SIZE],
181
182 pub reserved: [u8; 252],
185 pub root_checksum: u32,
187}
188
189const _: () = assert!(core::mem::size_of::<Level0Root>() == 4096);
191
192impl Level0Root {
193 pub const SIG_BUF_SIZE: usize = 3684;
196
197 pub const fn zeroed() -> Self {
199 Self {
200 magic: ROOT_MANIFEST_MAGIC,
201 version: 0,
202 flags: 0,
203 l1_manifest_offset: 0,
204 l1_manifest_length: 0,
205 total_vector_count: 0,
206 dimension: 0,
207 base_dtype: 0,
208 profile_id: 0,
209 epoch: 0,
210 created_ns: 0,
211 modified_ns: 0,
212 entrypoint: EntrypointPtr {
213 seg_offset: 0,
214 block_offset: 0,
215 count: 0,
216 },
217 toplayer: TopLayerPtr {
218 seg_offset: 0,
219 block_offset: 0,
220 node_count: 0,
221 },
222 centroid: CentroidPtr {
223 seg_offset: 0,
224 block_offset: 0,
225 count: 0,
226 },
227 quantdict: QuantDictPtr {
228 seg_offset: 0,
229 block_offset: 0,
230 size: 0,
231 },
232 hot_cache: HotCachePtr {
233 seg_offset: 0,
234 block_offset: 0,
235 vector_count: 0,
236 },
237 prefetch_map: PrefetchMapPtr {
238 offset: 0,
239 entries: 0,
240 _pad: 0,
241 },
242 sig_algo: 0,
243 sig_length: 0,
244 signature_buf: [0u8; Self::SIG_BUF_SIZE],
245 reserved: [0u8; 252],
246 root_checksum: 0,
247 }
248 }
249
250 #[inline]
252 pub const fn is_valid_magic(&self) -> bool {
253 self.magic == ROOT_MANIFEST_MAGIC
254 }
255}
256
257#[cfg(test)]
258mod tests {
259 use super::*;
260
261 #[test]
262 fn level0_root_size_is_4096() {
263 assert_eq!(core::mem::size_of::<Level0Root>(), 4096);
264 }
265
266 #[test]
267 fn zeroed_has_valid_magic() {
268 let root = Level0Root::zeroed();
269 assert!(root.is_valid_magic());
270 }
271
272 #[test]
273 fn field_offsets() {
274 let root = Level0Root::zeroed();
275 let base = core::ptr::addr_of!(root) as usize;
276
277 let magic_off = core::ptr::addr_of!(root.magic) as usize - base;
279 let version_off = core::ptr::addr_of!(root.version) as usize - base;
280 let flags_off = core::ptr::addr_of!(root.flags) as usize - base;
281 let l1_offset_off = core::ptr::addr_of!(root.l1_manifest_offset) as usize - base;
282 let l1_length_off = core::ptr::addr_of!(root.l1_manifest_length) as usize - base;
283 let total_vec_off = core::ptr::addr_of!(root.total_vector_count) as usize - base;
284 let dim_off = core::ptr::addr_of!(root.dimension) as usize - base;
285 let dtype_off = core::ptr::addr_of!(root.base_dtype) as usize - base;
286 let profile_off = core::ptr::addr_of!(root.profile_id) as usize - base;
287 let epoch_off = core::ptr::addr_of!(root.epoch) as usize - base;
288 let created_off = core::ptr::addr_of!(root.created_ns) as usize - base;
289 let modified_off = core::ptr::addr_of!(root.modified_ns) as usize - base;
290 let entry_off = core::ptr::addr_of!(root.entrypoint) as usize - base;
291 let toplayer_off = core::ptr::addr_of!(root.toplayer) as usize - base;
292 let centroid_off = core::ptr::addr_of!(root.centroid) as usize - base;
293 let quantdict_off = core::ptr::addr_of!(root.quantdict) as usize - base;
294 let hot_cache_off = core::ptr::addr_of!(root.hot_cache) as usize - base;
295 let prefetch_off = core::ptr::addr_of!(root.prefetch_map) as usize - base;
296 let sig_algo_off = core::ptr::addr_of!(root.sig_algo) as usize - base;
297 let sig_len_off = core::ptr::addr_of!(root.sig_length) as usize - base;
298 let sig_buf_off = core::ptr::addr_of!(root.signature_buf) as usize - base;
299 let reserved_off = core::ptr::addr_of!(root.reserved) as usize - base;
300 let checksum_off = core::ptr::addr_of!(root.root_checksum) as usize - base;
301
302 assert_eq!(magic_off, 0x000);
303 assert_eq!(version_off, 0x004);
304 assert_eq!(flags_off, 0x006);
305 assert_eq!(l1_offset_off, 0x008);
306 assert_eq!(l1_length_off, 0x010);
307 assert_eq!(total_vec_off, 0x018);
308 assert_eq!(dim_off, 0x020);
309 assert_eq!(dtype_off, 0x022);
310 assert_eq!(profile_off, 0x023);
311 assert_eq!(epoch_off, 0x024);
312 assert_eq!(created_off, 0x028);
313 assert_eq!(modified_off, 0x030);
314 assert_eq!(entry_off, 0x038);
315 assert_eq!(toplayer_off, 0x048);
316 assert_eq!(centroid_off, 0x058);
317 assert_eq!(quantdict_off, 0x068);
318 assert_eq!(hot_cache_off, 0x078);
319 assert_eq!(prefetch_off, 0x088);
320 assert_eq!(sig_algo_off, 0x098);
321 assert_eq!(sig_len_off, 0x09A);
322 assert_eq!(sig_buf_off, 0x09C);
323 assert_eq!(reserved_off, 0xF00);
324 assert_eq!(checksum_off, 0xFFC);
325 }
326
327 #[test]
328 fn hotset_pointer_sizes() {
329 assert_eq!(core::mem::size_of::<EntrypointPtr>(), 16);
330 assert_eq!(core::mem::size_of::<TopLayerPtr>(), 16);
331 assert_eq!(core::mem::size_of::<CentroidPtr>(), 16);
332 assert_eq!(core::mem::size_of::<QuantDictPtr>(), 16);
333 assert_eq!(core::mem::size_of::<HotCachePtr>(), 16);
334 assert_eq!(core::mem::size_of::<PrefetchMapPtr>(), 16);
335 }
336}