Write a v2 NDVS segment file to `path`. `surrogate_ids[i]` is the u64 surrogate for `vectors[i]`. The slice may be empty, in which case all surrogate IDs are written as 0. # Errors Returns `std::io::Error` on any I/O failure or arithmetic overflow.
(
path: &Path,
dim: usize,
vectors: &[&[f32]],
surrogate_ids: &[u64],
)
| 17 | /// |
| 18 | /// Returns `std::io::Error` on any I/O failure or arithmetic overflow. |
| 19 | pub fn write_segment( |
| 20 | path: &Path, |
| 21 | dim: usize, |
| 22 | vectors: &[&[f32]], |
| 23 | surrogate_ids: &[u64], |
| 24 | ) -> std::io::Result<()> { |
| 25 | use std::io::Write as _; |
| 26 | |
| 27 | debug_assert!( |
| 28 | surrogate_ids.is_empty() || surrogate_ids.len() == vectors.len(), |
| 29 | "surrogate_ids length must match vectors length or be empty" |
| 30 | ); |
| 31 | |
| 32 | if let Some(parent) = path.parent() { |
| 33 | std::fs::create_dir_all(parent)?; |
| 34 | } |
| 35 | |
| 36 | let count = vectors.len() as u64; |
| 37 | |
| 38 | let mut fd = std::fs::OpenOptions::new() |
| 39 | .read(true) |
| 40 | .write(true) |
| 41 | .create(true) |
| 42 | .truncate(true) |
| 43 | .open(path)?; |
| 44 | |
| 45 | // Header — 32 bytes. |
| 46 | fd.write_all(&MAGIC)?; |
| 47 | fd.write_all(&FORMAT_VERSION.to_le_bytes())?; |
| 48 | fd.write_all(&0u16.to_le_bytes())?; // flags |
| 49 | fd.write_all(&(dim as u32).to_le_bytes())?; |
| 50 | fd.write_all(&count.to_le_bytes())?; |
| 51 | fd.write_all(&[DTYPE_F32])?; |
| 52 | fd.write_all(&[VectorSegmentCodec::None as u8])?; |
| 53 | fd.write_all(&[0u8; 10])?; // reserved (10 bytes → header total 32, 8-byte aligned) |
| 54 | |
| 55 | // Vector data block — D × N × 4 bytes, row-major, no framing. |
| 56 | let mut written_vec_bytes: usize = 0; |
| 57 | for v in vectors { |
| 58 | debug_assert_eq!(v.len(), dim, "vector dimension mismatch during write"); |
| 59 | let bytes: &[u8] = |
| 60 | unsafe { std::slice::from_raw_parts(v.as_ptr() as *const u8, v.len() * 4) }; |
| 61 | fd.write_all(bytes)?; |
| 62 | written_vec_bytes += bytes.len(); |
| 63 | } |
| 64 | |
| 65 | // Pad to 8-byte alignment so the surrogate ID block is naturally aligned. |
| 66 | let pad = vec_pad(written_vec_bytes); |
| 67 | if pad > 0 { |
| 68 | fd.write_all(&[0u8; 8][..pad])?; |
| 69 | } |
| 70 | |
| 71 | // Surrogate ID block — N × 8 bytes. |
| 72 | for i in 0..vectors.len() { |
| 73 | let sid: u64 = surrogate_ids.get(i).copied().unwrap_or(0); |
| 74 | fd.write_all(&sid.to_le_bytes())?; |
| 75 | } |
| 76 |