feather_db_cli/
lib.rs

1use std::ffi::{c_void, c_char};
2use std::path::Path;
3
4#[repr(C)]
5pub struct DB(*mut c_void);  // ← `pub`
6
7extern "C" {
8    fn feather_open(path: *const c_char, dim: usize) -> *mut c_void;
9    fn feather_add(db: *mut c_void, id: u64, vec: *const f32, len: usize);
10    fn feather_search(db: *mut c_void, query: *const f32, len: usize, k: usize,
11                      out_ids: *mut u64, out_dists: *mut f32);
12    fn feather_save(db: *mut c_void);
13    fn feather_close(db: *mut c_void);
14}
15
16impl DB {
17    pub fn open(path: &Path, dim: usize) -> Option<Self> {
18        let c_path = std::ffi::CString::new(path.to_str()?).ok()?;
19        let ptr = unsafe { feather_open(c_path.as_ptr(), dim) };
20        if ptr.is_null() { None } else { Some(DB(ptr)) }
21    }
22
23    pub fn add(&self, id: u64, vec: &[f32]) {
24        unsafe { feather_add(self.0, id, vec.as_ptr(), vec.len()) }
25    }
26
27    pub fn search(&self, query: &[f32], k: usize) -> (Vec<u64>, Vec<f32>) {
28        let mut ids = vec![0u64; k];
29        let mut dists = vec![0f32; k];
30        unsafe {
31            feather_search(self.0, query.as_ptr(), query.len(), k, ids.as_mut_ptr(), dists.as_mut_ptr())
32        };
33        (ids, dists)
34    }
35
36    pub fn save(&self) { unsafe { feather_save(self.0) } }
37}
38
39impl Drop for DB {
40    fn drop(&mut self) { unsafe { feather_close(self.0) } }
41}