zvec-rust
English | 中文
Safe, idiomatic Rust bindings for the zvec vector database.
Features
- RAII Resource Management — All C resources are automatically freed via
Drop - Builder Pattern — Fluent APIs for schema, query, and configuration
- Type Safety — Rust enums for all C constants with compile-time checks
- Comprehensive Error Handling — All FFI calls return
Result<T>with detailed error codes - Zero-Copy Where Possible — Minimizes data copying across the FFI boundary
- Prebuilt Libraries — Automatically downloads prebuilt
libzvec_c_apifrom GitHub Releases; advanced users can override withZVEC_LIB_DIR
Supported Platforms
| Platform | Architecture | CI Status | Notes |
|---|---|---|---|
| macOS | ARM64 (Apple Silicon) | ✅ Clippy + Test | Primary development platform |
| macOS | x86_64 (Intel) | ✅ Clippy + Test | |
| Linux | x86_64 | ✅ Clippy + Test + Fuzz + Coverage + Benchmark | Full CI coverage |
| Linux | ARM64 (AArch64) | ✅ Clippy + Test + Fuzz + Coverage | |
| Windows | x86_64 (MSVC) | ✅ Clippy + Test | CMake + MSVC toolchain |
The dynamic library name varies by platform:
libzvec_c_api.dylib(macOS),libzvec_c_api.so(Linux),zvec_c_api.dll(Windows).
Architecture
zvec-rust/
├── zvec-sys/ # Low-level FFI bindings to libzvec_c_api
├── zvec/ # Safe, high-level Rust wrapper
└── fuzz/ # Fuzz testing targets
zvec-rust-sys— Rawextern "C"declarations, opaque pointer types, and constantszvec-rust— Safe wrappers with RAII, builders, iterators, and idiomatic Rust APIs
Prerequisites
The Rust SDK depends on the zvec C library (libzvec_c_api). Choose one of the following ways to provide it:
Option 1: Bundled Prebuilt Library (Zero Setup)
Add zvec-rust to your Cargo.toml. The default bundled feature automatically downloads the prebuilt libzvec_c_api for your platform from GitHub Releases and sets up the library path via rpath:
[]
= "0.6.0"
Option 2: Custom Build
If you want to build the zvec C library yourself (e.g., for a custom configuration or unsupported platform), set the ZVEC_LIB_DIR environment variable:
# Build zvec from source
&&
&&
# Point zvec-rust to your custom build
Or use the built-in Makefile for local development:
Library Resolution Order
The build script resolves the C library in this order:
ZVEC_LIB_DIRenvironment variable (highest priority)- Sibling checkout:
../zvec/build/lib - Git submodule:
vendor/zvec/build/lib - Vendor directory:
vendor/lib/ - Prebuilt download: from GitHub Releases (automatic)
- Auto-build: clone and build from source (requires
git,cmake, C++17 compiler)
Set ZVEC_AUTO_BUILD=0 to disable steps 5 and 6.
Quick Start
use *;
Examples
Run any example with cargo run --example <name>:
| Example | Description |
|---|---|
basic |
End-to-end workflow: schema → insert → query → fetch → delete |
schema_builder |
Various schema configurations: field types, index types, quantization |
vector_search |
Vector query patterns: simple, builder, filter, output fields, HNSW params |
crud_operations |
Full CRUD: insert, fetch, update, upsert, delete, stats, flush |
config_logging |
Library configuration: memory limits, thread counts, logging |
# Using cargo directly (requires ZVEC_LIB_DIR / DYLD_LIBRARY_PATH)
API Overview
Initialization
| Function | Description |
|---|---|
initialize(config) |
Initialize the library (call once); pass None for defaults |
shutdown() |
Release all resources |
version() |
Get version string |
is_initialized() |
Check initialization status |
Use ConfigBuilder to customize memory limits, thread counts, and logging:
let config = new
.memory_limit
.num_threads
.enable_console_log
.build;
initialize?;
Schema Definition
let schema = builder
.add_field
.add_vector_field
.build?;
Collection Operations
| Method | Description |
|---|---|
Collection::create_and_open() |
Create a new collection |
Collection::open() |
Open an existing collection |
collection.insert(&docs) |
Insert documents |
collection.update(&docs) |
Update documents |
collection.upsert(&docs) |
Insert or update |
collection.delete(&pks) |
Delete by primary keys |
collection.delete_by_filter(filter) |
Delete documents matching a filter expression |
collection.query(&query) |
Vector similarity search |
collection.multi_query(&query) |
Multi-route search with RRF / weighted rerank |
collection.fetch(&pks) |
Fetch by primary keys |
collection.fetch_with_options(&pks, fields, include_vector) |
Fetch with output-field control |
collection.create_index(field, params) / drop_index(field) |
Runtime index management |
collection.optimize() |
Rebuild indexes / merge segments |
collection.stats() |
Get collection statistics |
collection.flush() |
Flush to disk |
Document Operations
let mut doc = new?;
doc.set_pk;
doc.add_string?;
doc.add_i64?;
doc.add_vector_f32?;
// Getters return `Result<Option<T>>` — `?` only unwraps the Result.
// Use `unwrap_or_default()` / `expect(..)` etc. to handle the Option.
let name: = doc.get_string?;
let count: = doc.get_i64?;
Vector Query
// Simple query
let query = new?;
// Builder pattern with filters
let query = builder
.field_name
.vector
.topk
.filter
.output_fields
.build?;
Multi-Query (Hybrid Search)
MultiQuery combines multiple sub-queries (dense vector, sparse vector, or FTS) with RRF or weighted reranking:
// FTS + vector hybrid search with RRF reranking
let mut sub_vec = new?;
sub_vec.set_field_name?;
sub_vec.set_query_vector?;
sub_vec.set_num_candidates?;
let mut fts = new?;
fts.set_match_string?;
let mut sub_fts = new?;
sub_fts.set_field_name?;
sub_fts.set_fts?;
sub_fts.set_num_candidates?;
let mut mq = new?;
mq.set_topk?;
mq.set_rerank_rrf?; // rank constant for RRF
mq.add_sub_query?;
mq.add_sub_query?;
let results = collection.multi_query?;
// Weighted reranking
mq.set_rerank_weighted?; // weights per sub-query
Supported Types
| Category | Types |
|---|---|
| Scalar | Bool, Int32, Int64, Uint32, Uint64, Float, Double, String, Binary |
| Vector | VectorFp16, VectorFp32, VectorFp64, VectorInt4, VectorInt8, VectorInt16, VectorBinary32, VectorBinary64 |
| Sparse | SparseVectorFp16, SparseVectorFp32 |
| Array | ArrayBool, ArrayInt32, ArrayInt64, ArrayUint32, ArrayUint64, ArrayFloat, ArrayDouble, ArrayString, ArrayBinary |
Index Types
Available distance metrics: L2, Ip, Cosine, MipsL2.
| Type | Constructor | Description |
|---|---|---|
| HNSW | IndexParams::hnsw(metric, m, ef) |
Graph index (recommended) |
| HNSW+Q | IndexParams::hnsw_with_quantize(...) |
HNSW with quantization |
| IVF | IndexParams::ivf(metric, nlist, niters, soar) |
Inverted file index |
| Flat | IndexParams::flat(metric) |
Brute-force index |
| DiskANN | IndexParams::diskann(metric, max_degree, list_size, pq_chunk_num) |
Disk-based graph index for large datasets (Linux x86_64 only) |
| Invert | IndexParams::invert(range, wildcard) |
Scalar field index |
| FTS | IndexParams::fts(tokenizer, filters, extra) |
Full-text search index |
Testing
# Using Makefile (recommended — auto-detects library paths)
# Using cargo directly (requires ZVEC_LIB_DIR / DYLD_LIBRARY_PATH)
# Fuzz tests (requires nightly)
# Benchmarks
# Code coverage
Keeping in Sync with zvec Core
This SDK tracks the zvec C-API. When the upstream C-API changes:
- Update
zvec-sys/src/lib.rswith new FFI declarations - Add safe wrappers in the
zveccrate - Update integration tests to cover new functionality
- Run the full test suite to verify compatibility
The CI pipeline automatically clones the latest zvec and builds the C library, ensuring FFI compatibility on every PR.
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Ensure all tests pass (
cargo test) - Ensure code is formatted (
cargo fmt --all -- --check) - Ensure clippy is clean (
cargo clippy --workspace --all-targets -- -D warnings) - Submit a pull request
License
Apache-2.0 — see LICENSE.