1use std::ffi::CStr;
2
3use crate::error::{check_error, Error, ErrorCode, Result};
4use crate::types::LogLevel;
5
6pub struct ConfigBuilder {
22 pub memory_limit: u64,
24 pub num_threads: u32,
26 pub enable_console_log: bool,
28 pub fts_brute_force_by_keys_ratio: Option<f32>,
30}
31
32impl ConfigBuilder {
33 pub fn new() -> Self {
35 ConfigBuilder {
36 memory_limit: 0,
37 num_threads: 0,
38 enable_console_log: false,
39 fts_brute_force_by_keys_ratio: None,
40 }
41 }
42
43 pub fn memory_limit(mut self, bytes: u64) -> Self {
45 self.memory_limit = bytes;
46 self
47 }
48
49 pub fn num_threads(mut self, count: u32) -> Self {
51 self.num_threads = count;
52 self
53 }
54
55 pub fn enable_console_log(mut self, enable: bool) -> Self {
57 self.enable_console_log = enable;
58 self
59 }
60
61 pub fn fts_brute_force_by_keys_ratio(mut self, ratio: f32) -> Self {
63 self.fts_brute_force_by_keys_ratio = Some(ratio);
64 self
65 }
66
67 pub fn build(self) -> Self {
73 self
74 }
75}
76
77impl Default for ConfigBuilder {
78 fn default() -> Self {
79 Self::new()
80 }
81}
82
83pub(crate) struct ConfigData {
85 pub(crate) handle: *mut zvec_rust_sys::zvec_config_data_t,
86}
87
88impl ConfigData {
89 pub(crate) fn new() -> Result<Self> {
90 let handle = unsafe { zvec_rust_sys::zvec_config_data_create() };
91 if handle.is_null() {
92 return Err(Error {
93 code: ErrorCode::InternalError,
94 message: "failed to create config data".into(),
95 });
96 }
97 Ok(ConfigData { handle })
98 }
99
100 pub(crate) fn set_memory_limit(&mut self, bytes: u64) -> Result<()> {
101 check_error(unsafe { zvec_rust_sys::zvec_config_data_set_memory_limit(self.handle, bytes) })
102 }
103
104 pub(crate) fn set_query_thread_count(&mut self, count: u32) -> Result<()> {
105 check_error(unsafe {
106 zvec_rust_sys::zvec_config_data_set_query_thread_count(self.handle, count)
107 })
108 }
109
110 pub(crate) fn set_optimize_thread_count(&mut self, count: u32) -> Result<()> {
111 check_error(unsafe {
112 zvec_rust_sys::zvec_config_data_set_optimize_thread_count(self.handle, count)
113 })
114 }
115
116 pub(crate) fn set_fts_brute_force_by_keys_ratio(&mut self, ratio: f32) -> Result<()> {
117 check_error(unsafe {
118 zvec_rust_sys::zvec_config_data_set_fts_brute_force_by_keys_ratio(self.handle, ratio)
119 })
120 }
121
122 pub(crate) fn set_console_log(&mut self, level: LogLevel) -> Result<()> {
123 let log_config = unsafe { zvec_rust_sys::zvec_config_log_create_console(level as u32) };
124 if log_config.is_null() {
125 return Err(Error {
126 code: ErrorCode::InternalError,
127 message: "failed to create console log config".into(),
128 });
129 }
130 let result = check_error(unsafe {
133 zvec_rust_sys::zvec_config_data_set_log_config(self.handle, log_config)
134 });
135 if result.is_err() {
136 unsafe { zvec_rust_sys::zvec_config_log_destroy(log_config) };
137 }
138 result
139 }
140}
141
142impl Drop for ConfigData {
143 fn drop(&mut self) {
144 if !self.handle.is_null() {
145 unsafe { zvec_rust_sys::zvec_config_data_destroy(self.handle) };
147 }
148 }
149}
150
151pub fn initialize(config: Option<&ConfigBuilder>) -> Result<()> {
173 match config {
174 None => check_error(unsafe { zvec_rust_sys::zvec_initialize(std::ptr::null()) }),
175 Some(builder) => {
176 let mut cfg = ConfigData::new()?;
177 if builder.memory_limit > 0 {
178 cfg.set_memory_limit(builder.memory_limit)?;
179 }
180 if builder.num_threads > 0 {
181 cfg.set_query_thread_count(builder.num_threads)?;
182 cfg.set_optimize_thread_count(builder.num_threads)?;
183 }
184 if builder.enable_console_log {
185 cfg.set_console_log(LogLevel::Info)?;
186 }
187 if let Some(ratio) = builder.fts_brute_force_by_keys_ratio {
188 cfg.set_fts_brute_force_by_keys_ratio(ratio)?;
189 }
190 check_error(unsafe { zvec_rust_sys::zvec_initialize(cfg.handle as *const _) })
191 }
192 }
193}
194
195#[doc(hidden)]
197pub fn shutdown() -> Result<()> {
198 check_error(unsafe { zvec_rust_sys::zvec_shutdown() })
199}
200
201pub fn is_initialized() -> bool {
203 unsafe { zvec_rust_sys::zvec_is_initialized() }
204}
205
206pub fn version() -> String {
208 unsafe {
209 let ptr = zvec_rust_sys::zvec_get_version();
210 if ptr.is_null() {
211 return String::new();
212 }
213 CStr::from_ptr(ptr).to_string_lossy().into_owned()
214 }
215}
216
217pub fn check_version(major: i32, minor: i32, patch: i32) -> bool {
219 unsafe { zvec_rust_sys::zvec_check_version(major, minor, patch) }
220}
221
222pub fn version_major() -> i32 {
224 unsafe { zvec_rust_sys::zvec_get_version_major() }
225}
226
227pub fn version_minor() -> i32 {
229 unsafe { zvec_rust_sys::zvec_get_version_minor() }
230}
231
232pub fn version_patch() -> i32 {
234 unsafe { zvec_rust_sys::zvec_get_version_patch() }
235}
236
237#[cfg(test)]
238mod tests {
239 use super::*;
240
241 #[test]
242 fn config_builder_defaults() {
243 let builder = ConfigBuilder::new();
244 assert_eq!(builder.memory_limit, 0);
245 assert_eq!(builder.num_threads, 0);
246 assert!(!builder.enable_console_log);
247 }
248
249 #[test]
250 fn config_builder_chaining() {
251 let builder = ConfigBuilder::new()
252 .memory_limit(1024)
253 .num_threads(4)
254 .enable_console_log(true)
255 .build();
256 assert_eq!(builder.memory_limit, 1024);
257 assert_eq!(builder.num_threads, 4);
258 assert!(builder.enable_console_log);
259 }
260
261 #[test]
262 fn config_builder_default_trait() {
263 let builder = ConfigBuilder::default();
264 assert_eq!(builder.memory_limit, 0);
265 assert_eq!(builder.num_threads, 0);
266 assert!(!builder.enable_console_log);
267 }
268
269 #[test]
270 fn config_builder_memory_limit_setter() {
271 let builder = ConfigBuilder::new().memory_limit(2048);
272 assert_eq!(builder.memory_limit, 2048);
273 }
274
275 #[test]
276 fn config_builder_num_threads_setter() {
277 let builder = ConfigBuilder::new().num_threads(8);
278 assert_eq!(builder.num_threads, 8);
279 }
280
281 #[test]
282 fn config_builder_enable_console_log_setter() {
283 let builder = ConfigBuilder::new().enable_console_log(true);
284 assert!(builder.enable_console_log);
285 }
286
287 #[test]
288 fn config_builder_build_returns_self() {
289 let builder = ConfigBuilder::new()
290 .memory_limit(4096)
291 .num_threads(2)
292 .enable_console_log(true)
293 .build();
294 assert_eq!(builder.memory_limit, 4096);
295 assert_eq!(builder.num_threads, 2);
296 assert!(builder.enable_console_log);
297 }
298
299 #[test]
300 fn config_builder_overwrite_values() {
301 let builder = ConfigBuilder::new()
302 .memory_limit(1024)
303 .memory_limit(2048)
304 .num_threads(4)
305 .num_threads(8)
306 .enable_console_log(false)
307 .enable_console_log(true);
308 assert_eq!(builder.memory_limit, 2048);
309 assert_eq!(builder.num_threads, 8);
310 assert!(builder.enable_console_log);
311 }
312
313 #[test]
314 fn config_builder_zero_values() {
315 let builder = ConfigBuilder::new().memory_limit(0).num_threads(0);
316 assert_eq!(builder.memory_limit, 0);
317 assert_eq!(builder.num_threads, 0);
318 }
319
320 #[test]
321 fn config_builder_large_memory_limit() {
322 let builder = ConfigBuilder::new().memory_limit(u64::MAX);
323 assert_eq!(builder.memory_limit, u64::MAX);
324 }
325
326 #[test]
327 fn config_builder_fts_ratio() {
328 let builder = ConfigBuilder::new();
329 assert_eq!(builder.fts_brute_force_by_keys_ratio, None);
330
331 let builder = ConfigBuilder::new().fts_brute_force_by_keys_ratio(0.5);
332 assert_eq!(builder.fts_brute_force_by_keys_ratio, Some(0.5));
333 }
334}