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