Skip to main content

zeppelin_embed/segment/
reader.rs

1//! Read-only memory-mapped segment validation and lazy region access.
2
3use std::fs::File;
4use std::os::fd::AsRawFd;
5use std::path::Path;
6#[cfg(any(test, feature = "test-support"))]
7use std::path::PathBuf;
8use std::ptr::NonNull;
9use std::sync::atomic::{AtomicU64, Ordering};
10use std::sync::{Arc, Mutex, OnceLock};
11
12use xxhash_rust::xxh3::xxh3_64;
13
14use crate::format::frame::{
15    FILE_HEADER_LEN, FILE_TRAILER_LEN, FormatCheck, FormatError, decode_header, read_u16, read_u32,
16    read_u64,
17};
18use crate::format::{FormatFamily, FormatRegistry};
19use crate::graph::block::{GraphNodeBlocks, ValidatedGraphNodeBlocks, decode_node_blocks};
20use crate::ingest::{DocId, DocumentVersion, Revision};
21use crate::meta::{AliveSet, ColumnStore};
22use crate::quant::Bit4Factors;
23use crate::vfs::Vfs;
24
25use super::layout::{
26    CHECKSUM_CHUNK_BYTES, Cursor, Int8Factors, REGION_ALIGNMENT, REGION_ENTRY_LEN, RegionEntry,
27    RegionKind, SEGMENT_PREFIX_LEN, VECTOR_HEADER_LEN, align_up, decode_alive, decode_columns,
28    decode_vector_header,
29};
30use super::{SegmentError, SegmentId, SegmentMeta};
31
32const MAX_SEGMENT_HEADER_BYTES: usize = 1024 * 1024;
33
34thread_local! {
35    static DATA_READ_AUDIT: std::cell::RefCell<Option<Arc<AtomicU64>>> = const {
36        std::cell::RefCell::new(None)
37    };
38}
39
40#[cfg(any(test, feature = "test-support"))]
41thread_local! {
42    static SEGMENT_COST_AUDIT: std::cell::RefCell<Option<Arc<SegmentCostCounters>>> = const {
43        std::cell::RefCell::new(None)
44    };
45}
46
47#[cfg(any(test, feature = "test-support"))]
48#[derive(Default)]
49struct SegmentCostCounters {
50    identity_hash_bytes: AtomicU64,
51    rescore_hash_bytes: AtomicU64,
52    int8_factor_decode_bytes: AtomicU64,
53    postings_hash_bytes: AtomicU64,
54    postings_decode_bytes: AtomicU64,
55    columns_hash_bytes: AtomicU64,
56    columns_decode_bytes: AtomicU64,
57    alive_hash_bytes: AtomicU64,
58    alive_decode_bytes: AtomicU64,
59}
60
61/// Test-only deterministic costs observed while reading immutable segments.
62#[cfg(any(test, feature = "test-support"))]
63#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
64pub struct SegmentCostSnapshot {
65    /// Bytes hashed while validating document identities.
66    pub identity_hash_bytes: u64,
67    /// Bytes hashed while validating exact-rescore rows.
68    pub rescore_hash_bytes: u64,
69    /// Int8 factor bytes decoded for scan validation.
70    pub int8_factor_decode_bytes: u64,
71    /// Bytes hashed while validating sealed postings.
72    pub postings_hash_bytes: u64,
73    /// Sealed-postings bytes heap-decoded into query-ready state.
74    pub postings_decode_bytes: u64,
75    /// Bytes hashed while validating typed columns.
76    pub columns_hash_bytes: u64,
77    /// Typed-column bytes heap-decoded into query-ready state.
78    pub columns_decode_bytes: u64,
79    /// Bytes hashed while validating alive state.
80    pub alive_hash_bytes: u64,
81    /// Alive-state bytes heap-decoded into query-ready state.
82    pub alive_decode_bytes: u64,
83}
84
85/// Test-only scoped collector for deterministic segment read-path costs.
86#[cfg(any(test, feature = "test-support"))]
87#[derive(Clone, Default)]
88pub struct SegmentCostAudit {
89    counters: Arc<SegmentCostCounters>,
90}
91
92#[cfg(any(test, feature = "test-support"))]
93struct SegmentCostAuditGuard {
94    previous: Option<Arc<SegmentCostCounters>>,
95}
96
97#[cfg(any(test, feature = "test-support"))]
98impl Drop for SegmentCostAuditGuard {
99    fn drop(&mut self) {
100        let previous = self.previous.take();
101        SEGMENT_COST_AUDIT.with(|slot| {
102            slot.replace(previous);
103        });
104    }
105}
106
107#[cfg(any(test, feature = "test-support"))]
108impl SegmentCostAudit {
109    /// Creates a zeroed cost collector.
110    #[must_use]
111    pub fn new() -> Self {
112        Self::default()
113    }
114
115    /// Runs one operation with this collector installed on the calling thread.
116    pub fn measure<T>(&self, operation: impl FnOnce() -> T) -> T {
117        let previous =
118            SEGMENT_COST_AUDIT.with(|slot| slot.replace(Some(Arc::clone(&self.counters))));
119        let _guard = SegmentCostAuditGuard { previous };
120        operation()
121    }
122
123    /// Returns the exact accumulated byte counters.
124    #[must_use]
125    pub fn snapshot(&self) -> SegmentCostSnapshot {
126        SegmentCostSnapshot {
127            identity_hash_bytes: self.counters.identity_hash_bytes.load(Ordering::Relaxed),
128            rescore_hash_bytes: self.counters.rescore_hash_bytes.load(Ordering::Relaxed),
129            int8_factor_decode_bytes: self
130                .counters
131                .int8_factor_decode_bytes
132                .load(Ordering::Relaxed),
133            postings_hash_bytes: self.counters.postings_hash_bytes.load(Ordering::Relaxed),
134            postings_decode_bytes: self.counters.postings_decode_bytes.load(Ordering::Relaxed),
135            columns_hash_bytes: self.counters.columns_hash_bytes.load(Ordering::Relaxed),
136            columns_decode_bytes: self.counters.columns_decode_bytes.load(Ordering::Relaxed),
137            alive_hash_bytes: self.counters.alive_hash_bytes.load(Ordering::Relaxed),
138            alive_decode_bytes: self.counters.alive_decode_bytes.load(Ordering::Relaxed),
139        }
140    }
141}
142
143#[cfg(any(test, feature = "test-support"))]
144fn account_region_hash(kind: RegionKind, bytes: usize) {
145    let bytes = u64::try_from(bytes).unwrap_or(u64::MAX);
146    SEGMENT_COST_AUDIT.with(|slot| {
147        let Some(counters) = slot.borrow().as_ref().cloned() else {
148            return;
149        };
150        let counter = match kind {
151            RegionKind::DocumentVersions => &counters.identity_hash_bytes,
152            RegionKind::VectorRescore => &counters.rescore_hash_bytes,
153            RegionKind::Postings => &counters.postings_hash_bytes,
154            RegionKind::Columns => &counters.columns_hash_bytes,
155            RegionKind::Alive => &counters.alive_hash_bytes,
156            _ => return,
157        };
158        let _ = counter.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| {
159            Some(current.saturating_add(bytes))
160        });
161    });
162}
163
164#[cfg(any(test, feature = "test-support"))]
165fn account_region_decode(kind: RegionKind, bytes: usize) {
166    let bytes = u64::try_from(bytes).unwrap_or(u64::MAX);
167    SEGMENT_COST_AUDIT.with(|slot| {
168        let Some(counters) = slot.borrow().as_ref().cloned() else {
169            return;
170        };
171        let counter = match kind {
172            RegionKind::VectorFactors => &counters.int8_factor_decode_bytes,
173            RegionKind::Postings => &counters.postings_decode_bytes,
174            RegionKind::Columns => &counters.columns_decode_bytes,
175            RegionKind::Alive => &counters.alive_decode_bytes,
176            _ => return,
177        };
178        let _ = counter.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| {
179            Some(current.saturating_add(bytes))
180        });
181    });
182}
183
184#[cfg(any(test, feature = "test-support"))]
185pub(crate) fn account_active_postings_decode(bytes: usize) {
186    let bytes = u64::try_from(bytes).unwrap_or(u64::MAX);
187    SEGMENT_COST_AUDIT.with(|slot| {
188        if let Some(counters) = slot.borrow().as_ref() {
189            let _ = counters.postings_decode_bytes.fetch_update(
190                Ordering::Relaxed,
191                Ordering::Relaxed,
192                |current| Some(current.saturating_add(bytes)),
193            );
194        }
195    });
196}
197
198fn region_hash(_kind: RegionKind, bytes: &[u8]) -> u64 {
199    #[cfg(any(test, feature = "test-support"))]
200    account_region_hash(_kind, bytes.len());
201    xxh3_64(bytes)
202}
203
204pub(crate) struct DataReadAuditGuard {
205    previous: Option<Arc<AtomicU64>>,
206}
207
208impl Drop for DataReadAuditGuard {
209    fn drop(&mut self) {
210        let previous = self.previous.take();
211        DATA_READ_AUDIT.with(|slot| {
212            slot.replace(previous);
213        });
214    }
215}
216
217pub(crate) fn install_data_read_audit(counter: Option<Arc<AtomicU64>>) -> DataReadAuditGuard {
218    let previous = DATA_READ_AUDIT.with(|slot| slot.replace(counter));
219    DataReadAuditGuard { previous }
220}
221
222fn account_data_read(bytes: usize) {
223    let bytes = u64::try_from(bytes).unwrap_or(u64::MAX);
224    DATA_READ_AUDIT.with(|slot| {
225        if let Some(counter) = slot.borrow().as_ref() {
226            let _ = counter.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| {
227                Some(current.saturating_add(bytes))
228            });
229        }
230    });
231}
232
233struct MappedFile {
234    _file: File,
235    pointer: NonNull<u8>,
236    length: usize,
237}
238
239impl MappedFile {
240    fn open(file: File, path: &Path) -> Result<Self, SegmentError> {
241        let length = usize::try_from(
242            file.metadata()
243                .map_err(|error| SegmentError::io(path, error))?
244                .len(),
245        )
246        .map_err(|_| SegmentError::Geometry("mapped file length exceeds usize".to_owned()))?;
247        if length == 0 {
248            return Err(FormatError::new(
249                path.display().to_string(),
250                FormatCheck::Length,
251                "empty segment file",
252            )
253            .into());
254        }
255        // SAFETY: `file` is an open regular-file descriptor, length is non-zero,
256        // and the mapping is read-only/private. The mapping owns its lifetime and
257        // is released exactly once in `Drop`; closing the descriptor is permitted.
258        let mapped = unsafe {
259            libc::mmap(
260                std::ptr::null_mut(),
261                length,
262                libc::PROT_READ,
263                libc::MAP_PRIVATE,
264                file.as_raw_fd(),
265                0,
266            )
267        };
268        if mapped == libc::MAP_FAILED {
269            return Err(SegmentError::io(path, std::io::Error::last_os_error()));
270        }
271        let pointer = NonNull::new(mapped.cast::<u8>()).ok_or_else(|| {
272            SegmentError::Geometry("mmap returned a null non-failure pointer".to_owned())
273        })?;
274        Ok(Self {
275            _file: file,
276            pointer,
277            length,
278        })
279    }
280
281    fn as_bytes(&self) -> &[u8] {
282        // SAFETY: the read-only mapping is valid for `length` bytes and remains
283        // alive for the returned borrow through `&self`.
284        unsafe { std::slice::from_raw_parts(self.pointer.as_ptr(), self.length) }
285    }
286
287    /// Flips `mask` into one byte of the private mapping through copy-on-write,
288    /// leaving the file untouched. Test support only: it models bit rot under a
289    /// reader that already validated the page, deterministically on every
290    /// platform (a file write is not visible through a private mapping on
291    /// macOS). `&mut self` proves no `as_bytes` borrow is live during the write.
292    #[cfg(any(test, feature = "test-support"))]
293    fn corrupt_byte(&mut self, offset: usize, mask: u8) -> std::io::Result<()> {
294        if offset >= self.length {
295            return Err(std::io::Error::other(
296                "corruption offset is outside the mapping",
297            ));
298        }
299        let page_size_raw = unsafe {
300            // SAFETY: `_SC_PAGESIZE` takes no pointer arguments and has no preconditions.
301            libc::sysconf(libc::_SC_PAGESIZE)
302        };
303        let page_size = usize::try_from(page_size_raw)
304            .ok()
305            .filter(|size| *size != 0)
306            .ok_or_else(|| std::io::Error::other("sysconf returned an invalid page size"))?;
307        let page_offset = offset - offset % page_size;
308        let page = self
309            .pointer
310            .as_ptr()
311            .wrapping_add(page_offset)
312            .cast::<libc::c_void>();
313        // SAFETY: `page` is the page-aligned start of a page inside this live
314        // private mapping, so the kernel may grant copy-on-write access to it.
315        if unsafe { libc::mprotect(page, page_size, libc::PROT_READ | libc::PROT_WRITE) } != 0 {
316            return Err(std::io::Error::last_os_error());
317        }
318        // SAFETY: `offset < length` keeps the byte inside the mapping, the page
319        // is writable, and `&mut self` guarantees no shared view of the bytes.
320        unsafe {
321            let byte = self.pointer.as_ptr().add(offset);
322            byte.write(byte.read() ^ mask);
323        }
324        // SAFETY: the same page range as above, returned to read-only.
325        if unsafe { libc::mprotect(page, page_size, libc::PROT_READ) } != 0 {
326            return Err(std::io::Error::last_os_error());
327        }
328        Ok(())
329    }
330}
331
332impl Drop for MappedFile {
333    fn drop(&mut self) {
334        // SAFETY: this is the exact pointer/length pair returned by successful
335        // `mmap`, and `Drop` runs once for the sole mapping owner.
336        let _ = unsafe { libc::munmap(self.pointer.as_ptr().cast(), self.length) };
337    }
338}
339
340// SAFETY: the mapping is immutable for its entire lifetime.
341unsafe impl Send for MappedFile {}
342// SAFETY: all shared access exposes read-only slices.
343unsafe impl Sync for MappedFile {}
344
345impl crate::graph::search::RescoreValidator for SegmentReader {
346    fn validate_rows(&self, rows: &[u32]) -> Result<(), String> {
347        self.validate_rescore_rows(rows).map_err(|source| {
348            format!(
349                "exact scores unavailable for segment {}: {source}",
350                self.meta.id
351            )
352        })
353    }
354}
355
356struct ParsedHeader {
357    meta: SegmentMeta,
358    header_length: usize,
359    entries: Vec<RegionEntry>,
360}
361
362/// Validated read-only memory mapping with lazy region checksum verification.
363pub struct SegmentReader {
364    mapping: MappedFile,
365    meta: SegmentMeta,
366    #[cfg(any(test, feature = "test-support"))]
367    storage_store_directory: PathBuf,
368    header_length: usize,
369    entries: Vec<RegionEntry>,
370    document_versions_validation: OnceLock<Result<(), DocumentVersionValidationError>>,
371    // Set by the query path once the stored-text region has passed its checksum
372    // and every row offset has been walked; the public `stored_text` never
373    // consults it and verifies on every call.
374    stored_text_validated: OnceLock<()>,
375    // Set only by the get path after the stored-metadata region has passed its
376    // checksum and full row-offset walk.
377    stored_metadata_validated: OnceLock<()>,
378    vector_codes_validated: OnceLock<()>,
379    vector_factors_validated: OnceLock<()>,
380    rescore_valid_chunks: Mutex<Box<[u64]>>,
381    query_accounting: Option<Arc<crate::lifecycle::stats::Accounting>>,
382    int8_factors_cache: OnceLock<CachedQueryValue<Arc<Vec<crate::scan::Int8Factors>>>>,
383    postings_cache: OnceLock<CachedQueryValue<Arc<crate::fts::sealed::SealedSegment>>>,
384    columns_cache: OnceLock<CachedQueryValue<Arc<ColumnStore>>>,
385    alive_cache: OnceLock<CachedQueryValue<Arc<AliveSet>>>,
386    // Sealed rows ordered by persisted document identity so an exact revision
387    // resolves by binary search instead of a full row scan.
388    document_version_index_cache: OnceLock<CachedQueryValue<Arc<Box<[u32]>>>>,
389    // Inline cached graph metadata is covered by this reader's exactly
390    // accounted snapshot slot; its heap-backed scratch is charged to Cache.
391    pub(crate) graph_search_cache: crate::lifecycle::graph_cache::SegmentGraphSearchCache,
392    // Query-independent half of the fusion vector ceiling. The enclosure is a
393    // property of this sealed segment's immutable factor or rescore bytes, so
394    // it is walked once per reader and folded with each query's norm after.
395    // Two f64 held inline, covered by the accounted snapshot slot.
396    vector_ceiling_norm_range: OnceLock<crate::graph::search::GraphSegmentNormRange>,
397}
398
399struct CachedQueryValue<T> {
400    value: T,
401    _accounting: Option<crate::lifecycle::stats::AccountedCounter>,
402}
403
404#[derive(Clone, Debug)]
405enum DocumentVersionValidationError {
406    Geometry(String),
407    Checksum,
408}
409
410impl DocumentVersionValidationError {
411    fn into_segment_error(self, segment_id: SegmentId) -> SegmentError {
412        match self {
413            Self::Geometry(detail) => SegmentError::Geometry(detail),
414            Self::Checksum => FormatError::new(
415                format!("segment:{segment_id}:document-versions"),
416                FormatCheck::BlockChecksum,
417                "document-version region checksum mismatch",
418            )
419            .into(),
420        }
421    }
422}
423
424/// Validated mmap-backed opaque metadata rows.
425#[derive(Clone, Copy, Debug)]
426pub struct StoredMetadataRows<'a> {
427    offsets: &'a [u8],
428    bytes: &'a [u8],
429    row_count: usize,
430}
431
432impl<'a> StoredMetadataRows<'a> {
433    /// Returns the number of dense metadata rows.
434    #[must_use]
435    pub const fn row_count(self) -> usize {
436        self.row_count
437    }
438
439    /// Returns one row's original opaque bytes.
440    #[must_use]
441    pub fn row(self, row: usize) -> Option<&'a [u8]> {
442        if row >= self.row_count {
443            return None;
444        }
445        let start_index = row.checked_mul(8)?;
446        let end_index = row.checked_add(1)?.checked_mul(8)?;
447        let start = self
448            .offsets
449            .get(start_index..start_index.checked_add(8)?)?
450            .try_into()
451            .ok()
452            .map(u64::from_le_bytes)
453            .and_then(|value| usize::try_from(value).ok())?;
454        let end = self
455            .offsets
456            .get(end_index..end_index.checked_add(8)?)?
457            .try_into()
458            .ok()
459            .map(u64::from_le_bytes)
460            .and_then(|value| usize::try_from(value).ok())?;
461        self.bytes.get(start..end)
462    }
463}
464
465/// Validated mmap-backed optional UTF-8 source rows.
466#[derive(Clone, Copy, Debug)]
467pub struct StoredTextRows<'a> {
468    present: &'a [u8],
469    offsets: &'a [u8],
470    bytes: &'a [u8],
471    row_count: usize,
472}
473
474impl<'a> StoredTextRows<'a> {
475    /// Returns the number of dense text rows.
476    #[must_use]
477    pub const fn row_count(self) -> usize {
478        self.row_count
479    }
480
481    /// Returns `None` for an invalid row, `Some(None)` for an absent field,
482    /// and `Some(Some(text))` for a present UTF-8 field (including empty text).
483    #[must_use]
484    pub fn row(self, row: usize) -> Option<Option<&'a str>> {
485        if row >= self.row_count {
486            return None;
487        }
488        let end_index = row.checked_mul(8)?;
489        let end = self
490            .offsets
491            .get(end_index..end_index.checked_add(8)?)?
492            .try_into()
493            .ok()
494            .map(u64::from_le_bytes)
495            .and_then(|value| usize::try_from(value).ok())?;
496        let start = if row == 0 {
497            0
498        } else {
499            let start_index = row.checked_sub(1)?.checked_mul(8)?;
500            self.offsets
501                .get(start_index..start_index.checked_add(8)?)?
502                .try_into()
503                .ok()
504                .map(u64::from_le_bytes)
505                .and_then(|value| usize::try_from(value).ok())?
506        };
507        let byte = *self.present.get(row / 8)?;
508        if byte & (1 << (row % 8)) == 0 {
509            return (start == end).then_some(None);
510        }
511        let text = std::str::from_utf8(self.bytes.get(start..end)?).ok()?;
512        Some(Some(text))
513    }
514}
515
516/// Tri-state cache for query-path checksum verification: 0 unset,
517/// 1 disabled, 2 enabled. Read from `ZE_VERIFY_QUERY_CHECKSUMS` once.
518static QUERY_CHECKSUMS: std::sync::atomic::AtomicU8 = std::sync::atomic::AtomicU8::new(0);
519
520/// Forces query-path checksum verification on or off.
521///
522/// Verification is opt-in and off by default, so a test that asserts the
523/// verifying behaviour must turn it on rather than assume it.
524#[cfg(any(test, feature = "test-support"))]
525pub fn set_query_checksum_verification(enabled: bool) {
526    QUERY_CHECKSUMS.store(
527        if enabled { 2 } else { 1 },
528        std::sync::atomic::Ordering::Relaxed,
529    );
530}
531
532impl SegmentReader {
533    /// Memory-maps a segment and validates only its bounded header/directory.
534    pub fn open(vfs: &dyn Vfs, path: &Path, expected_id: SegmentId) -> Result<Self, SegmentError> {
535        let file = vfs
536            .open_for_map(path)
537            .map_err(|error| SegmentError::io(path, error))?;
538        let mapping = MappedFile::open(file, path)?;
539        let artifact = path.display().to_string();
540        let parsed = parse_segment_header(
541            &artifact,
542            mapping.as_bytes(),
543            mapping.length as u64,
544            expected_id,
545        )?;
546        let rescore_valid_chunks = rescore_validation_words(&parsed.entries)?;
547        Ok(Self {
548            mapping,
549            meta: parsed.meta,
550            #[cfg(any(test, feature = "test-support"))]
551            storage_store_directory: path.parent().unwrap_or(Path::new("")).to_path_buf(),
552            header_length: parsed.header_length,
553            entries: parsed.entries,
554            document_versions_validation: OnceLock::new(),
555            stored_text_validated: OnceLock::new(),
556            stored_metadata_validated: OnceLock::new(),
557            vector_codes_validated: OnceLock::new(),
558            vector_factors_validated: OnceLock::new(),
559            rescore_valid_chunks: Mutex::new(vec![0_u64; rescore_valid_chunks].into_boxed_slice()),
560            query_accounting: None,
561            int8_factors_cache: OnceLock::new(),
562            postings_cache: OnceLock::new(),
563            columns_cache: OnceLock::new(),
564            alive_cache: OnceLock::new(),
565            document_version_index_cache: OnceLock::new(),
566            graph_search_cache: crate::lifecycle::graph_cache::SegmentGraphSearchCache::new(),
567            vector_ceiling_norm_range: OnceLock::new(),
568        })
569    }
570
571    pub(crate) fn open_accounted(
572        vfs: &dyn Vfs,
573        path: &Path,
574        expected: &SegmentMeta,
575        accounting: &Arc<crate::lifecycle::stats::Accounting>,
576        mut before_reader_allocation: impl FnMut(usize) -> Result<(), crate::lifecycle::StoreError>,
577    ) -> Result<Self, crate::lifecycle::StoreError> {
578        let file = vfs
579            .open_for_map(path)
580            .map_err(|error| SegmentError::io(path, error))
581            .map_err(crate::lifecycle::StoreError::Segment)?;
582        let mapping =
583            MappedFile::open(file, path).map_err(crate::lifecycle::StoreError::Segment)?;
584        let artifact = path.display().to_string();
585        let region_count =
586            preflight_region_count(&artifact, mapping.as_bytes(), mapping.length as u64)
587                .map_err(crate::lifecycle::StoreError::Segment)?;
588        let directory_bytes = region_count
589            .checked_mul(std::mem::size_of::<RegionEntry>())
590            .ok_or(crate::lifecycle::StoreError::BudgetExceeded {
591                needed: u64::MAX,
592                budget: u64::MAX,
593                component: "snapshot",
594            })?;
595        before_reader_allocation(directory_bytes)?;
596        let parsed = parse_segment_header(
597            &artifact,
598            mapping.as_bytes(),
599            mapping.length as u64,
600            expected.id,
601        )
602        .map_err(crate::lifecycle::StoreError::Segment)?;
603        if !parsed.meta.same_segment_file(expected) {
604            return Err(crate::lifecycle::StoreError::Segment(
605                SegmentError::Geometry(format!(
606                    "manifest metadata {expected:?}, mapped header metadata {:?}",
607                    parsed.meta
608                )),
609            ));
610        }
611        let rescore_valid_chunks = rescore_validation_words(&parsed.entries)
612            .map_err(crate::lifecycle::StoreError::Segment)?;
613        let validation_bytes = rescore_valid_chunks
614            .checked_mul(std::mem::size_of::<u64>())
615            .ok_or(crate::lifecycle::StoreError::BudgetExceeded {
616                needed: u64::MAX,
617                budget: u64::MAX,
618                component: "snapshot",
619            })?;
620        before_reader_allocation(validation_bytes)?;
621        Ok(Self {
622            mapping,
623            meta: expected.clone(),
624            #[cfg(any(test, feature = "test-support"))]
625            storage_store_directory: path.parent().unwrap_or(Path::new("")).to_path_buf(),
626            header_length: parsed.header_length,
627            entries: parsed.entries,
628            document_versions_validation: OnceLock::new(),
629            stored_text_validated: OnceLock::new(),
630            stored_metadata_validated: OnceLock::new(),
631            vector_codes_validated: OnceLock::new(),
632            vector_factors_validated: OnceLock::new(),
633            rescore_valid_chunks: Mutex::new(vec![0_u64; rescore_valid_chunks].into_boxed_slice()),
634            query_accounting: Some(Arc::clone(accounting)),
635            int8_factors_cache: OnceLock::new(),
636            postings_cache: OnceLock::new(),
637            columns_cache: OnceLock::new(),
638            alive_cache: OnceLock::new(),
639            document_version_index_cache: OnceLock::new(),
640            graph_search_cache: crate::lifecycle::graph_cache::SegmentGraphSearchCache::new(),
641            vector_ceiling_norm_range: OnceLock::new(),
642        })
643    }
644
645    /// Returns immutable manifest-visible metadata decoded from the header.
646    #[must_use]
647    pub const fn meta(&self) -> &SegmentMeta {
648        &self.meta
649    }
650
651    /// Returns exact header bytes touched by an O(manifest) open.
652    #[must_use]
653    pub const fn header_length(&self) -> usize {
654        self.header_length
655    }
656
657    /// Returns the exact virtual byte length of this immutable file mapping.
658    #[must_use]
659    pub(crate) const fn mapped_bytes(&self) -> usize {
660        self.mapping.length
661    }
662
663    /// Returns mapped bytes whose intersecting pages are resident per `mincore`.
664    pub(crate) fn mapped_resident_bytes(&self) -> std::io::Result<u64> {
665        crate::sys::memory::mincore_resident_bytes(self.mapping.as_bytes())
666    }
667
668    #[cfg(test)]
669    pub(crate) fn retained_validation_bytes(&self) -> usize {
670        self.rescore_valid_chunks
671            .lock()
672            .map_or(0, |words| std::mem::size_of_val(words.as_ref()))
673    }
674
675    /// Flips `mask` into one mapped byte through copy-on-write, leaving the
676    /// segment file untouched, so a test can corrupt what an already-validated
677    /// reader sees. `&mut self` guarantees no region view is live meanwhile.
678    #[cfg(any(test, feature = "test-support"))]
679    #[doc(hidden)]
680    pub fn corrupt_mapped_byte_for_test(&mut self, offset: usize, mask: u8) -> std::io::Result<()> {
681        self.mapping.corrupt_byte(offset, mask)
682    }
683
684    #[cfg(any(test, feature = "test-support"))]
685    #[doc(hidden)]
686    pub fn retained_query_view_bytes(&self) -> u64 {
687        let int8_factors = self.int8_factors_cache.get().and_then(|cached| {
688            cached
689                .value
690                .capacity()
691                .checked_mul(std::mem::size_of::<crate::scan::Int8Factors>())
692                .and_then(arc_resident_bytes::<Vec<crate::scan::Int8Factors>>)
693        });
694        let postings = self.postings_cache.get().and_then(|cached| {
695            cached
696                .value
697                .resident_bytes()
698                .ok()
699                .and_then(arc_resident_bytes::<crate::fts::sealed::SealedSegment>)
700        });
701        let columns = self.columns_cache.get().and_then(|cached| {
702            cached
703                .value
704                .resident_bytes()
705                .and_then(arc_resident_bytes::<ColumnStore>)
706        });
707        let alive = self.alive_cache.get().and_then(|cached| {
708            cached
709                .value
710                .resident_bytes()
711                .and_then(arc_resident_bytes::<AliveSet>)
712        });
713        let document_version_index = self.document_version_index_cache.get().and_then(|cached| {
714            cached
715                .value
716                .len()
717                .checked_mul(std::mem::size_of::<u32>())
718                .and_then(arc_resident_bytes::<Box<[u32]>>)
719        });
720        int8_factors
721            .into_iter()
722            .chain(postings)
723            .chain(columns)
724            .chain(alive)
725            .chain(document_version_index)
726            .fold(0_u64, |total, bytes| {
727                total.saturating_add(u64::try_from(bytes).unwrap_or(u64::MAX))
728            })
729    }
730
731    /// Returns the validated region directory, including unknown skippable kinds.
732    #[must_use]
733    pub fn directory(&self) -> &[RegionEntry] {
734        &self.entries
735    }
736
737    /// Returns unknown region ids without treating them as corruption.
738    #[must_use]
739    pub fn unknown_region_ids(&self) -> Vec<u16> {
740        self.entries
741            .iter()
742            .filter_map(|entry| {
743                RegionKind::from_id(entry.kind)
744                    .is_none()
745                    .then_some(entry.kind)
746            })
747            .collect()
748    }
749
750    /// Validates a complete region and returns its original mmap-backed bytes.
751    pub fn region(&self, kind: RegionKind) -> Result<&[u8], SegmentError> {
752        let entry = self.entry(kind)?;
753        let bytes = self.region_slice(entry)?;
754        let actual = region_hash(kind, bytes);
755        if actual != entry.checksum {
756            #[cfg(any(test, feature = "test-support"))]
757            crate::lifecycle::record_storage_segment_checksum_fault(
758                &self.storage_store_directory,
759                self.meta.id,
760                kind,
761                0,
762                entry.checksum,
763                actual,
764            );
765            return Err(FormatError::checksum_mismatch(
766                format!("segment:{}:{kind:?}", self.meta.id),
767                FormatCheck::BlockChecksum,
768                entry.checksum,
769                actual,
770            )
771            .into());
772        }
773        Ok(bytes)
774    }
775
776    /// Validates and returns one source region by its numeric directory kind.
777    pub(crate) fn region_by_id(&self, kind: u16) -> Result<&[u8], SegmentError> {
778        let entry = self
779            .entries
780            .iter()
781            .find(|entry| entry.kind == kind)
782            .ok_or_else(|| {
783                SegmentError::Geometry(format!("segment is missing region kind {kind}"))
784            })?;
785        let bytes = self.region_slice(entry)?;
786        let actual = xxh3_64(bytes);
787        if actual != entry.checksum {
788            return Err(FormatError::checksum_mismatch(
789                format!("segment:{}:region-{kind}", self.meta.id),
790                FormatCheck::BlockChecksum,
791                entry.checksum,
792                actual,
793            )
794            .into());
795        }
796        Ok(bytes)
797    }
798
799    /// Validates one 64-KB chunk and returns only that mmap-backed chunk.
800    pub fn region_chunk(&self, kind: RegionKind, chunk_index: u32) -> Result<&[u8], SegmentError> {
801        let entry = self.entry(kind)?;
802        let region = self.region_slice(entry)?;
803        let start = (chunk_index as usize)
804            .checked_mul(CHECKSUM_CHUNK_BYTES)
805            .ok_or_else(|| SegmentError::Geometry("chunk offset overflow".to_owned()))?;
806        let end = start.saturating_add(CHECKSUM_CHUNK_BYTES).min(region.len());
807        let chunk = region.get(start..end).ok_or_else(|| {
808            SegmentError::Geometry(format!("chunk {chunk_index} is outside {kind:?}"))
809        })?;
810        if chunk.is_empty() {
811            return Err(SegmentError::Geometry(format!(
812                "chunk {chunk_index} is outside {kind:?}"
813            )));
814        }
815        let expected = self.chunk_checksum(kind, chunk_index)?;
816        let actual = region_hash(kind, chunk);
817        if actual != expected {
818            #[cfg(any(test, feature = "test-support"))]
819            crate::lifecycle::record_storage_segment_checksum_fault(
820                &self.storage_store_directory,
821                self.meta.id,
822                kind,
823                chunk_index,
824                expected,
825                actual,
826            );
827            return Err(FormatError::checksum_mismatch(
828                format!("segment:{}:{kind:?}:chunk-{chunk_index}", self.meta.id),
829                FormatCheck::BlockChecksum,
830                expected,
831                actual,
832            )
833            .into());
834        }
835        Ok(chunk)
836    }
837
838    /// Returns packed Bit4 code bytes exactly as passed to the batch kernel.
839    pub fn bit4_codes(&self) -> Result<&[u8], SegmentError> {
840        let (header, payload) = self.vector_payload(RegionKind::VectorCodes)?;
841        self.bit4_codes_from(header, payload)
842    }
843
844    fn bit4_codes_unchecked(&self) -> Result<&[u8], SegmentError> {
845        let (header, payload) = self.vector_payload_unchecked(RegionKind::VectorCodes)?;
846        self.bit4_codes_from(header, payload)
847    }
848
849    fn bit4_codes_from<'a>(
850        &'a self,
851        header: super::layout::VectorHeader,
852        payload: &'a [u8],
853    ) -> Result<&'a [u8], SegmentError> {
854        if self.meta.scheme != 4 {
855            return Err(SegmentError::Geometry(format!(
856                "Bit4 codes requested for scheme {}",
857                self.meta.scheme
858            )));
859        }
860        let expected = (self.meta.dims as usize)
861            .div_ceil(2)
862            .checked_mul(self.meta.row_count as usize)
863            .ok_or_else(|| SegmentError::Geometry("Bit4 code length overflow".to_owned()))?;
864        if header.row_stride_bytes as usize != (self.meta.dims as usize).div_ceil(2)
865            || payload.len() != expected
866        {
867            return Err(SegmentError::Geometry(format!(
868                "Bit4 code stride/length {}/{}, expected {}/{}",
869                header.row_stride_bytes,
870                payload.len(),
871                (self.meta.dims as usize).div_ceil(2),
872                expected
873            )));
874        }
875        Ok(payload)
876    }
877
878    /// Casts validated full-precision code rows directly from the mapping.
879    pub fn f32_codes(&self) -> Result<&[f32], SegmentError> {
880        let (header, payload) = self.vector_payload(RegionKind::VectorCodes)?;
881        self.f32_codes_from(header, payload)
882    }
883
884    /// Validate-once twin of [`Self::f32_codes`].
885    pub(crate) fn query_f32_codes(&self) -> Result<&[f32], SegmentError> {
886        self.validate_vector_region_once(RegionKind::VectorCodes, &self.vector_codes_validated)?;
887        let (header, payload) = self.vector_payload_unchecked(RegionKind::VectorCodes)?;
888        self.f32_codes_from(header, payload)
889    }
890
891    fn f32_codes_from<'a>(
892        &'a self,
893        header: super::layout::VectorHeader,
894        payload: &'a [u8],
895    ) -> Result<&'a [f32], SegmentError> {
896        if self.meta.scheme != 0 {
897            return Err(SegmentError::Geometry(format!(
898                "F32 codes requested for scheme {}",
899                self.meta.scheme
900            )));
901        }
902        let expected = (self.meta.dims as usize)
903            .checked_mul(self.meta.row_count as usize)
904            .ok_or_else(|| SegmentError::Geometry("F32 code length overflow".to_owned()))?;
905        let expected_bytes = expected
906            .checked_mul(std::mem::size_of::<f32>())
907            .ok_or_else(|| SegmentError::Geometry("F32 code byte length overflow".to_owned()))?;
908        let expected_stride = (self.meta.dims as usize)
909            .checked_mul(std::mem::size_of::<f32>())
910            .ok_or_else(|| SegmentError::Geometry("F32 code stride overflow".to_owned()))?;
911        if header.row_stride_bytes as usize != expected_stride || payload.len() != expected_bytes {
912            return Err(SegmentError::Geometry(format!(
913                "F32 code stride/length {}/{}, expected {expected_stride}/{expected_bytes}",
914                header.row_stride_bytes,
915                payload.len()
916            )));
917        }
918        cast_slice::<f32>(payload, expected, "F32 codes")
919    }
920
921    /// Casts signed-byte vector codes directly from the validated mmap region.
922    pub fn int8_codes(&self) -> Result<&[i8], SegmentError> {
923        let (header, payload) = self.vector_payload(RegionKind::VectorCodes)?;
924        self.int8_codes_from(header, payload)
925    }
926
927    fn int8_codes_unchecked(&self) -> Result<&[i8], SegmentError> {
928        let (header, payload) = self.vector_payload_unchecked(RegionKind::VectorCodes)?;
929        self.int8_codes_from(header, payload)
930    }
931
932    fn int8_codes_from<'a>(
933        &'a self,
934        header: super::layout::VectorHeader,
935        payload: &'a [u8],
936    ) -> Result<&'a [i8], SegmentError> {
937        if self.meta.scheme != 2 {
938            return Err(SegmentError::Geometry(format!(
939                "Int8 codes requested for scheme {}",
940                self.meta.scheme
941            )));
942        }
943        let expected = (self.meta.dims as usize)
944            .checked_mul(self.meta.row_count as usize)
945            .ok_or_else(|| SegmentError::Geometry("Int8 code length overflow".to_owned()))?;
946        if header.row_stride_bytes as usize != self.meta.dims as usize || payload.len() != expected
947        {
948            return Err(SegmentError::Geometry(format!(
949                "Int8 code stride/length {}/{}, expected {}/{}",
950                header.row_stride_bytes,
951                payload.len(),
952                self.meta.dims,
953                expected
954            )));
955        }
956        cast_slice::<i8>(payload, expected, "Int8 codes")
957    }
958
959    /// Casts the validated factor region directly to permanent Bit4 records.
960    pub fn bit4_factors(&self) -> Result<&[Bit4Factors], SegmentError> {
961        let (header, payload) = self.vector_payload(RegionKind::VectorFactors)?;
962        self.bit4_factors_from(header, payload)
963    }
964
965    fn bit4_factors_unchecked(&self) -> Result<&[Bit4Factors], SegmentError> {
966        let (header, payload) = self.vector_payload_unchecked(RegionKind::VectorFactors)?;
967        self.bit4_factors_from(header, payload)
968    }
969
970    fn bit4_factors_from<'a>(
971        &'a self,
972        header: super::layout::VectorHeader,
973        payload: &'a [u8],
974    ) -> Result<&'a [Bit4Factors], SegmentError> {
975        if self.meta.scheme != 4 {
976            return Err(SegmentError::Geometry(format!(
977                "Bit4 factors requested for scheme {}",
978                self.meta.scheme
979            )));
980        }
981        if header.factor_stride_bytes != 12 {
982            return Err(SegmentError::Geometry(format!(
983                "Bit4 factor stride {}, expected 12",
984                header.factor_stride_bytes
985            )));
986        }
987        cast_slice::<Bit4Factors>(payload, self.meta.row_count as usize, "Bit4 factors")
988    }
989
990    /// Casts a validated Int8 factor region directly to permanent records.
991    pub fn int8_factors(&self) -> Result<&[Int8Factors], SegmentError> {
992        let (header, payload) = self.vector_payload(RegionKind::VectorFactors)?;
993        self.int8_factors_from(header, payload)
994    }
995
996    fn int8_factors_unchecked(&self) -> Result<&[Int8Factors], SegmentError> {
997        let (header, payload) = self.vector_payload_unchecked(RegionKind::VectorFactors)?;
998        self.int8_factors_from(header, payload)
999    }
1000
1001    fn int8_factors_from<'a>(
1002        &'a self,
1003        header: super::layout::VectorHeader,
1004        payload: &'a [u8],
1005    ) -> Result<&'a [Int8Factors], SegmentError> {
1006        if self.meta.scheme != 2 {
1007            return Err(SegmentError::Geometry(format!(
1008                "Int8 factors requested for scheme {}",
1009                self.meta.scheme
1010            )));
1011        }
1012        if header.factor_stride_bytes != 8 {
1013            return Err(SegmentError::Geometry(format!(
1014                "Int8 factor stride {}, expected 8",
1015                header.factor_stride_bytes
1016            )));
1017        }
1018        #[cfg(any(test, feature = "test-support"))]
1019        account_region_decode(RegionKind::VectorFactors, payload.len());
1020        cast_slice::<Int8Factors>(payload, self.meta.row_count as usize, "Int8 factors")
1021    }
1022
1023    /// Reports whether query paths verify region checksums at all.
1024    ///
1025    /// Owner decision 2026-09-04: verification is opt-in and off by
1026    /// default. A sealed segment is immutable and its checksums are
1027    /// written and verified at seal; re-verifying at query time defends
1028    /// only against on-disk corruption after publication, which is what
1029    /// `Store::health()` and the diagnostics paths are for. Those paths
1030    /// still verify unconditionally. Set `ZE_VERIFY_QUERY_CHECKSUMS=1`
1031    /// to restore per-reader verification on the query path.
1032    fn query_checksums_enabled() -> bool {
1033        match QUERY_CHECKSUMS.load(std::sync::atomic::Ordering::Relaxed) {
1034            0 => {
1035                let enabled =
1036                    std::env::var_os("ZE_VERIFY_QUERY_CHECKSUMS").is_some_and(|value| value != "0");
1037                QUERY_CHECKSUMS.store(
1038                    if enabled { 2 } else { 1 },
1039                    std::sync::atomic::Ordering::Relaxed,
1040                );
1041                enabled
1042            }
1043            1 => false,
1044            _ => true,
1045        }
1046    }
1047
1048    /// Verifies a vector region's checksum once per reader, then serves it
1049    /// from the mapping without re-hashing.
1050    ///
1051    /// The verifying accessors re-hash the whole region on every call. On
1052    /// a query path that is ruinous: hybrid cross-fill called the
1053    /// verifying rescore accessor once per cross-filled document and
1054    /// spent 219 ms of a 221 ms query re-hashing 181 MB. Query paths use
1055    /// these twins; validation, diagnostics and maintenance keep the
1056    /// verifying accessors.
1057    fn validate_vector_region_once(
1058        &self,
1059        kind: RegionKind,
1060        gate: &OnceLock<()>,
1061    ) -> Result<(), SegmentError> {
1062        if gate.get().is_some() || !Self::query_checksums_enabled() {
1063            return Ok(());
1064        }
1065        let _ = self.region(kind)?;
1066        let _ = gate.set(());
1067        Ok(())
1068    }
1069
1070    /// Validate-once twin of [`Self::bit4_codes`].
1071    pub(crate) fn query_bit4_codes(&self) -> Result<&[u8], SegmentError> {
1072        self.validate_vector_region_once(RegionKind::VectorCodes, &self.vector_codes_validated)?;
1073        self.bit4_codes_unchecked()
1074    }
1075
1076    /// Validate-once twin of [`Self::int8_codes`].
1077    pub(crate) fn query_int8_codes(&self) -> Result<&[i8], SegmentError> {
1078        self.validate_vector_region_once(RegionKind::VectorCodes, &self.vector_codes_validated)?;
1079        self.int8_codes_unchecked()
1080    }
1081
1082    /// Validate-once twin of [`Self::int8_factors`] returning the raw slice.
1083    pub(crate) fn query_int8_factors_slice(&self) -> Result<&[Int8Factors], SegmentError> {
1084        self.validate_vector_region_once(
1085            RegionKind::VectorFactors,
1086            &self.vector_factors_validated,
1087        )?;
1088        self.int8_factors_unchecked()
1089    }
1090
1091    /// Returns this reader's remembered query-independent norm enclosure.
1092    ///
1093    /// `None` means no query has walked the region yet. The enclosure is
1094    /// derived only from immutable sealed bytes, so a remembered value is the
1095    /// same value any later walk would produce.
1096    pub(crate) fn cached_vector_ceiling_norm_range(
1097        &self,
1098    ) -> Option<crate::graph::search::GraphSegmentNormRange> {
1099        self.vector_ceiling_norm_range.get().copied()
1100    }
1101
1102    /// Remembers the enclosure a query walked out of this segment's bytes.
1103    pub(crate) fn remember_vector_ceiling_norm_range(
1104        &self,
1105        range: crate::graph::search::GraphSegmentNormRange,
1106    ) {
1107        if self.vector_ceiling_norm_range.set(range).is_err() {
1108            // A concurrent walk won. It read the same immutable bytes with the
1109            // same arithmetic, so its enclosure is this enclosure.
1110        }
1111    }
1112
1113    /// Validate-once twin of [`Self::bit4_factors`].
1114    pub(crate) fn query_bit4_factors(&self) -> Result<&[Bit4Factors], SegmentError> {
1115        self.validate_vector_region_once(
1116            RegionKind::VectorFactors,
1117            &self.vector_factors_validated,
1118        )?;
1119        self.bit4_factors_unchecked()
1120    }
1121
1122    pub(crate) fn query_int8_factors(
1123        &self,
1124    ) -> Result<Arc<Vec<crate::scan::Int8Factors>>, crate::lifecycle::StoreError> {
1125        if let Some(cached) = self.int8_factors_cache.get() {
1126            return Ok(Arc::clone(&cached.value));
1127        }
1128        let factors = self
1129            .int8_factors()
1130            .map_err(crate::lifecycle::StoreError::Segment)?
1131            .iter()
1132            .map(|factor| crate::scan::Int8Factors::new(factor.scale, factor.offset))
1133            .collect::<Result<Vec<_>, _>>()
1134            .map_err(|_| {
1135                crate::lifecycle::StoreError::Segment(SegmentError::Geometry(
1136                    "Int8 factor is not finite and non-negative".to_owned(),
1137                ))
1138            })?;
1139        let resident_bytes = factors
1140            .capacity()
1141            .checked_mul(std::mem::size_of::<crate::scan::Int8Factors>())
1142            .and_then(arc_resident_bytes::<Vec<crate::scan::Int8Factors>>)
1143            .ok_or(crate::lifecycle::StoreError::BudgetExceeded {
1144                needed: u64::MAX,
1145                budget: u64::MAX,
1146                component: "snapshot",
1147            })?;
1148        let cached = CachedQueryValue {
1149            value: Arc::new(factors),
1150            _accounting: self.account_query_cache(resident_bytes)?,
1151        };
1152        if self.int8_factors_cache.set(cached).is_err() {
1153            // A concurrent initializer won. Its value and reservation are authoritative.
1154        }
1155        self.int8_factors_cache
1156            .get()
1157            .map(|cached| Arc::clone(&cached.value))
1158            .ok_or(crate::lifecycle::StoreError::Synchronization {
1159                component: "Int8 factors query cache",
1160            })
1161    }
1162
1163    /// Casts validated f32 exact-rescore rows directly from the mmap.
1164    pub fn rescore_f32(&self) -> Result<&[f32], SegmentError> {
1165        let (header, payload) = self.vector_payload(RegionKind::VectorRescore)?;
1166        if header.scheme != 0 {
1167            return Err(SegmentError::Geometry(format!(
1168                "v1 rescore scheme must be F32/0, got {}",
1169                header.scheme
1170            )));
1171        }
1172        let count = (self.meta.row_count as usize)
1173            .checked_mul(self.meta.dims as usize)
1174            .ok_or_else(|| SegmentError::Geometry("rescore count overflow".to_owned()))?;
1175        cast_slice::<f32>(payload, count, "f32 rescore")
1176    }
1177
1178    pub(crate) fn query_rescore_f32(&self) -> Result<&[f32], SegmentError> {
1179        self.validate_rescore_byte_range(0, VECTOR_HEADER_LEN)?;
1180        let (header, payload) = self.vector_payload_unchecked(RegionKind::VectorRescore)?;
1181        if header.scheme != 0 {
1182            return Err(SegmentError::Geometry(format!(
1183                "v1 rescore scheme must be F32/0, got {}",
1184                header.scheme
1185            )));
1186        }
1187        let count = (self.meta.row_count as usize)
1188            .checked_mul(self.meta.dims as usize)
1189            .ok_or_else(|| SegmentError::Geometry("rescore count overflow".to_owned()))?;
1190        cast_slice::<f32>(payload, count, "f32 rescore")
1191    }
1192
1193    pub(crate) fn validate_rescore_rows(&self, rows: &[u32]) -> Result<(), SegmentError> {
1194        let row_bytes = (self.meta.dims as usize)
1195            .checked_mul(std::mem::size_of::<f32>())
1196            .ok_or_else(|| SegmentError::Geometry("rescore row byte length overflow".to_owned()))?;
1197        for row in rows {
1198            if *row >= self.meta.row_count {
1199                return Err(SegmentError::Geometry(format!(
1200                    "rescore row {row} is outside {} rows",
1201                    self.meta.row_count
1202                )));
1203            }
1204            let start = (*row as usize)
1205                .checked_mul(row_bytes)
1206                .and_then(|offset| offset.checked_add(VECTOR_HEADER_LEN))
1207                .ok_or_else(|| SegmentError::Geometry("rescore row offset overflow".to_owned()))?;
1208            self.validate_rescore_byte_range(start, row_bytes)?;
1209        }
1210        Ok(())
1211    }
1212
1213    /// Decodes the checksummed metadata region into typed column arrays.
1214    pub fn columns(&self) -> Result<ColumnStore, SegmentError> {
1215        let region = self.region(RegionKind::Columns)?;
1216        #[cfg(any(test, feature = "test-support"))]
1217        account_region_decode(RegionKind::Columns, region.len());
1218        let columns = decode_columns(region)?;
1219        if columns.row_count() != self.meta.row_count {
1220            return Err(SegmentError::Geometry(format!(
1221                "column rows {}, header rows {}",
1222                columns.row_count(),
1223                self.meta.row_count
1224            )));
1225        }
1226        Ok(columns)
1227    }
1228
1229    pub(crate) fn query_columns(&self) -> Result<Arc<ColumnStore>, crate::lifecycle::StoreError> {
1230        if let Some(cached) = self.columns_cache.get() {
1231            return Ok(Arc::clone(&cached.value));
1232        }
1233        let region = self
1234            .region(RegionKind::Columns)
1235            .map_err(crate::lifecycle::StoreError::Segment)?;
1236        #[cfg(any(test, feature = "test-support"))]
1237        account_region_decode(RegionKind::Columns, region.len());
1238        let mut columns = decode_columns(region).map_err(crate::lifecycle::StoreError::Segment)?;
1239        if columns.row_count() != self.meta.row_count {
1240            return Err(crate::lifecycle::StoreError::Segment(
1241                SegmentError::Geometry(format!(
1242                    "column rows {}, header rows {}",
1243                    columns.row_count(),
1244                    self.meta.row_count
1245                )),
1246            ));
1247        }
1248        columns.compact_for_cache();
1249        let resident_bytes = columns
1250            .resident_bytes()
1251            .and_then(arc_resident_bytes::<ColumnStore>)
1252            .ok_or(crate::lifecycle::StoreError::BudgetExceeded {
1253                needed: u64::MAX,
1254                budget: u64::MAX,
1255                component: "snapshot",
1256            })?;
1257        let cached = CachedQueryValue {
1258            value: Arc::new(columns),
1259            _accounting: self.account_query_cache(resident_bytes)?,
1260        };
1261        if self.columns_cache.set(cached).is_err() {
1262            // A concurrent initializer won. Its value and reservation are authoritative.
1263        }
1264        self.columns_cache
1265            .get()
1266            .map(|cached| Arc::clone(&cached.value))
1267            .ok_or(crate::lifecycle::StoreError::Synchronization {
1268                component: "columns query cache",
1269            })
1270    }
1271
1272    /// Decodes the optional whole-segment lexical region.
1273    pub fn postings(&self) -> Result<Option<crate::fts::sealed::SealedSegment>, SegmentError> {
1274        if !self
1275            .entries
1276            .iter()
1277            .any(|entry| entry.kind == RegionKind::Postings.id())
1278        {
1279            return Ok(None);
1280        }
1281        let region = self.region(RegionKind::Postings)?;
1282        #[cfg(any(test, feature = "test-support"))]
1283        account_region_decode(RegionKind::Postings, region.len());
1284        let postings = crate::fts::sealed::SealedSegment::decode_region(region)?;
1285        if postings.row_count() != self.meta.row_count {
1286            return Err(SegmentError::Geometry(format!(
1287                "postings rows {}, header rows {}",
1288                postings.row_count(),
1289                self.meta.row_count
1290            )));
1291        }
1292        Ok(Some(postings))
1293    }
1294
1295    /// Directory identity for already verified lexical payloads. A remapped
1296    /// reader may reuse statistics only after its normal postings validation.
1297    pub(crate) fn lexical_postings_identity(&self) -> Result<(u64, u64), SegmentError> {
1298        let entry = self.entry(RegionKind::Postings)?;
1299        Ok((entry.length, entry.checksum))
1300    }
1301
1302    pub(crate) fn query_postings(
1303        &self,
1304    ) -> Result<Option<Arc<crate::fts::sealed::SealedSegment>>, crate::lifecycle::StoreError> {
1305        if !self
1306            .entries
1307            .iter()
1308            .any(|entry| entry.kind == RegionKind::Postings.id())
1309        {
1310            return Ok(None);
1311        }
1312        if let Some(cached) = self.postings_cache.get() {
1313            return Ok(Some(Arc::clone(&cached.value)));
1314        }
1315        let region = self
1316            .region(RegionKind::Postings)
1317            .map_err(crate::lifecycle::StoreError::Segment)?;
1318        #[cfg(any(test, feature = "test-support"))]
1319        account_region_decode(RegionKind::Postings, region.len());
1320        let postings = crate::fts::sealed::SealedSegment::decode_region(region)
1321            .map_err(SegmentError::from)
1322            .map_err(crate::lifecycle::StoreError::Segment)?;
1323        if postings.row_count() != self.meta.row_count {
1324            return Err(crate::lifecycle::StoreError::Segment(
1325                SegmentError::Geometry(format!(
1326                    "postings rows {}, header rows {}",
1327                    postings.row_count(),
1328                    self.meta.row_count
1329                )),
1330            ));
1331        }
1332        let resident_bytes = postings
1333            .resident_bytes()
1334            .map_err(SegmentError::from)
1335            .map_err(crate::lifecycle::StoreError::Segment)?
1336            .checked_add(std::mem::size_of::<crate::fts::sealed::SealedSegment>())
1337            .and_then(|bytes| bytes.checked_add(2 * std::mem::size_of::<usize>()))
1338            .ok_or(crate::lifecycle::StoreError::BudgetExceeded {
1339                needed: u64::MAX,
1340                budget: u64::MAX,
1341                component: "snapshot",
1342            })?;
1343        let mut cache_accounting = self
1344            .query_accounting
1345            .as_ref()
1346            .map(|accounting| {
1347                crate::lifecycle::stats::AccountedCounter::new(
1348                    accounting,
1349                    crate::lifecycle::stats::AllocationComponent::Snapshot,
1350                )
1351            })
1352            .transpose()?;
1353        if let Some(counter) = cache_accounting.as_mut() {
1354            counter.set(resident_bytes)?;
1355        }
1356        let cached = CachedQueryValue {
1357            value: Arc::new(postings),
1358            _accounting: cache_accounting,
1359        };
1360        if self.postings_cache.set(cached).is_err() {
1361            // A concurrent initializer won. Its value and reservation are authoritative.
1362        }
1363        self.postings_cache
1364            .get()
1365            .map(|cached| Some(Arc::clone(&cached.value)))
1366            .ok_or(crate::lifecycle::StoreError::Synchronization {
1367                component: "postings query cache",
1368            })
1369    }
1370
1371    /// Decodes the checksummed alive/tombstone region.
1372    pub fn alive(&self) -> Result<AliveSet, SegmentError> {
1373        let region = self.region(RegionKind::Alive)?;
1374        #[cfg(any(test, feature = "test-support"))]
1375        account_region_decode(RegionKind::Alive, region.len());
1376        let alive = decode_alive(region)?;
1377        if alive.row_count() != self.meta.row_count {
1378            return Err(SegmentError::Geometry(format!(
1379                "alive rows {}, header rows {}",
1380                alive.row_count(),
1381                self.meta.row_count
1382            )));
1383        }
1384        Ok(alive)
1385    }
1386
1387    pub(crate) fn query_alive(&self) -> Result<Arc<AliveSet>, crate::lifecycle::StoreError> {
1388        if let Some(cached) = self.alive_cache.get() {
1389            return Ok(Arc::clone(&cached.value));
1390        }
1391        let region = self
1392            .region(RegionKind::Alive)
1393            .map_err(crate::lifecycle::StoreError::Segment)?;
1394        #[cfg(any(test, feature = "test-support"))]
1395        account_region_decode(RegionKind::Alive, region.len());
1396        let mut alive = decode_alive(region).map_err(crate::lifecycle::StoreError::Segment)?;
1397        if alive.row_count() != self.meta.row_count {
1398            return Err(crate::lifecycle::StoreError::Segment(
1399                SegmentError::Geometry(format!(
1400                    "alive rows {}, header rows {}",
1401                    alive.row_count(),
1402                    self.meta.row_count
1403                )),
1404            ));
1405        }
1406        alive.compact_for_cache();
1407        let resident_bytes = alive
1408            .resident_bytes()
1409            .and_then(arc_resident_bytes::<AliveSet>)
1410            .ok_or(crate::lifecycle::StoreError::BudgetExceeded {
1411                needed: u64::MAX,
1412                budget: u64::MAX,
1413                component: "snapshot",
1414            })?;
1415        let cached = CachedQueryValue {
1416            value: Arc::new(alive),
1417            _accounting: self.account_query_cache(resident_bytes)?,
1418        };
1419        if self.alive_cache.set(cached).is_err() {
1420            // A concurrent initializer won. Its value and reservation are authoritative.
1421        }
1422        self.alive_cache
1423            .get()
1424            .map(|cached| Arc::clone(&cached.value))
1425            .ok_or(crate::lifecycle::StoreError::Synchronization {
1426                component: "alive query cache",
1427            })
1428    }
1429
1430    /// Resolves the checksum-validated document-version region once, or
1431    /// `None` for segments sealed before the region existed.
1432    fn document_versions_region(&self) -> Result<Option<&[u8]>, SegmentError> {
1433        let Some(entry) = self
1434            .entries
1435            .iter()
1436            .find(|entry| entry.kind == RegionKind::DocumentVersions.id())
1437        else {
1438            return Ok(None);
1439        };
1440        let validation = self.document_versions_validation.get_or_init(|| {
1441            let bytes = self
1442                .region_slice(entry)
1443                .map_err(|error| DocumentVersionValidationError::Geometry(error.to_string()))?;
1444            if region_hash(RegionKind::DocumentVersions, bytes) != entry.checksum {
1445                return Err(DocumentVersionValidationError::Checksum);
1446            }
1447            let expected = (self.meta.row_count as usize)
1448                .checked_mul(24)
1449                .ok_or_else(|| {
1450                    DocumentVersionValidationError::Geometry(
1451                        "document-version length overflow".to_owned(),
1452                    )
1453                })?;
1454            if bytes.len() != expected {
1455                return Err(DocumentVersionValidationError::Geometry(format!(
1456                    "document-version bytes {}, expected {expected}",
1457                    bytes.len()
1458                )));
1459            }
1460            Ok(())
1461        });
1462        if let Err(error) = validation {
1463            return Err(error.clone().into_segment_error(self.meta.id));
1464        }
1465        self.region_slice_unaccounted(entry).map(Some)
1466    }
1467
1468    /// Decodes one optional sealed-row document identity directly from the mapping.
1469    pub fn document_version(&self, row: usize) -> Result<Option<DocumentVersion>, SegmentError> {
1470        let Some(bytes) = self.document_versions_region()? else {
1471            return Ok(None);
1472        };
1473        let start = row
1474            .checked_mul(24)
1475            .ok_or_else(|| SegmentError::Geometry("document-version row overflow".to_owned()))?;
1476        let doc_end = start
1477            .checked_add(16)
1478            .ok_or_else(|| SegmentError::Geometry("document id end overflow".to_owned()))?;
1479        let revision_end = doc_end
1480            .checked_add(8)
1481            .ok_or_else(|| SegmentError::Geometry("revision end overflow".to_owned()))?;
1482        let doc_id = bytes
1483            .get(start..doc_end)
1484            .and_then(|value| value.try_into().ok())
1485            .map(u128::from_le_bytes)
1486            .ok_or_else(|| SegmentError::Geometry(format!("document id row {row} is missing")))?;
1487        let revision = bytes
1488            .get(doc_end..revision_end)
1489            .and_then(|value| value.try_into().ok())
1490            .map(u64::from_le_bytes)
1491            .ok_or_else(|| SegmentError::Geometry(format!("revision row {row} is missing")))?;
1492        Ok(Some(DocumentVersion::new(
1493            DocId::new(doc_id),
1494            Revision::new(revision),
1495        )))
1496    }
1497
1498    /// Finds the sealed row that holds exactly `version`.
1499    ///
1500    /// `None` means the segment predates document versions or holds no row
1501    /// with that exact document id and revision.
1502    pub fn row_for_document_version(
1503        &self,
1504        version: DocumentVersion,
1505    ) -> Result<Option<usize>, SegmentError> {
1506        let Some(bytes) = self.document_versions_region()? else {
1507            return Ok(None);
1508        };
1509        let needle = encode_document_version(version);
1510        Ok(bytes
1511            .chunks_exact(DOCUMENT_VERSION_BYTES)
1512            .position(|entry| entry == needle))
1513    }
1514
1515    /// Finds the sealed row that holds exactly `version` through the cached
1516    /// identity-ordered row permutation, building it on first use.
1517    ///
1518    /// Equal identities resolve to the lowest row, matching a forward scan.
1519    pub(crate) fn query_row_for_document_version(
1520        &self,
1521        version: DocumentVersion,
1522    ) -> Result<Option<usize>, crate::lifecycle::StoreError> {
1523        let Some(bytes) = self
1524            .document_versions_region()
1525            .map_err(crate::lifecycle::StoreError::Segment)?
1526        else {
1527            return Ok(None);
1528        };
1529        let Some(index) = self.query_document_version_index(bytes)? else {
1530            return Ok(None);
1531        };
1532        let needle = encode_document_version(version);
1533        let position =
1534            index.partition_point(|&row| document_version_entry(bytes, row) < needle.as_slice());
1535        Ok(index
1536            .get(position)
1537            .copied()
1538            .filter(|&row| document_version_entry(bytes, row) == needle)
1539            .map(|row| row as usize))
1540    }
1541
1542    /// Finds every live sealed row for `doc_id` through the cached
1543    /// identity-ordered row permutation, building it on first use.
1544    pub(crate) fn query_rows_for_doc_id(
1545        &self,
1546        doc_id: DocId,
1547    ) -> Result<Vec<usize>, crate::lifecycle::StoreError> {
1548        let Some(bytes) = self
1549            .document_versions_region()
1550            .map_err(crate::lifecycle::StoreError::Segment)?
1551        else {
1552            return Ok(Vec::new());
1553        };
1554        let Some(index) = self.query_document_version_index(bytes)? else {
1555            return Ok(Vec::new());
1556        };
1557        let needle = doc_id.get().to_le_bytes();
1558        let start = index.partition_point(|&row| document_id_entry(bytes, row) < needle.as_slice());
1559        let end = index.partition_point(|&row| document_id_entry(bytes, row) <= needle.as_slice());
1560        let matching = index.get(start..end).ok_or_else(|| {
1561            crate::lifecycle::StoreError::Segment(SegmentError::Geometry(
1562                "document-id index range is invalid".to_owned(),
1563            ))
1564        })?;
1565        let alive = self.query_alive()?;
1566        let mut rows = Vec::new();
1567        rows.try_reserve_exact(matching.len()).map_err(|_| {
1568            crate::lifecycle::StoreError::AllocationFailed {
1569                needed: matching
1570                    .len()
1571                    .checked_mul(std::mem::size_of::<usize>())
1572                    .and_then(|bytes| u64::try_from(bytes).ok())
1573                    .unwrap_or(u64::MAX),
1574                component: "document-id rows",
1575            }
1576        })?;
1577        for row in matching {
1578            if alive.is_alive(*row) {
1579                rows.push(*row as usize);
1580            }
1581        }
1582        Ok(rows)
1583    }
1584
1585    fn query_document_version_index(
1586        &self,
1587        bytes: &[u8],
1588    ) -> Result<Option<Arc<Box<[u32]>>>, crate::lifecycle::StoreError> {
1589        if let Some(cached) = self.document_version_index_cache.get() {
1590            return Ok(Some(Arc::clone(&cached.value)));
1591        }
1592        let mut rows: Vec<u32> = (0..self.meta.row_count).collect();
1593        rows.sort_unstable_by(|&left, &right| {
1594            document_version_entry(bytes, left)
1595                .cmp(document_version_entry(bytes, right))
1596                .then(left.cmp(&right))
1597        });
1598        let index = rows.into_boxed_slice();
1599        let resident_bytes = index
1600            .len()
1601            .checked_mul(std::mem::size_of::<u32>())
1602            .and_then(arc_resident_bytes::<Box<[u32]>>)
1603            .ok_or(crate::lifecycle::StoreError::BudgetExceeded {
1604                needed: u64::MAX,
1605                budget: u64::MAX,
1606                component: "snapshot",
1607            })?;
1608        let cached = CachedQueryValue {
1609            value: Arc::new(index),
1610            _accounting: self.account_query_cache(resident_bytes)?,
1611        };
1612        if self.document_version_index_cache.set(cached).is_err() {
1613            // A concurrent initializer won. Its value and reservation are authoritative.
1614        }
1615        self.document_version_index_cache
1616            .get()
1617            .map(|cached| Some(Arc::clone(&cached.value)))
1618            .ok_or(crate::lifecycle::StoreError::Synchronization {
1619                component: "document-version index cache",
1620            })
1621    }
1622
1623    /// Returns validated opaque metadata rows, or `None` for older segments.
1624    pub fn stored_metadata(&self) -> Result<Option<StoredMetadataRows<'_>>, SegmentError> {
1625        let Some(entry) = self
1626            .entries
1627            .iter()
1628            .find(|entry| entry.kind == RegionKind::StoredMetadata.id())
1629        else {
1630            return Ok(None);
1631        };
1632        let region = self.region(RegionKind::StoredMetadata)?;
1633        let declared_rows = region
1634            .get(..4)
1635            .and_then(|value| value.try_into().ok())
1636            .map(u32::from_le_bytes)
1637            .ok_or_else(|| {
1638                SegmentError::Geometry("stored-metadata header is truncated".to_owned())
1639            })?;
1640        let reserved = region
1641            .get(4..8)
1642            .and_then(|value| value.try_into().ok())
1643            .map(u32::from_le_bytes)
1644            .ok_or_else(|| {
1645                SegmentError::Geometry("stored-metadata reserved field is truncated".to_owned())
1646            })?;
1647        if declared_rows != self.meta.row_count || reserved != 0 {
1648            return Err(SegmentError::Geometry(format!(
1649                "stored-metadata rows/reserved {declared_rows}/{reserved}, expected {}/0",
1650                self.meta.row_count
1651            )));
1652        }
1653        let row_count = declared_rows as usize;
1654        let offset_bytes = row_count
1655            .checked_add(1)
1656            .and_then(|count| count.checked_mul(8))
1657            .ok_or_else(|| SegmentError::Geometry("stored-metadata offsets overflow".to_owned()))?;
1658        let offsets_end = 8_usize.checked_add(offset_bytes).ok_or_else(|| {
1659            SegmentError::Geometry("stored-metadata offset end overflow".to_owned())
1660        })?;
1661        let offsets = region.get(8..offsets_end).ok_or_else(|| {
1662            SegmentError::Geometry("stored-metadata offsets are truncated".to_owned())
1663        })?;
1664        let bytes = region.get(offsets_end..).ok_or_else(|| {
1665            SegmentError::Geometry("stored-metadata payload is truncated".to_owned())
1666        })?;
1667        let view = StoredMetadataRows {
1668            offsets,
1669            bytes,
1670            row_count,
1671        };
1672        let first = view
1673            .offsets
1674            .get(..8)
1675            .and_then(|value| value.try_into().ok())
1676            .map(u64::from_le_bytes)
1677            .ok_or_else(|| {
1678                SegmentError::Geometry("stored-metadata first offset is missing".to_owned())
1679            })?;
1680        if first != 0 {
1681            return Err(SegmentError::Geometry(format!(
1682                "stored-metadata first offset is {first}, expected zero"
1683            )));
1684        }
1685        let mut previous = 0_usize;
1686        for row in 0..row_count {
1687            let value = view.row(row).ok_or_else(|| {
1688                SegmentError::Geometry(format!("stored-metadata row {row} is invalid"))
1689            })?;
1690            previous = previous.checked_add(value.len()).ok_or_else(|| {
1691                SegmentError::Geometry("stored-metadata length overflow".to_owned())
1692            })?;
1693        }
1694        if previous != bytes.len() {
1695            return Err(SegmentError::Geometry(format!(
1696                "stored-metadata final offset {previous}, bytes {}",
1697                bytes.len()
1698            )));
1699        }
1700        let _ = entry;
1701        Ok(Some(view))
1702    }
1703
1704    /// Returns validated optional UTF-8 source rows, or `None` for older segments.
1705    ///
1706    /// Every call verifies the region checksum and walks every row offset.
1707    pub fn stored_text(&self) -> Result<Option<StoredTextRows<'_>>, SegmentError> {
1708        let Some(_) = self
1709            .entries
1710            .iter()
1711            .find(|entry| entry.kind == RegionKind::StoredText.id())
1712        else {
1713            return Ok(None);
1714        };
1715        let region = self.region(RegionKind::StoredText)?;
1716        let view = stored_text_view(region, self.meta.row_count)?;
1717        let StoredTextRows {
1718            offsets,
1719            bytes,
1720            row_count,
1721            ..
1722        } = view;
1723        let mut previous = 0_usize;
1724        for row in 0..row_count {
1725            let value = view.row(row).ok_or_else(|| {
1726                SegmentError::Geometry(format!("stored-text row {row} is invalid"))
1727            })?;
1728            let end_index = row.checked_mul(8).ok_or_else(|| {
1729                SegmentError::Geometry("stored-text offset index overflow".to_owned())
1730            })?;
1731            let end = offsets
1732                .get(end_index..end_index + 8)
1733                .and_then(|value| value.try_into().ok())
1734                .map(u64::from_le_bytes)
1735                .and_then(|value| usize::try_from(value).ok())
1736                .ok_or_else(|| {
1737                    SegmentError::Geometry(format!("stored-text offset row {row} is invalid"))
1738                })?;
1739            if end < previous || end > bytes.len() {
1740                return Err(SegmentError::Geometry(format!(
1741                    "stored-text offset row {row} is outside {previous}..={} bytes",
1742                    bytes.len()
1743                )));
1744            }
1745            if value.is_none() && end != previous {
1746                return Err(SegmentError::Geometry(format!(
1747                    "stored-text absent row {row} owns bytes {previous}..{end}"
1748                )));
1749            }
1750            previous = end;
1751        }
1752        if previous != bytes.len() {
1753            return Err(SegmentError::Geometry(format!(
1754                "stored-text final offset {previous}, bytes {}",
1755                bytes.len()
1756            )));
1757        }
1758        Ok(Some(view))
1759    }
1760
1761    /// Query-path twin of [`Self::stored_text`]: the checksum and the full
1762    /// row-offset walk run once per reader, and later calls rebuild the view
1763    /// from the fixed header geometry alone. Like the document-version region,
1764    /// later reads come from the mapping without re-verification. Nothing is
1765    /// retained beyond the validation fact, so there is nothing to account.
1766    pub(crate) fn query_stored_text(&self) -> Result<Option<StoredTextRows<'_>>, SegmentError> {
1767        if self.stored_text_validated.get().is_some() || !Self::query_checksums_enabled() {
1768            let Some(entry) = self
1769                .entries
1770                .iter()
1771                .find(|entry| entry.kind == RegionKind::StoredText.id())
1772            else {
1773                return Ok(None);
1774            };
1775            let region = self.region_slice(entry)?;
1776            return stored_text_view(region, self.meta.row_count).map(Some);
1777        }
1778        let view = self.stored_text()?;
1779        if view.is_some() {
1780            // A concurrent validator may have set this first; same fact either way.
1781            let _ = self.stored_text_validated.set(());
1782        }
1783        Ok(view)
1784    }
1785
1786    /// Query-path twin of [`Self::stored_metadata`]: checksum and row-offset
1787    /// validation run once per reader, then later calls rebuild only the view.
1788    pub(crate) fn query_stored_metadata(
1789        &self,
1790    ) -> Result<Option<StoredMetadataRows<'_>>, SegmentError> {
1791        if self.stored_metadata_validated.get().is_some() || !Self::query_checksums_enabled() {
1792            let Some(entry) = self
1793                .entries
1794                .iter()
1795                .find(|entry| entry.kind == RegionKind::StoredMetadata.id())
1796            else {
1797                return Ok(None);
1798            };
1799            let region = self.region_slice(entry)?;
1800            return stored_metadata_view(region, self.meta.row_count).map(Some);
1801        }
1802        let view = self.stored_metadata()?;
1803        if view.is_some() {
1804            let _ = self.stored_metadata_validated.set(());
1805        }
1806        Ok(view)
1807    }
1808}
1809
1810fn stored_metadata_view(
1811    region: &[u8],
1812    header_rows: u32,
1813) -> Result<StoredMetadataRows<'_>, SegmentError> {
1814    let declared_rows = region
1815        .get(..4)
1816        .and_then(|value| value.try_into().ok())
1817        .map(u32::from_le_bytes)
1818        .ok_or_else(|| SegmentError::Geometry("stored-metadata header is truncated".to_owned()))?;
1819    let reserved = region
1820        .get(4..8)
1821        .and_then(|value| value.try_into().ok())
1822        .map(u32::from_le_bytes)
1823        .ok_or_else(|| {
1824            SegmentError::Geometry("stored-metadata reserved field is truncated".to_owned())
1825        })?;
1826    if declared_rows != header_rows || reserved != 0 {
1827        return Err(SegmentError::Geometry(format!(
1828            "stored-metadata rows/reserved {declared_rows}/{reserved}, expected {header_rows}/0"
1829        )));
1830    }
1831    let row_count = declared_rows as usize;
1832    let offset_bytes = row_count
1833        .checked_add(1)
1834        .and_then(|count| count.checked_mul(8))
1835        .ok_or_else(|| SegmentError::Geometry("stored-metadata offsets overflow".to_owned()))?;
1836    let offsets_end = 8_usize
1837        .checked_add(offset_bytes)
1838        .ok_or_else(|| SegmentError::Geometry("stored-metadata offset end overflow".to_owned()))?;
1839    let offsets = region.get(8..offsets_end).ok_or_else(|| {
1840        SegmentError::Geometry("stored-metadata offsets are truncated".to_owned())
1841    })?;
1842    let bytes = region
1843        .get(offsets_end..)
1844        .ok_or_else(|| SegmentError::Geometry("stored-metadata payload is truncated".to_owned()))?;
1845    Ok(StoredMetadataRows {
1846        offsets,
1847        bytes,
1848        row_count,
1849    })
1850}
1851
1852/// Parses the stored-text header geometry into a row view without walking rows.
1853fn stored_text_view(region: &[u8], header_rows: u32) -> Result<StoredTextRows<'_>, SegmentError> {
1854    {
1855        let declared_rows = region
1856            .get(..4)
1857            .and_then(|value| value.try_into().ok())
1858            .map(u32::from_le_bytes)
1859            .ok_or_else(|| SegmentError::Geometry("stored-text header is truncated".to_owned()))?;
1860        let reserved = region
1861            .get(4..8)
1862            .and_then(|value| value.try_into().ok())
1863            .map(u32::from_le_bytes)
1864            .ok_or_else(|| {
1865                SegmentError::Geometry("stored-text reserved field is truncated".to_owned())
1866            })?;
1867        if declared_rows != header_rows || reserved != 0 {
1868            return Err(SegmentError::Geometry(format!(
1869                "stored-text rows/reserved {declared_rows}/{reserved}, expected {header_rows}/0"
1870            )));
1871        }
1872        let row_count = declared_rows as usize;
1873        let bitmap_len = row_count.div_ceil(8);
1874        let bitmap_end = 8_usize
1875            .checked_add(bitmap_len)
1876            .ok_or_else(|| SegmentError::Geometry("stored-text bitmap overflow".to_owned()))?;
1877        let offsets_len = row_count
1878            .checked_mul(8)
1879            .ok_or_else(|| SegmentError::Geometry("stored-text offsets overflow".to_owned()))?;
1880        let offsets_end = bitmap_end
1881            .checked_add(offsets_len)
1882            .ok_or_else(|| SegmentError::Geometry("stored-text offset end overflow".to_owned()))?;
1883        let present = region.get(8..bitmap_end).ok_or_else(|| {
1884            SegmentError::Geometry("stored-text presence bitmap is truncated".to_owned())
1885        })?;
1886        let offsets = region.get(bitmap_end..offsets_end).ok_or_else(|| {
1887            SegmentError::Geometry("stored-text offsets are truncated".to_owned())
1888        })?;
1889        let bytes = region
1890            .get(offsets_end..)
1891            .ok_or_else(|| SegmentError::Geometry("stored-text payload is truncated".to_owned()))?;
1892        if !row_count.is_multiple_of(8) {
1893            let used = row_count % 8;
1894            let padding_mask = !((1_u8 << used) - 1);
1895            if present.last().is_some_and(|byte| byte & padding_mask != 0) {
1896                return Err(SegmentError::Geometry(
1897                    "stored-text presence padding bits are nonzero".to_owned(),
1898                ));
1899            }
1900        }
1901        Ok(StoredTextRows {
1902            present,
1903            offsets,
1904            bytes,
1905            row_count,
1906        })
1907    }
1908}
1909
1910impl SegmentReader {
1911    /// Returns the validated, mmap-backed fixed-stride graph node-block region.
1912    pub fn graph_node_blocks(&self) -> Result<GraphNodeBlocks<'_>, SegmentError> {
1913        let blocks = decode_node_blocks(self.region(RegionKind::GraphNodeBlocks)?)?;
1914        if blocks.layout().dims() != self.meta.dims {
1915            return Err(SegmentError::Geometry(format!(
1916                "graph dimensions {}, segment dimensions {}",
1917                blocks.layout().dims(),
1918                self.meta.dims
1919            )));
1920        }
1921        if blocks.node_count() != self.meta.row_count {
1922            return Err(SegmentError::Geometry(format!(
1923                "graph nodes {}, segment rows {}",
1924                blocks.node_count(),
1925                self.meta.row_count
1926            )));
1927        }
1928        Ok(blocks)
1929    }
1930
1931    pub(crate) fn bind_validated_graph_node_blocks(
1932        &self,
1933        descriptor: ValidatedGraphNodeBlocks,
1934    ) -> Result<GraphNodeBlocks<'_>, SegmentError> {
1935        let entry = self.entry(RegionKind::GraphNodeBlocks)?;
1936        let bytes = self.region_slice(entry)?;
1937        descriptor.bind(bytes).map_err(SegmentError::Graph)
1938    }
1939
1940    /// Validates every region, alignment padding, and the whole-file trailer.
1941    pub fn validate_all(&self) -> Result<(), SegmentError> {
1942        for entry in &self.entries {
1943            let bytes = self.region_slice(entry)?;
1944            let actual = xxh3_64(bytes);
1945            if actual != entry.checksum {
1946                return Err(FormatError::new(
1947                    format!("segment:{}:region-{}", self.meta.id, entry.kind),
1948                    FormatCheck::BlockChecksum,
1949                    format!("expected {:#018x}, computed {actual:#018x}", entry.checksum),
1950                )
1951                .into());
1952            }
1953        }
1954        let bytes = self.mapping.as_bytes();
1955        let trailer_start = bytes.len().checked_sub(FILE_TRAILER_LEN).ok_or_else(|| {
1956            FormatError::new(
1957                format!("segment: {}", self.meta.id),
1958                FormatCheck::Length,
1959                "missing file trailer",
1960            )
1961        })?;
1962        let expected = read_u64("segment", bytes, trailer_start)?;
1963        let checksummed = bytes.get(..trailer_start).ok_or_else(|| {
1964            FormatError::new("segment", FormatCheck::Length, "invalid trailer position")
1965        })?;
1966        let actual = xxh3_64(checksummed);
1967        if actual != expected {
1968            return Err(FormatError::new(
1969                format!("segment: {}", self.meta.id),
1970                FormatCheck::FileChecksum,
1971                format!("expected {expected:#018x}, computed {actual:#018x}"),
1972            )
1973            .into());
1974        }
1975        Ok(())
1976    }
1977
1978    fn vector_payload(
1979        &self,
1980        kind: RegionKind,
1981    ) -> Result<(super::layout::VectorHeader, &[u8]), SegmentError> {
1982        let region = self.region(kind)?;
1983        let header_bytes = region.get(..VECTOR_HEADER_LEN).ok_or_else(|| {
1984            SegmentError::Geometry(format!("{kind:?} is shorter than vector header"))
1985        })?;
1986        let header = decode_vector_header(header_bytes)?;
1987        if header.dims != self.meta.dims
1988            || header.row_count != self.meta.row_count
1989            || (kind != RegionKind::VectorRescore && header.scheme != self.meta.scheme)
1990        {
1991            return Err(SegmentError::Geometry(format!(
1992                "{kind:?} header scheme/dims/rows {}/{}/{}, segment {}/{}/{}",
1993                header.scheme,
1994                header.dims,
1995                header.row_count,
1996                self.meta.scheme,
1997                self.meta.dims,
1998                self.meta.row_count
1999            )));
2000        }
2001        let payload = region
2002            .get(VECTOR_HEADER_LEN..)
2003            .ok_or_else(|| SegmentError::Geometry(format!("{kind:?} payload offset is invalid")))?;
2004        Ok((header, payload))
2005    }
2006
2007    fn vector_payload_unchecked(
2008        &self,
2009        kind: RegionKind,
2010    ) -> Result<(super::layout::VectorHeader, &[u8]), SegmentError> {
2011        let entry = self.entry(kind)?;
2012        let region = self.region_slice_unaccounted(entry)?;
2013        let header_bytes = region.get(..VECTOR_HEADER_LEN).ok_or_else(|| {
2014            SegmentError::Geometry(format!("{kind:?} is shorter than vector header"))
2015        })?;
2016        let header = decode_vector_header(header_bytes)?;
2017        if header.dims != self.meta.dims
2018            || header.row_count != self.meta.row_count
2019            || (kind != RegionKind::VectorRescore && header.scheme != self.meta.scheme)
2020        {
2021            return Err(SegmentError::Geometry(format!(
2022                "{kind:?} header scheme/dims/rows {}/{}/{}, segment {}/{}/{}",
2023                header.scheme,
2024                header.dims,
2025                header.row_count,
2026                self.meta.scheme,
2027                self.meta.dims,
2028                self.meta.row_count
2029            )));
2030        }
2031        let payload = region
2032            .get(VECTOR_HEADER_LEN..)
2033            .ok_or_else(|| SegmentError::Geometry(format!("{kind:?} payload offset is invalid")))?;
2034        Ok((header, payload))
2035    }
2036
2037    fn validate_rescore_byte_range(&self, start: usize, length: usize) -> Result<(), SegmentError> {
2038        let entry = self.entry(RegionKind::VectorRescore)?;
2039        let region_length = usize::try_from(entry.length).map_err(|_| {
2040            SegmentError::Geometry("rescore region length exceeds usize".to_owned())
2041        })?;
2042        let end = start
2043            .checked_add(length)
2044            .ok_or_else(|| SegmentError::Geometry("rescore byte range overflow".to_owned()))?;
2045        if end > region_length {
2046            return Err(SegmentError::Geometry(format!(
2047                "rescore byte range {start}..{end} exceeds {region_length}"
2048            )));
2049        }
2050        if length == 0 || !Self::query_checksums_enabled() {
2051            return Ok(());
2052        }
2053        let first_chunk = start / CHECKSUM_CHUNK_BYTES;
2054        let last_chunk = end.saturating_sub(1) / CHECKSUM_CHUNK_BYTES;
2055        let mut validated = self.rescore_valid_chunks.lock().map_err(|_| {
2056            SegmentError::Geometry("rescore validation state is poisoned".to_owned())
2057        })?;
2058        for chunk in first_chunk..=last_chunk {
2059            let word = chunk / u64::BITS as usize;
2060            let bit = chunk % u64::BITS as usize;
2061            let mask = 1_u64 << bit;
2062            let state = validated.get_mut(word).ok_or_else(|| {
2063                SegmentError::Geometry(format!("rescore checksum chunk {chunk} is untracked"))
2064            })?;
2065            if *state & mask != 0 {
2066                continue;
2067            }
2068            let chunk_index = u32::try_from(chunk).map_err(|_| {
2069                SegmentError::Geometry("rescore checksum chunk exceeds u32".to_owned())
2070            })?;
2071            self.region_chunk(RegionKind::VectorRescore, chunk_index)?;
2072            *state |= mask;
2073        }
2074        Ok(())
2075    }
2076
2077    fn account_query_cache(
2078        &self,
2079        bytes: usize,
2080    ) -> Result<Option<crate::lifecycle::stats::AccountedCounter>, crate::lifecycle::StoreError>
2081    {
2082        let Some(accounting) = &self.query_accounting else {
2083            return Ok(None);
2084        };
2085        let mut counter = crate::lifecycle::stats::AccountedCounter::new(
2086            accounting,
2087            crate::lifecycle::stats::AllocationComponent::Snapshot,
2088        )?;
2089        counter.set(bytes)?;
2090        Ok(Some(counter))
2091    }
2092
2093    fn entry(&self, kind: RegionKind) -> Result<&RegionEntry, SegmentError> {
2094        self.entries
2095            .iter()
2096            .find(|entry| entry.kind == kind.id())
2097            .ok_or(SegmentError::MissingRegion(kind))
2098    }
2099
2100    fn region_slice(&self, entry: &RegionEntry) -> Result<&[u8], SegmentError> {
2101        let bytes = self.region_slice_unaccounted(entry)?;
2102        account_data_read(bytes.len());
2103        Ok(bytes)
2104    }
2105
2106    fn region_slice_unaccounted(&self, entry: &RegionEntry) -> Result<&[u8], SegmentError> {
2107        let start = usize::try_from(entry.offset)
2108            .map_err(|_| SegmentError::Geometry("region offset exceeds usize".to_owned()))?;
2109        let length = usize::try_from(entry.length)
2110            .map_err(|_| SegmentError::Geometry("region length exceeds usize".to_owned()))?;
2111        let end = start
2112            .checked_add(length)
2113            .ok_or_else(|| SegmentError::Geometry("region end overflow".to_owned()))?;
2114        let bytes = self.mapping.as_bytes().get(start..end).ok_or_else(|| {
2115            SegmentError::Geometry(format!(
2116                "region {} range {start}..{end} exceeds file {}",
2117                entry.kind, self.mapping.length
2118            ))
2119        })?;
2120        Ok(bytes)
2121    }
2122
2123    fn chunk_checksum(&self, kind: RegionKind, chunk_index: u32) -> Result<u64, SegmentError> {
2124        let table = self.region(RegionKind::ChecksumTable)?;
2125        let mut cursor = Cursor::new("checksum-table", table);
2126        let count = cursor.u32()?;
2127        let chunk_size = cursor.u32()?;
2128        if chunk_size as usize != CHECKSUM_CHUNK_BYTES {
2129            return Err(SegmentError::Geometry(format!(
2130                "checksum chunk size {chunk_size}, expected {CHECKSUM_CHUNK_BYTES}"
2131            )));
2132        }
2133        let mut found = None;
2134        for _ in 0..count {
2135            let entry_kind = cursor.u16()?;
2136            let reserved = cursor.u16()?;
2137            let entry_chunk = cursor.u32()?;
2138            let checksum = cursor.u64()?;
2139            if reserved != 0 {
2140                return Err(SegmentError::Geometry(
2141                    "checksum-table reserved field is non-zero".to_owned(),
2142                ));
2143            }
2144            if entry_kind == kind.id() && entry_chunk == chunk_index {
2145                found = Some(checksum);
2146            }
2147        }
2148        cursor.finish().map_err(SegmentError::Geometry)?;
2149        found.ok_or_else(|| {
2150            SegmentError::Geometry(format!(
2151                "checksum table has no {kind:?} chunk {chunk_index}"
2152            ))
2153        })
2154    }
2155}
2156
2157/// Persisted width of one document-version row: a little-endian `u128`
2158/// document id followed by a little-endian `u64` revision.
2159const DOCUMENT_VERSION_BYTES: usize = 24;
2160
2161fn encode_document_version(version: DocumentVersion) -> [u8; DOCUMENT_VERSION_BYTES] {
2162    let doc_id = version.doc_id().get().to_le_bytes();
2163    let revision = version.revision().get().to_le_bytes();
2164    let mut bytes = [0_u8; DOCUMENT_VERSION_BYTES];
2165    for (slot, byte) in bytes.iter_mut().zip(doc_id.into_iter().chain(revision)) {
2166        *slot = byte;
2167    }
2168    bytes
2169}
2170
2171/// Returns the persisted identity bytes of one sealed row. The region length
2172/// is validated as exactly `row_count * 24` before any caller reaches this,
2173/// so the empty fallback is unreachable and sorts consistently if it were not.
2174fn document_version_entry(bytes: &[u8], row: u32) -> &[u8] {
2175    (row as usize)
2176        .checked_mul(DOCUMENT_VERSION_BYTES)
2177        .and_then(|start| bytes.get(start..start.checked_add(DOCUMENT_VERSION_BYTES)?))
2178        .unwrap_or(&[])
2179}
2180
2181fn document_id_entry(bytes: &[u8], row: u32) -> &[u8] {
2182    document_version_entry(bytes, row)
2183        .get(..std::mem::size_of::<u128>())
2184        .unwrap_or(&[])
2185}
2186
2187fn arc_resident_bytes<T>(deep_bytes: usize) -> Option<usize> {
2188    deep_bytes
2189        .checked_add(std::mem::size_of::<T>())?
2190        .checked_add(2 * std::mem::size_of::<usize>())
2191}
2192
2193fn rescore_validation_words(entries: &[RegionEntry]) -> Result<usize, SegmentError> {
2194    let Some(entry) = entries
2195        .iter()
2196        .find(|entry| entry.kind == RegionKind::VectorRescore.id())
2197    else {
2198        return Ok(0);
2199    };
2200    let length = usize::try_from(entry.length)
2201        .map_err(|_| SegmentError::Geometry("rescore region length exceeds usize".to_owned()))?;
2202    let chunks = length.div_ceil(CHECKSUM_CHUNK_BYTES);
2203    Ok(chunks.div_ceil(u64::BITS as usize))
2204}
2205
2206/// Reads and validates only one bounded segment header through a VFS decorator.
2207pub fn validate_header_with_vfs(
2208    vfs: &dyn Vfs,
2209    path: &Path,
2210    expected: &SegmentMeta,
2211) -> Result<usize, SegmentError> {
2212    let actual_length = vfs
2213        .open(path)
2214        .map_err(|error| SegmentError::io(path, error))?;
2215    let mut header_bytes = vfs
2216        .read_range(path, 0, FILE_HEADER_LEN)
2217        .map_err(|error| SegmentError::io(path, error))?;
2218    let artifact = path.display().to_string();
2219    #[cfg(any(test, feature = "test-support"))]
2220    let actual_family = header_bytes
2221        .get(8..10)
2222        .and_then(|family| <[u8; 2]>::try_from(family).ok())
2223        .map(u16::from_le_bytes);
2224    let fixed =
2225        decode_header(&artifact, FormatFamily::Segment, &header_bytes).map_err(|error| {
2226            #[cfg(any(test, feature = "test-support"))]
2227            crate::lifecycle::record_storage_segment_format_fault(
2228                &error,
2229                actual_family,
2230                expected.id,
2231            );
2232            SegmentError::from(error)
2233        })?;
2234    let header_length = usize::try_from(fixed.header_length)
2235        .map_err(|_| SegmentError::Geometry("segment header length exceeds usize".to_owned()))?;
2236    validate_bounded_header_length(&artifact, header_length, actual_length)?;
2237    let remaining = header_length.saturating_sub(FILE_HEADER_LEN);
2238    if remaining > 0 {
2239        let tail = vfs
2240            .read_range(path, FILE_HEADER_LEN as u64, remaining)
2241            .map_err(|error| SegmentError::io(path, error))?;
2242        header_bytes.extend_from_slice(&tail);
2243    }
2244    let parsed = parse_segment_header(&artifact, &header_bytes, actual_length, expected.id)?;
2245    if !parsed.meta.same_segment_file(expected) {
2246        return Err(SegmentError::Geometry(format!(
2247            "manifest metadata {expected:?}, header metadata {:?}",
2248            parsed.meta
2249        )));
2250    }
2251    Ok(header_length)
2252}
2253
2254/// Fuzzing/parser seam that validates arbitrary complete segment bytes without mapping.
2255pub fn validate_segment_bytes(bytes: &[u8]) -> Result<SegmentMeta, SegmentError> {
2256    let id_bytes: [u8; 16] = bytes
2257        .get(FILE_HEADER_LEN..FILE_HEADER_LEN.saturating_add(16))
2258        .ok_or_else(|| {
2259            FormatError::new(
2260                "segment-bytes",
2261                FormatCheck::Length,
2262                format!("missing segment id in {} bytes", bytes.len()),
2263            )
2264        })?
2265        .try_into()
2266        .map_err(|_| {
2267            FormatError::new("segment-bytes", FormatCheck::Length, "invalid segment id")
2268        })?;
2269    let id = SegmentId::from_bytes(id_bytes);
2270    let actual_length = u64::try_from(bytes.len())
2271        .map_err(|_| SegmentError::Geometry("byte slice length exceeds u64".to_owned()))?;
2272    let parsed = parse_segment_header("segment-bytes", bytes, actual_length, id)?;
2273    for entry in &parsed.entries {
2274        let start = usize::try_from(entry.offset)
2275            .map_err(|_| SegmentError::Geometry("region offset exceeds usize".to_owned()))?;
2276        let length = usize::try_from(entry.length)
2277            .map_err(|_| SegmentError::Geometry("region length exceeds usize".to_owned()))?;
2278        let end = start
2279            .checked_add(length)
2280            .ok_or_else(|| SegmentError::Geometry("region end overflow".to_owned()))?;
2281        let region = bytes.get(start..end).ok_or_else(|| {
2282            FormatError::new(
2283                "segment-bytes",
2284                FormatCheck::BlockLength,
2285                format!("region {} range {start}..{end} is truncated", entry.kind),
2286            )
2287        })?;
2288        let actual = xxh3_64(region);
2289        if actual != entry.checksum {
2290            return Err(FormatError::new(
2291                format!("segment-bytes:region-{}", entry.kind),
2292                FormatCheck::BlockChecksum,
2293                format!("expected {:#018x}, computed {actual:#018x}", entry.checksum),
2294            )
2295            .into());
2296        }
2297    }
2298    let trailer = bytes.len().checked_sub(FILE_TRAILER_LEN).ok_or_else(|| {
2299        FormatError::new("segment-bytes", FormatCheck::Length, "missing file trailer")
2300    })?;
2301    let expected = read_u64("segment-bytes", bytes, trailer)?;
2302    let checksummed = bytes.get(..trailer).ok_or_else(|| {
2303        FormatError::new(
2304            "segment-bytes",
2305            FormatCheck::Length,
2306            "invalid trailer offset",
2307        )
2308    })?;
2309    let actual = xxh3_64(checksummed);
2310    if actual != expected {
2311        return Err(FormatError::new(
2312            "segment-bytes",
2313            FormatCheck::FileChecksum,
2314            format!("expected {expected:#018x}, computed {actual:#018x}"),
2315        )
2316        .into());
2317    }
2318    Ok(parsed.meta)
2319}
2320
2321fn preflight_region_count(
2322    artifact: &str,
2323    bytes: &[u8],
2324    actual_file_length: u64,
2325) -> Result<usize, SegmentError> {
2326    let fixed = decode_header(artifact, FormatFamily::Segment, bytes)?;
2327    if fixed.file_length != actual_file_length {
2328        return Err(FormatError::new(
2329            artifact,
2330            FormatCheck::FileLength,
2331            format!(
2332                "declared {}, actual {actual_file_length}",
2333                fixed.file_length
2334            ),
2335        )
2336        .into());
2337    }
2338    let header_length = usize::try_from(fixed.header_length)
2339        .map_err(|_| SegmentError::Geometry("header length exceeds usize".to_owned()))?;
2340    validate_bounded_header_length(artifact, header_length, actual_file_length)?;
2341    let header_bytes = bytes.get(..header_length).ok_or_else(|| {
2342        FormatError::new(
2343            artifact,
2344            FormatCheck::Length,
2345            format!("declared header {header_length}, available {}", bytes.len()),
2346        )
2347    })?;
2348    Ok(usize::from(read_u16(
2349        artifact,
2350        header_bytes,
2351        FILE_HEADER_LEN.saturating_add(20),
2352    )?))
2353}
2354
2355fn parse_segment_header(
2356    artifact: &str,
2357    bytes: &[u8],
2358    actual_file_length: u64,
2359    expected_id: SegmentId,
2360) -> Result<ParsedHeader, SegmentError> {
2361    #[cfg(any(test, feature = "test-support"))]
2362    let actual_family = bytes
2363        .get(8..10)
2364        .and_then(|family| <[u8; 2]>::try_from(family).ok())
2365        .map(u16::from_le_bytes);
2366    let fixed = decode_header(artifact, FormatFamily::Segment, bytes).map_err(|error| {
2367        #[cfg(any(test, feature = "test-support"))]
2368        crate::lifecycle::record_storage_segment_format_fault(&error, actual_family, expected_id);
2369        SegmentError::from(error)
2370    })?;
2371    if fixed.file_length != actual_file_length {
2372        return Err(FormatError::new(
2373            artifact,
2374            FormatCheck::FileLength,
2375            format!(
2376                "declared {}, actual {actual_file_length}",
2377                fixed.file_length
2378            ),
2379        )
2380        .into());
2381    }
2382    let header_length = usize::try_from(fixed.header_length)
2383        .map_err(|_| SegmentError::Geometry("header length exceeds usize".to_owned()))?;
2384    validate_bounded_header_length(artifact, header_length, actual_file_length)?;
2385    let header_bytes = bytes.get(..header_length).ok_or_else(|| {
2386        FormatError::new(
2387            artifact,
2388            FormatCheck::Length,
2389            format!("declared header {header_length}, available {}", bytes.len()),
2390        )
2391    })?;
2392    let id_bytes: [u8; 16] = header_bytes
2393        .get(FILE_HEADER_LEN..FILE_HEADER_LEN.saturating_add(16))
2394        .ok_or_else(|| FormatError::new(artifact, FormatCheck::Length, "missing segment id"))?
2395        .try_into()
2396        .map_err(|_| FormatError::new(artifact, FormatCheck::Length, "invalid segment id"))?;
2397    let actual_id = SegmentId::from_bytes(id_bytes);
2398    if actual_id != expected_id {
2399        #[cfg(any(test, feature = "test-support"))]
2400        crate::lifecycle::record_storage_segment_identity_fault(artifact, expected_id, actual_id);
2401        return Err(SegmentError::WrongObject {
2402            artifact: artifact.to_owned(),
2403            expected: expected_id,
2404            actual: actual_id,
2405        });
2406    }
2407    let row_count = read_u32(artifact, header_bytes, FILE_HEADER_LEN.saturating_add(16))?;
2408    let region_count = usize::from(read_u16(
2409        artifact,
2410        header_bytes,
2411        FILE_HEADER_LEN.saturating_add(20),
2412    )?);
2413    if read_u16(artifact, header_bytes, FILE_HEADER_LEN.saturating_add(22))? != 0 {
2414        return Err(SegmentError::Geometry(
2415            "segment prefix reserved field is non-zero".to_owned(),
2416        ));
2417    }
2418    let scheme = read_u16(artifact, header_bytes, FILE_HEADER_LEN.saturating_add(24))?;
2419    FormatRegistry::require_scheme(scheme)
2420        .map_err(|error| SegmentError::Geometry(error.to_string()))?;
2421    if read_u16(artifact, header_bytes, FILE_HEADER_LEN.saturating_add(26))? != 0 {
2422        return Err(SegmentError::Geometry(
2423            "segment scheme padding is non-zero".to_owned(),
2424        ));
2425    }
2426    let dims = read_u32(artifact, header_bytes, FILE_HEADER_LEN.saturating_add(28))?;
2427    let expected_header_length = FILE_HEADER_LEN
2428        .checked_add(SEGMENT_PREFIX_LEN)
2429        .and_then(|value| value.checked_add(region_count.saturating_mul(REGION_ENTRY_LEN)))
2430        .and_then(|value| value.checked_add(8))
2431        .ok_or_else(|| SegmentError::Geometry("header length overflow".to_owned()))?;
2432    if header_length != expected_header_length {
2433        return Err(FormatError::new(
2434            artifact,
2435            FormatCheck::HeaderLength,
2436            format!("declared {header_length}, directory implies {expected_header_length}"),
2437        )
2438        .into());
2439    }
2440    let checksum_offset = header_length.saturating_sub(8);
2441    let expected_checksum = read_u64(artifact, header_bytes, checksum_offset)?;
2442    let checksum_bytes = header_bytes.get(..checksum_offset).ok_or_else(|| {
2443        FormatError::new(
2444            artifact,
2445            FormatCheck::Length,
2446            "invalid header checksum offset",
2447        )
2448    })?;
2449    let actual_checksum = xxh3_64(checksum_bytes);
2450    if actual_checksum != expected_checksum {
2451        return Err(FormatError::new(
2452            artifact,
2453            FormatCheck::BlockChecksum,
2454            format!("header expected {expected_checksum:#018x}, computed {actual_checksum:#018x}"),
2455        )
2456        .into());
2457    }
2458
2459    let mut entries: Vec<RegionEntry> = Vec::with_capacity(region_count);
2460    let directory_start = FILE_HEADER_LEN.saturating_add(SEGMENT_PREFIX_LEN);
2461    for position in 0..region_count {
2462        let offset = directory_start
2463            .checked_add(position.saturating_mul(REGION_ENTRY_LEN))
2464            .ok_or_else(|| SegmentError::Geometry("directory offset overflow".to_owned()))?;
2465        let entry = RegionEntry {
2466            kind: read_u16(artifact, header_bytes, offset)?,
2467            version: read_u16(artifact, header_bytes, offset.saturating_add(2))?,
2468            reserved: read_u32(artifact, header_bytes, offset.saturating_add(4))?,
2469            offset: read_u64(artifact, header_bytes, offset.saturating_add(8))?,
2470            length: read_u64(artifact, header_bytes, offset.saturating_add(16))?,
2471            checksum: read_u64(artifact, header_bytes, offset.saturating_add(24))?,
2472        };
2473        if entry.reserved != 0 {
2474            return Err(SegmentError::Geometry(format!(
2475                "region {} reserved field is non-zero",
2476                entry.kind
2477            )));
2478        }
2479        if entries.iter().any(|existing| existing.kind == entry.kind) {
2480            return Err(SegmentError::Geometry(format!(
2481                "duplicate region kind {}",
2482                entry.kind
2483            )));
2484        }
2485        validate_entry(artifact, &entry, header_length, actual_file_length)?;
2486        if let Some(kind) = RegionKind::from_id(entry.kind)
2487            && let Some(family) = kind.family()
2488        {
2489            FormatRegistry::require(family.id(), entry.version).map_err(|error| {
2490                FormatError::new(artifact, FormatCheck::Version, error.to_string())
2491            })?;
2492        }
2493        entries.push(entry);
2494    }
2495    validate_non_overlapping(&entries)?;
2496    Ok(ParsedHeader {
2497        meta: SegmentMeta {
2498            id: actual_id,
2499            row_count,
2500            scheme,
2501            dims,
2502            file_size: actual_file_length,
2503            epoch_id: None,
2504            clustering_key_range: super::ClusteringKeyRange::Unstamped,
2505        },
2506        header_length,
2507        entries,
2508    })
2509}
2510
2511fn validate_bounded_header_length(
2512    artifact: &str,
2513    header_length: usize,
2514    actual_file_length: u64,
2515) -> Result<(), SegmentError> {
2516    if !(FILE_HEADER_LEN + SEGMENT_PREFIX_LEN + 8..=MAX_SEGMENT_HEADER_BYTES)
2517        .contains(&header_length)
2518    {
2519        return Err(FormatError::new(
2520            artifact,
2521            FormatCheck::HeaderLength,
2522            format!("header length {header_length} is outside bounded v1 range"),
2523        )
2524        .into());
2525    }
2526    let file_length = usize::try_from(actual_file_length)
2527        .map_err(|_| SegmentError::Geometry("file length exceeds usize".to_owned()))?;
2528    if header_length > file_length.saturating_sub(FILE_TRAILER_LEN) {
2529        return Err(FormatError::new(
2530            artifact,
2531            FormatCheck::HeaderLength,
2532            format!("header {header_length} exceeds file {file_length}"),
2533        )
2534        .into());
2535    }
2536    Ok(())
2537}
2538
2539fn validate_entry(
2540    artifact: &str,
2541    entry: &RegionEntry,
2542    header_length: usize,
2543    file_length: u64,
2544) -> Result<(), SegmentError> {
2545    let offset = usize::try_from(entry.offset)
2546        .map_err(|_| SegmentError::Geometry("region offset exceeds usize".to_owned()))?;
2547    let length = usize::try_from(entry.length)
2548        .map_err(|_| SegmentError::Geometry("region length exceeds usize".to_owned()))?;
2549    let minimum = align_up(header_length, REGION_ALIGNMENT)?;
2550    if offset < minimum || !offset.is_multiple_of(REGION_ALIGNMENT) {
2551        return Err(SegmentError::Geometry(format!(
2552            "region {} offset {offset} is below/aligned from {minimum}",
2553            entry.kind
2554        )));
2555    }
2556    let end = offset
2557        .checked_add(length)
2558        .ok_or_else(|| SegmentError::Geometry("region end overflow".to_owned()))?;
2559    let maximum = usize::try_from(file_length)
2560        .map_err(|_| SegmentError::Geometry("file length exceeds usize".to_owned()))?
2561        .checked_sub(FILE_TRAILER_LEN)
2562        .ok_or_else(|| SegmentError::Geometry("file is shorter than trailer".to_owned()))?;
2563    if end > maximum {
2564        return Err(FormatError::new(
2565            artifact,
2566            FormatCheck::BlockLength,
2567            format!("region {} ends at {end}, maximum {maximum}", entry.kind),
2568        )
2569        .into());
2570    }
2571    Ok(())
2572}
2573
2574fn validate_non_overlapping(entries: &[RegionEntry]) -> Result<(), SegmentError> {
2575    for (position, entry) in entries.iter().enumerate() {
2576        let entry_end = entry
2577            .offset
2578            .checked_add(entry.length)
2579            .ok_or_else(|| SegmentError::Geometry("region u64 end overflow".to_owned()))?;
2580        for other in entries.iter().skip(position.saturating_add(1)) {
2581            let other_end = other
2582                .offset
2583                .checked_add(other.length)
2584                .ok_or_else(|| SegmentError::Geometry("region u64 end overflow".to_owned()))?;
2585            if entry.offset < other_end && other.offset < entry_end {
2586                let (previous, current, previous_end) = if entry.offset <= other.offset {
2587                    (entry, other, entry_end)
2588                } else {
2589                    (other, entry, other_end)
2590                };
2591                return Err(SegmentError::Geometry(format!(
2592                    "region {} begins {} before previous end {previous_end} for region {}",
2593                    current.kind, current.offset, previous.kind
2594                )));
2595            }
2596        }
2597    }
2598    Ok(())
2599}
2600
2601fn cast_slice<'a, T>(
2602    bytes: &'a [u8],
2603    count: usize,
2604    artifact: &str,
2605) -> Result<&'a [T], SegmentError> {
2606    #[cfg(target_endian = "big")]
2607    {
2608        let _ = (bytes, count);
2609        return Err(SegmentError::Geometry(format!(
2610            "{artifact} zero-copy requires little-endian target"
2611        )));
2612    }
2613    #[cfg(target_endian = "little")]
2614    {
2615        let expected = count
2616            .checked_mul(std::mem::size_of::<T>())
2617            .ok_or_else(|| SegmentError::Geometry(format!("{artifact} byte length overflow")))?;
2618        if bytes.len() != expected {
2619            return Err(SegmentError::Geometry(format!(
2620                "{artifact} bytes {}, expected {expected}",
2621                bytes.len()
2622            )));
2623        }
2624        if !(bytes.as_ptr() as usize).is_multiple_of(std::mem::align_of::<T>()) {
2625            return Err(SegmentError::Geometry(format!(
2626                "{artifact} address is not {}-byte aligned",
2627                std::mem::align_of::<T>()
2628            )));
2629        }
2630        // SAFETY: byte length and alignment were checked above; T is one of the
2631        // pinned repr(C) all-f32 record types (or f32), and the checksum plus
2632        // little-endian target makes the mapped representation valid.
2633        Ok(unsafe { std::slice::from_raw_parts(bytes.as_ptr().cast::<T>(), count) })
2634    }
2635}