Skip to main content

velesdb_core/
vector_ref.rs

1//! Zero-copy vector reference abstraction.
2//!
3//! This module provides the `VectorRef` trait for zero-copy access to vectors,
4//! eliminating heap allocations during search operations.
5//!
6//! # Performance
7//!
8//! Using `VectorRef` instead of `Vec<f32>` eliminates:
9//! - **Heap allocations**: 0 allocations per read vs ~10k for 10k vector search
10//! - **Memory copies**: Direct slice access from mmap
11//! - **Allocator pressure**: No fragmentation from repeated alloc/dealloc
12//!
13//! # EPIC-B: TS-MEM-001, TS-MEM-002
14
15use std::borrow::Cow;
16use std::ops::Deref;
17
18/// A reference to vector data that may be borrowed or owned.
19///
20/// This trait abstracts over different ways to access vector data:
21/// - `&[f32]`: Direct slice reference (zero-copy from mmap)
22/// - `Cow<[f32]>`: Copy-on-write for flexibility
23/// - [`Vec<f32>`]: Owned data when needed
24///
25/// # Example
26///
27/// ```rust,no_run
28/// use velesdb_core::vector_ref::VectorRef;
29///
30/// fn compute_distance<V: VectorRef>(a: &V, b: &V) -> f32 {
31///     let a_slice = a.as_slice();
32///     let b_slice = b.as_slice();
33///     // SIMD distance calculation on slices
34///     0.0 // placeholder
35/// }
36/// ```
37pub trait VectorRef {
38    /// Returns the vector data as a slice.
39    fn as_slice(&self) -> &[f32];
40
41    /// Returns the dimension of the vector.
42    fn dimension(&self) -> usize {
43        self.as_slice().len()
44    }
45
46    /// Returns true if the vector is empty.
47    fn is_empty(&self) -> bool {
48        self.as_slice().is_empty()
49    }
50}
51
52// ============================================================================
53// Implementations for common types
54// ============================================================================
55
56impl VectorRef for [f32] {
57    #[inline]
58    fn as_slice(&self) -> &[f32] {
59        self
60    }
61}
62
63impl VectorRef for Vec<f32> {
64    #[inline]
65    fn as_slice(&self) -> &[f32] {
66        self
67    }
68}
69
70impl VectorRef for &[f32] {
71    #[inline]
72    fn as_slice(&self) -> &[f32] {
73        self
74    }
75}
76
77impl VectorRef for Cow<'_, [f32]> {
78    #[inline]
79    fn as_slice(&self) -> &[f32] {
80        self
81    }
82}
83
84/// A borrowed vector reference with explicit lifetime.
85///
86/// This is useful when you need to return a reference from a function
87/// while keeping the source locked.
88#[derive(Debug, Clone, Copy)]
89pub struct BorrowedVector<'a> {
90    data: &'a [f32],
91}
92
93impl<'a> BorrowedVector<'a> {
94    /// Creates a new borrowed vector reference.
95    #[inline]
96    #[must_use]
97    pub const fn new(data: &'a [f32]) -> Self {
98        Self { data }
99    }
100
101    /// Returns the underlying slice.
102    #[inline]
103    #[must_use]
104    pub const fn data(&self) -> &'a [f32] {
105        self.data
106    }
107}
108
109impl VectorRef for BorrowedVector<'_> {
110    #[inline]
111    fn as_slice(&self) -> &[f32] {
112        self.data
113    }
114}
115
116impl Deref for BorrowedVector<'_> {
117    type Target = [f32];
118
119    #[inline]
120    fn deref(&self) -> &Self::Target {
121        self.data
122    }
123}
124
125impl AsRef<[f32]> for BorrowedVector<'_> {
126    #[inline]
127    fn as_ref(&self) -> &[f32] {
128        self.data
129    }
130}
131
132/// Guard that holds a read lock and provides vector access.
133///
134/// This is used for zero-copy access from storage while holding the lock.
135/// The guard ensures the underlying data remains valid.
136pub struct VectorGuard<'a, G> {
137    /// The lock guard (kept alive to hold the lock)
138    _guard: G,
139    /// Pointer to the vector data
140    data: &'a [f32],
141}
142
143impl<'a, G> VectorGuard<'a, G> {
144    /// Creates a new vector guard.
145    ///
146    /// # Safety
147    ///
148    /// The `data` pointer must remain valid as long as `guard` is held.
149    /// This is enforced by the lifetime parameter.
150    #[must_use]
151    pub const fn new(guard: G, data: &'a [f32]) -> Self {
152        Self {
153            _guard: guard,
154            data,
155        }
156    }
157}
158
159impl<G> VectorRef for VectorGuard<'_, G> {
160    #[inline]
161    fn as_slice(&self) -> &[f32] {
162        self.data
163    }
164}
165
166impl<G> Deref for VectorGuard<'_, G> {
167    type Target = [f32];
168
169    #[inline]
170    fn deref(&self) -> &Self::Target {
171        self.data
172    }
173}
174
175impl<G> AsRef<[f32]> for VectorGuard<'_, G> {
176    #[inline]
177    fn as_ref(&self) -> &[f32] {
178        self.data
179    }
180}
181
182// ============================================================================
183// Tests moved to vector_ref_tests.rs per project rules