1use std::io;
4use std::mem::size_of;
5
6use serde::{Deserialize, Serialize};
7
8use crate::directories::{AsyncFileRead, LazyFileSlice, OwnedBytes};
9use crate::dsl::DenseVectorQuantization;
10use crate::segment::format::{DOC_ID_ENTRY_SIZE, FLAT_BINARY_HEADER_SIZE, FLAT_BINARY_MAGIC};
11use crate::structures::simd::{batch_f32_to_f16, batch_f32_to_u8, f16_to_f32, u8_to_f32};
12
13#[inline]
19pub fn dequantize_raw(
20 raw: &[u8],
21 quant: DenseVectorQuantization,
22 num_floats: usize,
23 out: &mut [f32],
24) {
25 debug_assert!(out.len() >= num_floats);
26 match quant {
27 DenseVectorQuantization::F32 => {
28 debug_assert!(
29 (raw.as_ptr() as usize).is_multiple_of(std::mem::align_of::<f32>()),
30 "f32 vector data not 4-byte aligned"
31 );
32 out[..num_floats].copy_from_slice(unsafe {
33 std::slice::from_raw_parts(raw.as_ptr() as *const f32, num_floats)
34 });
35 }
36 DenseVectorQuantization::F16 => {
37 debug_assert!(
38 (raw.as_ptr() as usize).is_multiple_of(std::mem::align_of::<u16>()),
39 "f16 vector data not 2-byte aligned"
40 );
41 let f16_slice =
42 unsafe { std::slice::from_raw_parts(raw.as_ptr() as *const u16, num_floats) };
43 for (i, &h) in f16_slice.iter().enumerate() {
44 out[i] = f16_to_f32(h);
45 }
46 }
47 DenseVectorQuantization::UInt8 => {
48 for (i, &b) in raw.iter().enumerate().take(num_floats) {
49 out[i] = u8_to_f32(b);
50 }
51 }
52 }
53}
54
55pub struct FlatVectorData;
68
69impl FlatVectorData {
70 pub fn write_binary_header(
72 dim: usize,
73 num_vectors: usize,
74 quant: DenseVectorQuantization,
75 writer: &mut dyn std::io::Write,
76 ) -> std::io::Result<()> {
77 writer.write_all(&FLAT_BINARY_MAGIC.to_le_bytes())?;
78 writer.write_all(&(dim as u32).to_le_bytes())?;
79 writer.write_all(&(num_vectors as u32).to_le_bytes())?;
80 writer.write_all(&[quant.tag(), 0, 0, 0])?; Ok(())
82 }
83
84 pub fn serialized_binary_size(
86 dim: usize,
87 num_vectors: usize,
88 quant: DenseVectorQuantization,
89 ) -> usize {
90 FLAT_BINARY_HEADER_SIZE
91 + num_vectors * dim * quant.element_size()
92 + num_vectors * DOC_ID_ENTRY_SIZE
93 }
94
95 pub fn serialize_binary_from_flat_streaming(
100 dim: usize,
101 flat_vectors: &[f32],
102 doc_ids: &[(u32, u16)],
103 quant: DenseVectorQuantization,
104 writer: &mut dyn std::io::Write,
105 ) -> std::io::Result<()> {
106 let num_vectors = doc_ids.len();
107 Self::write_binary_header(dim, num_vectors, quant, writer)?;
108
109 match quant {
110 DenseVectorQuantization::F32 => {
111 let bytes: &[u8] = unsafe {
112 std::slice::from_raw_parts(
113 flat_vectors.as_ptr() as *const u8,
114 std::mem::size_of_val(flat_vectors),
115 )
116 };
117 writer.write_all(bytes)?;
118 }
119 DenseVectorQuantization::F16 => {
120 let mut buf = vec![0u16; dim];
121 for v in flat_vectors.chunks_exact(dim) {
122 batch_f32_to_f16(v, &mut buf);
123 let bytes: &[u8] =
124 unsafe { std::slice::from_raw_parts(buf.as_ptr() as *const u8, dim * 2) };
125 writer.write_all(bytes)?;
126 }
127 }
128 DenseVectorQuantization::UInt8 => {
129 let mut buf = vec![0u8; dim];
130 for v in flat_vectors.chunks_exact(dim) {
131 batch_f32_to_u8(v, &mut buf);
132 writer.write_all(&buf)?;
133 }
134 }
135 }
136
137 for &(doc_id, ordinal) in doc_ids {
138 writer.write_all(&doc_id.to_le_bytes())?;
139 writer.write_all(&ordinal.to_le_bytes())?;
140 }
141
142 Ok(())
143 }
144
145 pub fn write_raw_vector_bytes(
149 raw_bytes: &[u8],
150 writer: &mut dyn std::io::Write,
151 ) -> std::io::Result<()> {
152 writer.write_all(raw_bytes)
153 }
154}
155
156#[derive(Debug, Clone)]
168pub struct LazyFlatVectorData {
169 pub dim: usize,
171 pub num_vectors: usize,
173 pub quantization: DenseVectorQuantization,
175 doc_ids_bytes: OwnedBytes,
177 handle: LazyFileSlice,
179 vectors_offset: u64,
181 element_size: usize,
183}
184
185impl LazyFlatVectorData {
186 pub async fn open(handle: LazyFileSlice) -> io::Result<Self> {
191 let header = handle
193 .read_bytes_range(0..FLAT_BINARY_HEADER_SIZE as u64)
194 .await?;
195 let hdr = header.as_slice();
196
197 let magic = u32::from_le_bytes([hdr[0], hdr[1], hdr[2], hdr[3]]);
198 if magic != FLAT_BINARY_MAGIC {
199 return Err(io::Error::new(
200 io::ErrorKind::InvalidData,
201 "Invalid FlatVectorData binary magic",
202 ));
203 }
204
205 let dim = u32::from_le_bytes([hdr[4], hdr[5], hdr[6], hdr[7]]) as usize;
206 let num_vectors = u32::from_le_bytes([hdr[8], hdr[9], hdr[10], hdr[11]]) as usize;
207 let quantization = DenseVectorQuantization::from_tag(hdr[12]).ok_or_else(|| {
208 io::Error::new(
209 io::ErrorKind::InvalidData,
210 format!("Unknown quantization tag: {}", hdr[12]),
211 )
212 })?;
213 let element_size = quantization.element_size();
214
215 let vectors_byte_len = num_vectors * dim * element_size;
217 let doc_ids_start = (FLAT_BINARY_HEADER_SIZE + vectors_byte_len) as u64;
218 let doc_ids_byte_len = (num_vectors * DOC_ID_ENTRY_SIZE) as u64;
219
220 let doc_ids_bytes = handle
221 .read_bytes_range(doc_ids_start..doc_ids_start + doc_ids_byte_len)
222 .await?;
223
224 Ok(Self {
225 dim,
226 num_vectors,
227 quantization,
228 doc_ids_bytes,
229 handle,
230 vectors_offset: FLAT_BINARY_HEADER_SIZE as u64,
231 element_size,
232 })
233 }
234
235 pub async fn read_vector_into(&self, idx: usize, out: &mut [f32]) -> io::Result<()> {
240 debug_assert!(out.len() >= self.dim);
241 let vec_byte_len = self.dim * self.element_size;
242 let byte_offset = self.vectors_offset + (idx * vec_byte_len) as u64;
243 let bytes = self
244 .handle
245 .read_bytes_range(byte_offset..byte_offset + vec_byte_len as u64)
246 .await?;
247 let raw = bytes.as_slice();
248
249 dequantize_raw(raw, self.quantization, self.dim, out);
250 Ok(())
251 }
252
253 pub async fn get_vector(&self, idx: usize) -> io::Result<Vec<f32>> {
255 let mut vector = vec![0f32; self.dim];
256 self.read_vector_into(idx, &mut vector).await?;
257 Ok(vector)
258 }
259
260 pub async fn read_vector_raw_into(&self, idx: usize, out: &mut [u8]) -> io::Result<()> {
265 let vbs = self.vector_byte_size();
266 debug_assert!(out.len() >= vbs);
267 let byte_offset = self.vectors_offset + (idx * vbs) as u64;
268 let bytes = self
269 .handle
270 .read_bytes_range(byte_offset..byte_offset + vbs as u64)
271 .await?;
272 out[..vbs].copy_from_slice(bytes.as_slice());
273 Ok(())
274 }
275
276 pub async fn read_vectors_batch(
282 &self,
283 start_idx: usize,
284 count: usize,
285 ) -> io::Result<OwnedBytes> {
286 debug_assert!(start_idx + count <= self.num_vectors);
287 let vec_byte_len = self.dim * self.element_size;
288 let byte_offset = self.vectors_offset + (start_idx * vec_byte_len) as u64;
289 let byte_len = (count * vec_byte_len) as u64;
290 self.handle
291 .read_bytes_range(byte_offset..byte_offset + byte_len)
292 .await
293 }
294
295 pub fn flat_indexes_for_doc_range(&self, doc_id: u32) -> (usize, usize) {
301 let n = self.num_vectors;
302 let start = {
303 let mut lo = 0usize;
304 let mut hi = n;
305 while lo < hi {
306 let mid = lo + (hi - lo) / 2;
307 if self.doc_id_at(mid) < doc_id {
308 lo = mid + 1;
309 } else {
310 hi = mid;
311 }
312 }
313 lo
314 };
315 let mut count = 0;
316 let mut i = start;
317 while i < n && self.doc_id_at(i) == doc_id {
318 count += 1;
319 i += 1;
320 }
321 (start, count)
322 }
323
324 pub fn flat_indexes_for_doc(&self, doc_id: u32) -> (usize, Vec<(u32, u16)>) {
331 let n = self.num_vectors;
332 let start = {
334 let mut lo = 0usize;
335 let mut hi = n;
336 while lo < hi {
337 let mid = lo + (hi - lo) / 2;
338 if self.doc_id_at(mid) < doc_id {
339 lo = mid + 1;
340 } else {
341 hi = mid;
342 }
343 }
344 lo
345 };
346 let mut entries = Vec::new();
348 let mut i = start;
349 while i < n {
350 let (did, ord) = self.get_doc_id(i);
351 if did != doc_id {
352 break;
353 }
354 entries.push((did, ord));
355 i += 1;
356 }
357 (start, entries)
358 }
359
360 #[inline]
362 fn doc_id_at(&self, idx: usize) -> u32 {
363 let off = idx * DOC_ID_ENTRY_SIZE;
364 let d = &self.doc_ids_bytes[off..];
365 u32::from_le_bytes([d[0], d[1], d[2], d[3]])
366 }
367
368 #[inline]
370 pub fn get_doc_id(&self, idx: usize) -> (u32, u16) {
371 let off = idx * DOC_ID_ENTRY_SIZE;
372 let d = &self.doc_ids_bytes[off..];
373 let doc_id = u32::from_le_bytes([d[0], d[1], d[2], d[3]]);
374 let ordinal = u16::from_le_bytes([d[4], d[5]]);
375 (doc_id, ordinal)
376 }
377
378 #[inline]
380 pub fn vector_byte_size(&self) -> usize {
381 self.dim * self.element_size
382 }
383
384 pub fn vector_bytes_len(&self) -> u64 {
386 (self.num_vectors as u64) * (self.vector_byte_size() as u64)
387 }
388
389 pub fn vectors_byte_offset(&self) -> u64 {
391 self.vectors_offset
392 }
393
394 pub fn handle(&self) -> &LazyFileSlice {
396 &self.handle
397 }
398
399 pub fn estimated_memory_bytes(&self) -> usize {
401 size_of::<Self>() + size_of::<OwnedBytes>()
402 }
403}
404
405#[derive(Debug, Clone, Serialize, Deserialize)]
410pub struct IVFRaBitQIndexData {
411 pub index: crate::structures::IVFRaBitQIndex,
412 pub codebook: crate::structures::RaBitQCodebook,
413}
414
415impl IVFRaBitQIndexData {
416 pub fn to_bytes(&self) -> std::io::Result<Vec<u8>> {
417 bincode::serde::encode_to_vec(self, bincode::config::standard())
418 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
419 }
420
421 pub fn from_bytes(data: &[u8]) -> std::io::Result<Self> {
422 bincode::serde::decode_from_slice(data, bincode::config::standard())
423 .map(|(v, _)| v)
424 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
425 }
426}
427
428#[derive(Debug, Clone, Serialize, Deserialize)]
433pub struct ScaNNIndexData {
434 pub index: crate::structures::IVFPQIndex,
435 pub codebook: crate::structures::PQCodebook,
436}
437
438impl ScaNNIndexData {
439 pub fn to_bytes(&self) -> std::io::Result<Vec<u8>> {
440 bincode::serde::encode_to_vec(self, bincode::config::standard())
441 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
442 }
443
444 pub fn from_bytes(data: &[u8]) -> std::io::Result<Self> {
445 bincode::serde::decode_from_slice(data, bincode::config::standard())
446 .map(|(v, _)| v)
447 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
448 }
449}