pub struct VectorIndex { /* private fields */ }Expand description
Thread-safe vector index for approximate nearest neighbor search.
Wraps usearch Index with ergonomic Rust API. The underlying index is already thread-safe (Send + Sync) for concurrent read/write operations.
§Vector IDs
Vector IDs are u64 keys that should map to your EmbeddingUnit indices. The index does not store metadata - that should be kept separately (typically in a JSON metadata file alongside the index).
§Persistence
Indexes can be saved to disk with save and loaded with
load. The view method provides memory-mapped
access for large indexes that don’t fit in RAM.
Implementations§
Source§impl VectorIndex
impl VectorIndex
Sourcepub fn new(dimensions: usize, metric: Metric) -> Result<Self>
pub fn new(dimensions: usize, metric: Metric) -> Result<Self>
Create a new vector index with the given dimensions and metric.
§Arguments
dimensions- Number of dimensions in embedding vectorsmetric- Distance metric for similarity computation
§Errors
Returns error if usearch index creation fails.
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
// Create index for 768-dim embeddings with inner product metric
let index = VectorIndex::new(768, Metric::InnerProduct)?;Sourcepub fn with_config(config: IndexConfig) -> Result<Self>
pub fn with_config(config: IndexConfig) -> Result<Self>
Create a new vector index with full configuration.
§Examples
use go_brrr::embedding::{VectorIndex, IndexConfig, Metric, Quantization};
let config = IndexConfig::new(1024)
.with_metric(Metric::InnerProduct)
.with_quantization(Quantization::F16)
.with_connectivity(32);
let index = VectorIndex::with_config(config)?;Sourcepub fn config(&self) -> &IndexConfig
pub fn config(&self) -> &IndexConfig
Get the index configuration.
Sourcepub fn dimensions(&self) -> usize
pub fn dimensions(&self) -> usize
Get the number of dimensions.
Sourcepub fn memory_usage(&self) -> usize
pub fn memory_usage(&self) -> usize
Get estimated memory usage in bytes.
Sourcepub fn to_similarity_scores(&self, distances: &[f32]) -> Vec<f32>
pub fn to_similarity_scores(&self, distances: &[f32]) -> Vec<f32>
Convert raw distances to similarity scores using this index’s metric.
Different metrics require different conversion formulas:
InnerProduct/Cosine: score = 1 - distance (clamped to [0, 1])L2Squared: score = 1 / (1 + distance) (maps [0, inf) to (0, 1])
§Arguments
distances- Raw distance values from search results
§Returns
Similarity scores in [0, 1] range, where 1.0 = perfect match.
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::L2Squared)?;
let distances = vec![0.0, 1.0, 4.0];
let scores = index.to_similarity_scores(&distances);
// L2: 0.0 -> 1.0, 1.0 -> 0.5, 4.0 -> 0.2
assert!((scores[0] - 1.0).abs() < 1e-6);
assert!((scores[1] - 0.5).abs() < 1e-6);
assert!((scores[2] - 0.2).abs() < 1e-6);Sourcepub fn contains(&self, key: u64) -> bool
pub fn contains(&self, key: u64) -> bool
Check if the index contains a vector with the given key.
Sourcepub fn count_key(&self, key: u64) -> usize
pub fn count_key(&self, key: u64) -> usize
Count vectors with a specific key (for multi-index mode).
In standard mode, returns 1 if key exists, 0 otherwise. In multi-index mode, returns the number of vectors stored under this key.
§Arguments
key- The vector key to count
§Returns
Number of vectors associated with the key.
§Examples
use go_brrr::embedding::{VectorIndex, IndexConfig, Metric};
// Multi-index mode allows multiple vectors per key
let config = IndexConfig::new(4)
.with_metric(Metric::InnerProduct)
.with_multi(true);
let index = VectorIndex::with_config(config)?;
index.reserve(10)?;
let key = 42u64;
index.add(key, &[1.0, 0.0, 0.0, 0.0])?;
index.add(key, &[0.0, 1.0, 0.0, 0.0])?;
assert_eq!(index.count_key(key), 2);
assert_eq!(index.count_key(999), 0); // Non-existent keySourcepub fn get(&self, key: u64) -> Option<Vec<f32>>
pub fn get(&self, key: u64) -> Option<Vec<f32>>
Retrieve a vector by its key.
Returns None if the key doesn’t exist in the index.
§Arguments
key- The unique identifier of the vector to retrieve
§Returns
The stored vector if the key exists, None otherwise.
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::InnerProduct)?;
index.reserve(10)?;
index.add(42, &[1.0, 0.0, 0.0, 0.0])?;
let retrieved = index.get(42);
assert!(retrieved.is_some());
assert_eq!(retrieved.unwrap(), vec![1.0, 0.0, 0.0, 0.0]);
// Non-existent key returns None
assert!(index.get(999).is_none());Sourcepub fn get_batch(&self, keys: &[u64]) -> Vec<Option<Vec<f32>>>
pub fn get_batch(&self, keys: &[u64]) -> Vec<Option<Vec<f32>>>
Retrieve multiple vectors by their keys.
Returns a Vec of Option<Vec<f32>> in the same order as the input keys.
Each element is Some(vector) if the key exists, None otherwise.
§Arguments
keys- Slice of unique identifiers to retrieve
§Returns
Vector of optional vectors, maintaining input order.
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::InnerProduct)?;
index.reserve(10)?;
index.add(1, &[1.0, 0.0, 0.0, 0.0])?;
index.add(3, &[0.0, 1.0, 0.0, 0.0])?;
let results = index.get_batch(&[1, 2, 3]);
assert!(results[0].is_some()); // Key 1 exists
assert!(results[1].is_none()); // Key 2 doesn't exist
assert!(results[2].is_some()); // Key 3 existsSourcepub fn add(&self, key: u64, vector: &[f32]) -> Result<()>
pub fn add(&self, key: u64, vector: &[f32]) -> Result<()>
Add a single vector to the index.
§Arguments
key- Unique identifier for the vector (maps to EmbeddingUnit index)vector- Embedding vector (must match index dimensions)
§Errors
Returns error if:
- Vector dimensions don’t match index dimensions
- Index insertion fails
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::Cosine)?;
index.reserve(10)?; // Must reserve capacity before adding vectors
index.add(42, &[0.1, 0.2, 0.3, 0.4])?;Sourcepub fn add_batch(&self, keys: &[u64], vectors: &[Vec<f32>]) -> Result<()>
pub fn add_batch(&self, keys: &[u64], vectors: &[Vec<f32>]) -> Result<()>
Add multiple vectors to the index in batch.
More efficient than calling add repeatedly due to better memory locality.
§Arguments
keys- Vector of unique identifiersvectors- Slice of embedding vectors (each must match index dimensions)
§Errors
Returns error if:
- Keys and vectors have different lengths
- Any vector has wrong dimensions
- Index insertion fails
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::InnerProduct)?;
index.reserve(100)?;
let keys = vec![0, 1, 2];
let vectors = vec![
vec![0.1, 0.2, 0.3, 0.4],
vec![0.5, 0.6, 0.7, 0.8],
vec![0.9, 0.1, 0.2, 0.3],
];
index.add_batch(&keys, &vectors)?;Sourcepub fn add_batch_sequential(
&self,
keys: &[u64],
vectors: &[Vec<f32>],
) -> Result<()>
pub fn add_batch_sequential( &self, keys: &[u64], vectors: &[Vec<f32>], ) -> Result<()>
Add multiple vectors sequentially (for when insertion order matters).
Unlike add_batch, this method guarantees vectors are added in the
order provided. Use this when vector order affects search results
or when debugging insertion issues.
§Arguments
keys- Vector of unique identifiersvectors- Slice of embedding vectors (each must match index dimensions)
Sourcepub fn add_batch_flat(&self, keys: &[u64], vectors_flat: &[f32]) -> Result<()>
pub fn add_batch_flat(&self, keys: &[u64], vectors_flat: &[f32]) -> Result<()>
Add multiple vectors from a flat array (more efficient for large batches).
Uses parallel insertion for batches >= 100 vectors. The flat array format
is more cache-friendly than Vec<Vec
§Arguments
keys- Vector of unique identifiersvectors_flat- Flat array of all vectors concatenated
§Errors
Returns error if flat array size doesn’t match keys * dimensions.
Sourcepub fn search(&self, query: &[f32], k: usize) -> Result<Vec<(u64, f32)>>
pub fn search(&self, query: &[f32], k: usize) -> Result<Vec<(u64, f32)>>
Search for k nearest neighbors to the query vector.
Returns results sorted by distance (ascending - closest first). For inner product metric, lower distance = higher similarity.
§Arguments
query- Query embedding vector (must match index dimensions)k- Maximum number of results to return
§Returns
Vector of (key, distance) pairs sorted by distance.
§Errors
Returns error if:
- Query dimensions don’t match index dimensions
- Search fails
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::InnerProduct)?;
index.reserve(10)?; // Must reserve capacity before adding vectors
index.add(0, &[0.1, 0.2, 0.3, 0.4])?;
index.add(1, &[0.5, 0.6, 0.7, 0.8])?;
let results = index.search(&[0.1, 0.2, 0.3, 0.4], 10)?;
// results[0] should be (0, ~0.0) - exact matchSourcepub fn search_exact(&self, query: &[f32], k: usize) -> Result<Vec<(u64, f32)>>
pub fn search_exact(&self, query: &[f32], k: usize) -> Result<Vec<(u64, f32)>>
Search with exact brute-force computation (slower but guaranteed optimal).
Use this for verification or when approximate results aren’t acceptable.
Sourcepub fn search_filtered<F>(
&self,
query: &[f32],
k: usize,
filter: F,
) -> Result<Vec<(u64, f32)>>
pub fn search_filtered<F>( &self, query: &[f32], k: usize, filter: F, ) -> Result<Vec<(u64, f32)>>
Search with a filter predicate.
Only returns results where the filter function returns true for the key.
§Arguments
query- Query embedding vectork- Maximum number of resultsfilter- Predicate function:fn(key) -> bool
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::InnerProduct)?;
index.reserve(100)?; // Must reserve capacity before adding vectors
// Add vectors with keys 0-99
for i in 0..100 {
index.add(i, &[0.1 * i as f32; 4])?;
}
// Only search among even-keyed vectors
let results = index.search_filtered(&[0.5; 4], 10, |key| key % 2 == 0)?;
assert!(results.iter().all(|(k, _)| k % 2 == 0));Sourcepub fn search_threshold(
&self,
query: &[f32],
k: usize,
threshold: f32,
) -> Result<Vec<(u64, f32)>>
pub fn search_threshold( &self, query: &[f32], k: usize, threshold: f32, ) -> Result<Vec<(u64, f32)>>
Search with a distance threshold filter.
Returns only results where the distance is less than or equal to the threshold. This is useful for semantic search where you want to filter out dissimilar results.
§Arguments
query- Query embedding vectork- Maximum number of resultsthreshold- Maximum distance threshold (results with distance > threshold are filtered)
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::InnerProduct)?;
index.reserve(10)?;
index.add(0, &[1.0, 0.0, 0.0, 0.0])?;
index.add(1, &[0.9, 0.1, 0.0, 0.0])?;
index.add(2, &[0.0, 0.0, 1.0, 0.0])?;
// Search with threshold to filter distant results
let results = index.search_threshold(&[1.0, 0.0, 0.0, 0.0], 10, 0.5)?;
// Only returns vectors within distance 0.5Sourcepub fn rename(&self, from_key: u64, to_key: u64) -> Result<usize>
pub fn rename(&self, from_key: u64, to_key: u64) -> Result<usize>
Rename a key in the index.
Moves all vectors from from_key to to_key.
Returns the number of vectors renamed (0 if from_key didn’t exist).
§Errors
Returns error if:
to_keyalready exists in the index (would cause data loss)- The underlying rename operation fails
§Examples
use go_brrr::embedding::{VectorIndex, IndexConfig, Metric};
let config = IndexConfig::new(4).with_metric(Metric::InnerProduct);
let index = VectorIndex::with_config(config)?;
index.reserve(10)?;
index.add(42, &[1.0, 0.0, 0.0, 0.0])?;
assert!(index.contains(42));
let renamed = index.rename(42, 100)?;
assert_eq!(renamed, 1);
assert!(!index.contains(42));
assert!(index.contains(100));Sourcepub fn rename_overwrite(&self, from_key: u64, to_key: u64) -> Result<usize>
pub fn rename_overwrite(&self, from_key: u64, to_key: u64) -> Result<usize>
Rename a key, overwriting target if it exists.
Removes any existing vectors at to_key before renaming.
Returns the number of vectors renamed (0 if from_key didn’t exist).
§Examples
use go_brrr::embedding::{VectorIndex, IndexConfig, Metric};
let config = IndexConfig::new(4).with_metric(Metric::InnerProduct);
let index = VectorIndex::with_config(config)?;
index.reserve(10)?;
index.add(42, &[1.0, 0.0, 0.0, 0.0])?;
index.add(100, &[0.0, 1.0, 0.0, 0.0])?; // Existing key
let renamed = index.rename_overwrite(42, 100)?;
assert_eq!(renamed, 1);
assert!(!index.contains(42));
assert!(index.contains(100));Sourcepub fn clear(&self) -> Result<()>
pub fn clear(&self) -> Result<()>
Clear all vectors from the index.
Releases memory back to the OS.
Sourcepub fn save(&self, path: impl AsRef<Path>) -> Result<()>
pub fn save(&self, path: impl AsRef<Path>) -> Result<()>
Save the index to a file atomically.
Uses a temp file + atomic rename pattern to prevent corruption on crash.
Creates a .usearch file that can be loaded with load
or memory-mapped with view.
§Atomic Write Strategy
- Creates a temporary file in the same directory as the target
- Writes index data to the temporary file
- Atomically renames the temp file to the target path
This ensures that if a crash occurs mid-write, the original file (if any) remains intact. The atomic rename is guaranteed by POSIX on Unix systems when source and destination are on the same filesystem.
§Arguments
path- File path to save to (typically with.usearchextension)
§Errors
Returns error if:
- Parent directory does not exist or is not writable
- Temporary file cannot be created
- Index serialization fails
- Atomic rename fails
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(768, Metric::InnerProduct)?;
index.reserve(100)?;
// ... add vectors ...
index.save("./index.usearch")?; // Crash-safe writeSourcepub fn save_unsafe(&self, path: impl AsRef<Path>) -> Result<()>
pub fn save_unsafe(&self, path: impl AsRef<Path>) -> Result<()>
Save the index directly to file without atomic write protection.
This is faster than save but risky: if a crash occurs
mid-write, the file may be corrupted. Use only when:
- Speed is critical and corruption risk is acceptable
- The file is easily regenerable
- You have your own backup/recovery mechanism
§Arguments
path- File path to save to (typically with.usearchextension)
§Errors
Returns error if file cannot be written.
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(768, Metric::InnerProduct)?;
index.reserve(100)?;
// ... add vectors ...
index.save_unsafe("./index.usearch")?; // Faster but not crash-safeSourcepub fn restore(path: impl AsRef<Path>) -> Result<Self>
pub fn restore(path: impl AsRef<Path>) -> Result<Self>
Restore an index from file, reading configuration from the file itself.
This is the SAFE way to load an index - dimensions and settings are read from the file header, not provided by the caller. This prevents dimension mismatches that could cause undefined behavior.
§Arguments
path- Path to.usearchfile
§Errors
Returns error if:
- File does not exist or cannot be read
- File format is invalid
§Examples
use go_brrr::embedding::VectorIndex;
// Safe load - dimensions come from the file
let index = VectorIndex::restore("./index.usearch")?;
println!("Loaded index with {} dimensions", index.dimensions());Sourcepub fn load_validated(
path: impl AsRef<Path>,
config: IndexConfig,
) -> Result<Self>
pub fn load_validated( path: impl AsRef<Path>, config: IndexConfig, ) -> Result<Self>
Load an index with explicit configuration validation.
First loads the index safely (reading dimensions from file), then validates that the loaded dimensions match the expected config. This is useful when you need to ensure the loaded index matches expected parameters.
§Arguments
path- Path to.usearchfileconfig- Expected configuration (dimensions will be validated)
§Errors
Returns error if:
- File does not exist or cannot be read
- File format is invalid
- Loaded dimensions don’t match config dimensions
§Examples
use go_brrr::embedding::{VectorIndex, IndexConfig, Metric};
// Load with validation - error if dimensions don't match
let config = IndexConfig::new(768).with_metric(Metric::InnerProduct);
let index = VectorIndex::load_validated("./index.usearch", config)?;Sourcepub fn load(path: impl AsRef<Path>, config: IndexConfig) -> Result<Self>
👎Deprecated since 1.2.0: Use restore() for safe loading or load_validated() for validated loading
pub fn load(path: impl AsRef<Path>, config: IndexConfig) -> Result<Self>
restore() for safe loading or load_validated() for validated loadingLoad an index from a file (legacy API, prefer restore or load_validated).
This method is kept for backward compatibility. It now safely loads the index first, then validates dimensions. For new code, prefer:
restore: Safe load without dimension constraintsload_validated: Safe load with dimension validation
§Arguments
path- Path to.usearchfileconfig- Configuration matching the saved index
§Errors
Returns error if:
- File does not exist or cannot be read
- File format is invalid
- Configuration dimensions don’t match saved index
Sourcepub fn view_restore(path: impl AsRef<Path>) -> Result<Self>
pub fn view_restore(path: impl AsRef<Path>) -> Result<Self>
Create a memory-mapped view of an index file, reading config from file.
This is the SAFE way to view an index - dimensions and settings are read from the file header, not provided by the caller. This prevents dimension mismatches that could cause undefined behavior.
Does not load the index into memory - reads directly from the file. Ideal for large indexes that don’t fit in RAM.
§Safety Note
The file must not be modified or deleted while the view is active.
§Arguments
path- Path to.usearchfile
§Examples
use go_brrr::embedding::VectorIndex;
// Safe view - dimensions come from the file
let index = VectorIndex::view_restore("./index.usearch")?;
println!("Viewing index with {} dimensions", index.dimensions());Sourcepub fn view_validated(
path: impl AsRef<Path>,
config: IndexConfig,
) -> Result<Self>
pub fn view_validated( path: impl AsRef<Path>, config: IndexConfig, ) -> Result<Self>
View an index with explicit configuration validation.
First views the index safely (reading dimensions from file), then validates that the dimensions match the expected config.
§Arguments
path- Path to.usearchfileconfig- Expected configuration (dimensions will be validated)
§Safety Note
The file must not be modified or deleted while the view is active.
§Errors
Returns error if:
- File does not exist or cannot be read
- File format is invalid
- Loaded dimensions don’t match config dimensions
§Examples
use go_brrr::embedding::{VectorIndex, IndexConfig, Metric};
// View with validation - error if dimensions don't match
let config = IndexConfig::new(768).with_metric(Metric::InnerProduct);
let index = VectorIndex::view_validated("./index.usearch", config)?;Sourcepub fn view(path: impl AsRef<Path>, config: IndexConfig) -> Result<Self>
👎Deprecated since 1.2.0: Use view_safe() for proper file lifecycle management
pub fn view(path: impl AsRef<Path>, config: IndexConfig) -> Result<Self>
view_safe() for proper file lifecycle managementCreate a memory-mapped view of an index file (legacy API).
This method is kept for backward compatibility. It now safely views the index first, then validates dimensions. For new code, prefer:
view_restore: Safe view without dimension constraintsview_validated: Safe view with dimension validation
§Arguments
path- Path to.usearchfileconfig- Configuration matching the saved index
§Safety Note
The file must not be modified or deleted while the view is active.
Sourcepub fn view_safe(path: impl AsRef<Path>) -> Result<IndexView>
pub fn view_safe(path: impl AsRef<Path>) -> Result<IndexView>
Create a memory-mapped view with proper file lifecycle management.
This is the SAFEST way to view an index. The returned IndexView:
- Keeps the file handle open to prevent file deletion issues
- Reads dimensions from the file header automatically
- Provides
is_valid()to check if the backing file still exists
On Unix systems, keeping the file handle open ensures the data remains accessible even if the file is unlinked from the filesystem.
§Arguments
path- Path to.usearchfile
§Safety Note
The file must not be modified while the view is active. However, deletion is handled safely by keeping the file handle open.
§Examples
use go_brrr::embedding::VectorIndex;
// Create a safe view with file lifecycle management
let view = VectorIndex::view_safe("./index.usearch")?;
assert!(view.is_valid());
println!("Viewing index with {} dimensions", view.dimensions());
// View is usable even if file gets deleted (on Unix)
let results = view.search(&[1.0, 0.0, 0.0, 0.0], 10)?;Sourcepub fn view_validated_safe(
path: impl AsRef<Path>,
config: IndexConfig,
) -> Result<IndexView>
pub fn view_validated_safe( path: impl AsRef<Path>, config: IndexConfig, ) -> Result<IndexView>
Create a safe view with explicit configuration validation.
Combines the safety of view_safe with dimension
validation. Returns an error if the file dimensions don’t match the
expected config.
§Arguments
path- Path to.usearchfileconfig- Expected configuration (dimensions will be validated)
§Safety Note
The file must not be modified while the view is active. However, deletion is handled safely by keeping the file handle open.
§Errors
Returns error if:
- File does not exist or cannot be read
- File format is invalid
- Loaded dimensions don’t match config dimensions (if config.dimensions != 0)
§Examples
use go_brrr::embedding::{VectorIndex, IndexConfig, Metric};
// Safe view with dimension validation
let config = IndexConfig::new(768).with_metric(Metric::InnerProduct);
let view = VectorIndex::view_validated_safe("./index.usearch", config)?;
// Can use view methods or deref to VectorIndex
let results = view.search(&[0.1f32; 768], 10)?;Sourcepub fn serialized_size(&self) -> usize
pub fn serialized_size(&self) -> usize
Get the serialized size of the index in bytes.
Use this to pre-allocate buffers before calling to_bytes.
The returned size includes all index data and metadata.
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::InnerProduct)?;
index.reserve(10)?;
index.add(0, &[1.0, 0.0, 0.0, 0.0])?;
let size = index.serialized_size();
println!("Index will serialize to {} bytes", size);Sourcepub fn check_disk_space(&self, path: impl AsRef<Path>) -> Result<bool>
pub fn check_disk_space(&self, path: impl AsRef<Path>) -> Result<bool>
Check if there’s enough disk space to save the index.
Uses the fs2 crate for cross-platform disk space detection.
Includes a safety margin (10% or at least 1MB) to account for
filesystem overhead and metadata.
§Arguments
path- Target file path. The parent directory is checked for available space.
§Returns
Ok(true)if there’s enough spaceOk(false)if there’s insufficient spaceErrif the disk space check fails (e.g., path doesn’t exist)
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(768, Metric::InnerProduct)?;
index.reserve(10000)?;
// ... add vectors ...
if index.check_disk_space("./index.usearch")? {
index.save("./index.usearch")?;
} else {
eprintln!("Insufficient disk space!");
}Sourcepub fn save_checked(&self, path: impl AsRef<Path>) -> Result<SaveInfo>
pub fn save_checked(&self, path: impl AsRef<Path>) -> Result<SaveInfo>
Save index with disk space verification.
This is the SAFEST way to save an index. It:
- Checks available disk space before writing
- Uses atomic write (temp file + rename)
- Returns detailed information about the save operation
§Arguments
path- File path to save to (typically with.usearchextension)
§Returns
SaveInfo containing path, size, duration, and space information.
§Errors
Returns error if:
- Insufficient disk space (with detailed message)
- Parent directory does not exist
- File write fails
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(768, Metric::InnerProduct)?;
index.reserve(10000)?;
// ... add vectors ...
let info = index.save_checked("./index.usearch")?;
println!("Saved {} bytes in {:?}", info.size_bytes, info.elapsed);Sourcepub fn to_bytes(&self) -> Result<Vec<u8>>
pub fn to_bytes(&self) -> Result<Vec<u8>>
Serialize the index to a byte vector.
This enables storing the index in Redis, sending over network, or any other scenario where file-based persistence is not suitable.
The serialized format includes all vectors and the HNSW graph structure.
Use from_bytes to deserialize.
§Performance
Serialization is O(n) where n is the number of vectors. The resulting
buffer size is approximately serialized_size() bytes.
§Errors
Returns error if serialization fails (e.g., internal usearch error).
§Examples
use go_brrr::embedding::{VectorIndex, IndexConfig, Metric};
let config = IndexConfig::new(4).with_metric(Metric::InnerProduct);
let index = VectorIndex::with_config(config.clone())?;
index.reserve(10)?;
index.add(1, &[1.0, 0.0, 0.0, 0.0])?;
// Serialize to bytes
let bytes = index.to_bytes()?;
// Store in Redis, send over network, etc.
// redis_client.set("my_index", &bytes)?;
// Later, deserialize
let restored = VectorIndex::from_bytes(&bytes, config)?;
assert_eq!(restored.len(), 1);Sourcepub fn from_bytes(data: &[u8], config: IndexConfig) -> Result<Self>
pub fn from_bytes(data: &[u8], config: IndexConfig) -> Result<Self>
Load an index from a byte slice.
Deserializes an index previously serialized with to_bytes.
The provided config specifies index parameters; dimensions are validated
against the loaded data.
§Arguments
data- Serialized index data fromto_bytes()config- Index configuration. Ifdimensionsis 0, dimensions are read from the serialized data without validation.
§Errors
Returns error if:
- Data is corrupted or not a valid usearch index
- Loaded dimensions don’t match config dimensions (when config.dimensions > 0)
§Examples
use go_brrr::embedding::{VectorIndex, IndexConfig, Metric};
// Create and serialize an index
let config = IndexConfig::new(4).with_metric(Metric::InnerProduct);
let original = VectorIndex::with_config(config.clone())?;
original.reserve(10)?;
original.add(42, &[1.0, 0.0, 0.0, 0.0])?;
let bytes = original.to_bytes()?;
// Deserialize with dimension validation
let restored = VectorIndex::from_bytes(&bytes, config)?;
assert!(restored.contains(42));Sourcepub fn from_bytes_unchecked(data: &[u8]) -> Result<Self>
pub fn from_bytes_unchecked(data: &[u8]) -> Result<Self>
Load an index from bytes without dimension validation.
This is a convenience method that creates a config with dimensions=0, allowing the dimensions to be read from the serialized data.
§Arguments
data- Serialized index data fromto_bytes()
§Examples
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::InnerProduct)?;
index.reserve(5)?;
index.add(1, &[1.0, 0.0, 0.0, 0.0])?;
let bytes = index.to_bytes()?;
// Restore without knowing the original dimensions
let restored = VectorIndex::from_bytes_unchecked(&bytes)?;
assert_eq!(restored.dimensions(), 4);Sourcepub fn hardware_acceleration(&self) -> String
pub fn hardware_acceleration(&self) -> String
Get hardware acceleration information.
Returns a string describing SIMD capabilities being used.
Sourcepub fn set_expansion_search(&self, expansion: usize)
pub fn set_expansion_search(&self, expansion: usize)
Change the expansion factor for search operations.
Higher values improve recall at the cost of search speed. Typical range: 10-200.
Sourcepub fn expansion_search(&self) -> usize
pub fn expansion_search(&self) -> usize
Get current expansion factor for search.
Sourcepub fn set_expansion_add(&self, expansion: usize)
pub fn set_expansion_add(&self, expansion: usize)
Change the expansion factor for add operations (index construction).
Higher values create a better-connected graph but increase insertion time. Typical range: 64-512, default is typically 128.
§Arguments
expansion- Expansion factor for vector addition
§Example
use go_brrr::embedding::{VectorIndex, Metric};
let index = VectorIndex::new(4, Metric::Cosine)?;
index.set_expansion_add(256); // Higher quality, slower insertSourcepub fn expansion_add(&self) -> usize
pub fn expansion_add(&self) -> usize
Get current expansion factor for add operations (index construction).
Higher values increase index quality but slow down insertion. The default is typically 128.
See also: [set_expansion_add], [expansion_search]
Trait Implementations§
Auto Trait Implementations§
impl Freeze for VectorIndex
impl !RefUnwindSafe for VectorIndex
impl Send for VectorIndex
impl Sync for VectorIndex
impl Unpin for VectorIndex
impl !UnwindSafe for VectorIndex
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request