1#[macro_use]
2mod macros;
3
4use crate::types::*;
5
6use libc::c_char;
7use std::error::Error;
8use std::ffi::CStr;
9use std::mem;
10use std::ptr;
11use std::slice;
12
13ffi_fn! {
14 fn load_annoy_index(path: *const c_char, dimension: i32, index_type: u8) -> *const AnnoyIndex {
15 let result = load_annoy_index_inner(path, dimension, index_type);
16 return match result {
17 Ok(ptr) => ptr,
18 Err(_e) => ptr::null(),
19 };
20 }
21}
22
23fn load_annoy_index_inner(
24 path: *const c_char,
25 dimension: i32,
26 index_type: u8,
27) -> Result<*const AnnoyIndex, Box<dyn Error>> {
28 let c_str_path = unsafe { CStr::from_ptr(path) };
29 let ru_path = c_str_path.to_str()?;
30 let ru_index_type: IndexType = unsafe { mem::transmute(index_type) };
31 let index = AnnoyIndex::load(dimension as usize, ru_path, ru_index_type)?;
32 return Ok(Box::into_raw(Box::new(index)));
33}
34
35ffi_fn! {
36 fn free_annoy_index(index: *const AnnoyIndex) {
37 unsafe { Box::from_raw(index as *mut AnnoyIndex); }
38 }
39}
40
41ffi_fn! {
42 fn get_dimension(index_ptr: *const AnnoyIndex) -> i32 {
43 let index = unsafe { &*index_ptr };
44 return index.dimension as i32;
45 }
46}
47
48ffi_fn! {
49 fn get_size(index_ptr: *const AnnoyIndex) -> u64 {
50 let index = unsafe { &*index_ptr };
51 return index.size as u64;
52 }
53}
54
55ffi_fn! {
56 fn get_item_vector(index_ptr: *const AnnoyIndex, item_index: u64, item_vector: *mut f32){
57 let index = unsafe{&*index_ptr};
58 let item_vec = index.get_item_vector(item_index);
59 let ptr = item_vec.as_ptr();
60 unsafe { ptr.copy_to(item_vector, index.dimension as usize) };
61 }
62}
63
64ffi_fn! {
65 fn get_nearest(
66 index_ptr: *const AnnoyIndex,
67 query_vector_ptr: *const f32,
68 n_results: u32,
69 search_k: i32,
70 should_include_distance: bool) -> *const AnnoyIndexSearchResult
71 {
72 let index = unsafe{&*index_ptr};
73 let query_vector = unsafe { slice::from_raw_parts(query_vector_ptr, index.dimension as usize) };
74 let result = index.get_nearest(query_vector, n_results as usize, search_k, should_include_distance);
75 return Box::into_raw(Box::new(result));
76 }
77}
78
79ffi_fn! {
80 fn get_nearest_to_item(
81 index_ptr: *const AnnoyIndex,
82 item_index: u64,
83 n_results: u32,
84 search_k: i32,
85 should_include_distance: bool,
86 ) -> *const AnnoyIndexSearchResult {
87 let index = unsafe { &*index_ptr };
88 let result =
89 index.get_nearest_to_item(item_index, n_results as usize, search_k, should_include_distance);
90 return Box::into_raw(Box::new(result));
91 }
92}
93
94ffi_fn! {
95 fn free_search_result(search_result_ptr: *const AnnoyIndexSearchResult){
96 unsafe { Box::from_raw(search_result_ptr as *mut AnnoyIndexSearchResult); }
97 }
98}
99
100ffi_fn! {
101 fn get_result_count(search_result_ptr: *const AnnoyIndexSearchResult) -> u64{
102 let search_result = unsafe{&*search_result_ptr};
103 return search_result.count as u64;
104 }
105}
106
107ffi_fn! {
108 fn get_id_list(search_result_ptr: *const AnnoyIndexSearchResult)->*const u64{
109 let search_result = unsafe{&*search_result_ptr};
110 return search_result.id_list.as_ptr();
111 }
112}
113
114ffi_fn! {
115 fn get_distance_list(search_result_ptr: *const AnnoyIndexSearchResult)->*const f32{
116 let search_result = unsafe{&*search_result_ptr};
117 return search_result.distance_list.as_ptr();
118 }
119}