1use std::ffi::CString;
2use std::ptr;
3
4use faiss_next_sys;
5
6use crate::error::{check_return_code, Result};
7use crate::index::{Index, IndexImpl};
8use crate::metric::MetricType;
9
10pub fn index_factory(d: u32, description: &str, metric: MetricType) -> Result<IndexImpl> {
11 let c_description = CString::new(description)?;
12 let mut inner = ptr::null_mut();
13
14 unsafe {
15 check_return_code(faiss_next_sys::faiss_index_factory(
16 &mut inner,
17 d as i32,
18 c_description.as_ptr(),
19 metric.as_native(),
20 ))?;
21
22 IndexImpl::from_raw(inner)
23 }
24}
25
26pub struct IndexBuilder {
27 d: u32,
28 description: String,
29 metric: MetricType,
30 nprobe: Option<usize>,
31 verbose: bool,
32}
33
34impl IndexBuilder {
35 pub fn new(d: u32) -> Self {
36 Self {
37 d,
38 description: "Flat".to_string(),
39 metric: MetricType::L2,
40 nprobe: None,
41 verbose: false,
42 }
43 }
44
45 pub fn description(mut self, desc: impl Into<String>) -> Self {
46 self.description = desc.into();
47 self
48 }
49
50 pub fn flat(self) -> Self {
51 self.description("Flat")
52 }
53
54 pub fn ivf_flat(self, nlist: usize) -> Self {
55 self.description(format!("IVF{},Flat", nlist))
56 }
57
58 pub fn ivf_pq(self, nlist: usize, m: usize, nbits: usize) -> Self {
59 self.description(format!("IVF{},PQ{}x{}", nlist, m, nbits))
60 }
61
62 pub fn pq(self, m: usize, nbits: usize) -> Self {
63 self.description(format!("PQ{}x{}", m, nbits))
64 }
65
66 pub fn hnsw(self, m: usize) -> Self {
67 self.description(format!("HNSW{}", m))
68 }
69
70 pub fn lsh(self, nbits: usize) -> Self {
71 self.description(format!("LSH{}", nbits))
72 }
73
74 pub fn metric(mut self, metric: MetricType) -> Self {
75 self.metric = metric;
76 self
77 }
78
79 pub fn l2(self) -> Self {
80 self.metric(MetricType::L2)
81 }
82
83 pub fn ip(self) -> Self {
84 self.metric(MetricType::InnerProduct)
85 }
86
87 pub fn nprobe(mut self, nprobe: usize) -> Self {
88 self.nprobe = Some(nprobe);
89 self
90 }
91
92 pub fn verbose(mut self, verbose: bool) -> Self {
93 self.verbose = verbose;
94 self
95 }
96
97 pub fn build(self) -> Result<IndexImpl> {
98 let mut index = index_factory(self.d, &self.description, self.metric)?;
99
100 if self.verbose {
101 index.set_verbose(true);
102 }
103
104 Ok(index)
105 }
106}