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(&self, doc_id: u32) -> (usize, Vec<(u32, u16)>) {
302 let n = self.num_vectors;
303 let start = {
305 let mut lo = 0usize;
306 let mut hi = n;
307 while lo < hi {
308 let mid = lo + (hi - lo) / 2;
309 if self.doc_id_at(mid) < doc_id {
310 lo = mid + 1;
311 } else {
312 hi = mid;
313 }
314 }
315 lo
316 };
317 let mut entries = Vec::new();
319 let mut i = start;
320 while i < n {
321 let (did, ord) = self.get_doc_id(i);
322 if did != doc_id {
323 break;
324 }
325 entries.push((did, ord));
326 i += 1;
327 }
328 (start, entries)
329 }
330
331 #[inline]
333 fn doc_id_at(&self, idx: usize) -> u32 {
334 let off = idx * DOC_ID_ENTRY_SIZE;
335 let d = &self.doc_ids_bytes[off..];
336 u32::from_le_bytes([d[0], d[1], d[2], d[3]])
337 }
338
339 #[inline]
341 pub fn get_doc_id(&self, idx: usize) -> (u32, u16) {
342 let off = idx * DOC_ID_ENTRY_SIZE;
343 let d = &self.doc_ids_bytes[off..];
344 let doc_id = u32::from_le_bytes([d[0], d[1], d[2], d[3]]);
345 let ordinal = u16::from_le_bytes([d[4], d[5]]);
346 (doc_id, ordinal)
347 }
348
349 #[inline]
351 pub fn vector_byte_size(&self) -> usize {
352 self.dim * self.element_size
353 }
354
355 pub fn vector_bytes_len(&self) -> u64 {
357 (self.num_vectors as u64) * (self.vector_byte_size() as u64)
358 }
359
360 pub fn vectors_byte_offset(&self) -> u64 {
362 self.vectors_offset
363 }
364
365 pub fn handle(&self) -> &LazyFileSlice {
367 &self.handle
368 }
369
370 pub fn estimated_memory_bytes(&self) -> usize {
372 size_of::<Self>() + size_of::<OwnedBytes>()
373 }
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize)]
381pub struct IVFRaBitQIndexData {
382 pub index: crate::structures::IVFRaBitQIndex,
383 pub codebook: crate::structures::RaBitQCodebook,
384}
385
386impl IVFRaBitQIndexData {
387 pub fn to_bytes(&self) -> std::io::Result<Vec<u8>> {
388 bincode::serde::encode_to_vec(self, bincode::config::standard())
389 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
390 }
391
392 pub fn from_bytes(data: &[u8]) -> std::io::Result<Self> {
393 bincode::serde::decode_from_slice(data, bincode::config::standard())
394 .map(|(v, _)| v)
395 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
396 }
397}
398
399#[derive(Debug, Clone, Serialize, Deserialize)]
404pub struct ScaNNIndexData {
405 pub index: crate::structures::IVFPQIndex,
406 pub codebook: crate::structures::PQCodebook,
407}
408
409impl ScaNNIndexData {
410 pub fn to_bytes(&self) -> std::io::Result<Vec<u8>> {
411 bincode::serde::encode_to_vec(self, bincode::config::standard())
412 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
413 }
414
415 pub fn from_bytes(data: &[u8]) -> std::io::Result<Self> {
416 bincode::serde::decode_from_slice(data, bincode::config::standard())
417 .map(|(v, _)| v)
418 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
419 }
420}