Skip to main content

weavatrix_search_vector/bundle/
mod.rs

1mod codec;
2mod format;
3mod io;
4mod mutable_api;
5mod reader;
6mod validation;
7mod writer;
8
9use crate::error::SearchError;
10use crate::mutable::MutableVectorIndex;
11use crate::quantized::QuantizedIndex;
12use std::path::Path;
13
14/// Atomic persistence unit for mutable f32 state and an optional compact
15/// representation.
16#[derive(Debug)]
17pub struct IndexBundle {
18    mutable: MutableVectorIndex,
19    quantized: Option<QuantizedIndex>,
20}
21
22impl IndexBundle {
23    /// Creates a validated bundle.
24    ///
25    /// # Errors
26    ///
27    /// Returns an error when the compact representation does not describe the
28    /// same active key set and configuration as the mutable index.
29    pub fn new(
30        mutable: MutableVectorIndex,
31        quantized: Option<QuantizedIndex>,
32    ) -> Result<Self, SearchError> {
33        validation::validate_quantized(&mutable.snapshot(), quantized.as_ref())?;
34        Ok(Self { mutable, quantized })
35    }
36
37    /// Returns the mutable f32 index and its delta/metadata state.
38    #[must_use]
39    pub const fn mutable(&self) -> &MutableVectorIndex {
40        &self.mutable
41    }
42
43    /// Returns mutable access to the f32 index.
44    ///
45    /// Callers replacing active vectors must also replace or remove the
46    /// compact representation before saving.
47    #[must_use]
48    pub const fn mutable_mut(&mut self) -> &mut MutableVectorIndex {
49        &mut self.mutable
50    }
51
52    /// Returns the optional compact representation.
53    #[must_use]
54    pub const fn quantized(&self) -> Option<&QuantizedIndex> {
55        self.quantized.as_ref()
56    }
57
58    /// Replaces the compact representation after validating bundle identity.
59    ///
60    /// # Errors
61    ///
62    /// Returns an error when config or active keys differ.
63    pub fn set_quantized(&mut self, quantized: Option<QuantizedIndex>) -> Result<(), SearchError> {
64        validation::validate_quantized(&self.mutable.snapshot(), quantized.as_ref())?;
65        self.quantized = quantized;
66        Ok(())
67    }
68
69    /// Consumes the bundle.
70    #[must_use]
71    pub fn into_parts(self) -> (MutableVectorIndex, Option<QuantizedIndex>) {
72        (self.mutable, self.quantized)
73    }
74
75    /// Atomically saves vectors, graphs, mutation delta, metadata, and compact
76    /// representation under one checksum.
77    ///
78    /// # Errors
79    ///
80    /// Returns a consistency, serialization, or filesystem error.
81    pub fn save(&self, path: impl AsRef<Path>) -> Result<(), SearchError> {
82        writer::save_complete(&self.mutable, self.quantized.as_ref(), path.as_ref())
83    }
84
85    /// Loads and validates a complete bundle.
86    ///
87    /// # Errors
88    ///
89    /// Returns a filesystem, integrity, format, or consistency error.
90    pub fn load(path: impl AsRef<Path>) -> Result<Self, SearchError> {
91        let (mutable, quantized) = reader::load_complete(path.as_ref())?;
92        Self::new(mutable, quantized)
93    }
94}