sourmash/ffi/
nodegraph.rs1use std::ffi::CStr;
2use std::os::raw::c_char;
3use std::slice;
4
5use crate::prelude::*;
6use crate::sketch::nodegraph::Nodegraph;
7
8use crate::ffi::minhash::SourmashKmerMinHash;
9use crate::ffi::utils::ForeignObject;
10
11pub struct SourmashNodegraph;
12
13impl ForeignObject for SourmashNodegraph {
14 type RustObject = Nodegraph;
15}
16
17#[no_mangle]
18pub unsafe extern "C" fn nodegraph_new() -> *mut SourmashNodegraph {
19 SourmashNodegraph::from_rust(Nodegraph::default())
20}
21
22#[no_mangle]
23pub unsafe extern "C" fn nodegraph_free(ptr: *mut SourmashNodegraph) {
24 SourmashNodegraph::drop(ptr);
25}
26
27#[no_mangle]
28pub unsafe extern "C" fn nodegraph_buffer_free(ptr: *mut u8, insize: usize) {
29 if ptr.is_null() {
30 return;
31 }
32 Vec::from_raw_parts(ptr, insize, insize);
33}
34
35#[no_mangle]
36pub unsafe extern "C" fn nodegraph_with_tables(
37 ksize: usize,
38 starting_size: usize,
39 n_tables: usize,
40) -> *mut SourmashNodegraph {
41 let ng = Nodegraph::with_tables(starting_size, n_tables, ksize);
42 SourmashNodegraph::from_rust(ng)
43}
44
45#[no_mangle]
46pub unsafe extern "C" fn nodegraph_count(ptr: *mut SourmashNodegraph, h: u64) -> bool {
47 let ng = SourmashNodegraph::as_rust_mut(ptr);
48 ng.count(h)
49}
50
51#[no_mangle]
52pub unsafe extern "C" fn nodegraph_count_kmer(
53 ptr: *mut SourmashNodegraph,
54 kmer: *const c_char,
55) -> bool {
56 let ng = SourmashNodegraph::as_rust_mut(ptr);
57
58 let c_str = {
60 assert!(!kmer.is_null());
61
62 CStr::from_ptr(kmer)
63 };
64
65 ng.count_kmer(c_str.to_bytes())
66}
67
68#[no_mangle]
69pub unsafe extern "C" fn nodegraph_get(ptr: *const SourmashNodegraph, h: u64) -> usize {
70 let ng = SourmashNodegraph::as_rust(ptr);
71 ng.get(h)
72}
73
74#[no_mangle]
75pub unsafe extern "C" fn nodegraph_get_kmer(
76 ptr: *const SourmashNodegraph,
77 kmer: *const c_char,
78) -> usize {
79 let ng = SourmashNodegraph::as_rust(ptr);
80
81 let c_str = {
83 assert!(!kmer.is_null());
84
85 CStr::from_ptr(kmer)
86 };
87
88 ng.get_kmer(c_str.to_bytes())
89}
90
91#[no_mangle]
92pub unsafe extern "C" fn nodegraph_expected_collisions(ptr: *const SourmashNodegraph) -> f64 {
93 let ng = SourmashNodegraph::as_rust(ptr);
94 ng.expected_collisions()
95}
96
97#[no_mangle]
98pub unsafe extern "C" fn nodegraph_ksize(ptr: *const SourmashNodegraph) -> usize {
99 let ng = SourmashNodegraph::as_rust(ptr);
100 ng.ksize()
101}
102
103#[no_mangle]
104pub unsafe extern "C" fn nodegraph_hashsizes(
105 ptr: *const SourmashNodegraph,
106 size: *mut usize,
107) -> *const u64 {
108 let ng = SourmashNodegraph::as_rust(ptr);
109 let st = ng.tablesizes();
110
111 let b = st.into_boxed_slice();
112 *size = b.len();
113
114 Box::into_raw(b) as *const u64
116}
117
118#[no_mangle]
119pub unsafe extern "C" fn nodegraph_ntables(ptr: *const SourmashNodegraph) -> usize {
120 let ng = SourmashNodegraph::as_rust(ptr);
121 ng.ntables()
122}
123
124#[no_mangle]
125pub unsafe extern "C" fn nodegraph_noccupied(ptr: *const SourmashNodegraph) -> usize {
126 let ng = SourmashNodegraph::as_rust(ptr);
127 ng.noccupied()
128}
129
130#[no_mangle]
131pub unsafe extern "C" fn nodegraph_matches(
132 ptr: *const SourmashNodegraph,
133 mh_ptr: *const SourmashKmerMinHash,
134) -> usize {
135 let ng = SourmashNodegraph::as_rust(ptr);
136 let mh = SourmashKmerMinHash::as_rust(mh_ptr);
137 ng.matches(mh)
138}
139
140#[no_mangle]
141pub unsafe extern "C" fn nodegraph_update(
142 ptr: *mut SourmashNodegraph,
143 optr: *const SourmashNodegraph,
144) {
145 let ng = SourmashNodegraph::as_rust_mut(ptr);
146 let ong = SourmashNodegraph::as_rust(optr);
147
148 ong.update(ng).unwrap();
150}
151
152#[no_mangle]
153pub unsafe extern "C" fn nodegraph_update_mh(
154 ptr: *mut SourmashNodegraph,
155 optr: *const SourmashKmerMinHash,
156) {
157 let ng = SourmashNodegraph::as_rust_mut(ptr);
158 let mh = SourmashKmerMinHash::as_rust(optr);
159
160 mh.update(ng).unwrap();
161}
162
163ffi_fn! {
164unsafe fn nodegraph_from_path(filename: *const c_char) -> Result<*mut SourmashNodegraph> {
165 let c_str = {
167 assert!(!filename.is_null());
168
169 CStr::from_ptr(filename)
170 };
171
172 let (mut input, _) = niffler::from_path(c_str.to_str()?)?;
173 let ng = Nodegraph::from_reader(&mut input)?;
174
175 Ok(SourmashNodegraph::from_rust(ng))
176}
177}
178
179ffi_fn! {
180unsafe fn nodegraph_from_buffer(ptr: *const c_char, insize: usize) -> Result<*mut SourmashNodegraph> {
181 let buf = {
183 assert!(!ptr.is_null());
184 slice::from_raw_parts(ptr as *mut u8, insize)
185 };
186
187 let ng = Nodegraph::from_reader(buf)?;
188
189 Ok(SourmashNodegraph::from_rust(ng))
190}
191}
192
193ffi_fn! {
194unsafe fn nodegraph_save(ptr: *const SourmashNodegraph, filename: *const c_char) -> Result<()> {
195 let ng = SourmashNodegraph::as_rust(ptr);
196
197 let c_str = {
199 assert!(!filename.is_null());
200
201 CStr::from_ptr(filename)
202 };
203
204 ng.save(c_str.to_str()?)?;
205
206 Ok(())
207}
208}
209
210ffi_fn! {
211unsafe fn nodegraph_to_buffer(ptr: *const SourmashNodegraph, compression: u8, size: *mut usize) -> Result<*const u8> {
212 let ng = SourmashNodegraph::as_rust(ptr);
213
214 let mut buffer = vec![];
215 {
216 let mut writer = if compression > 0 {
217 let level = match compression {
218 1 => niffler::compression::Level::One,
219 2 => niffler::compression::Level::Two,
220 3 => niffler::compression::Level::Three,
221 4 => niffler::compression::Level::Four,
222 5 => niffler::compression::Level::Five,
223 6 => niffler::compression::Level::Six,
224 7 => niffler::compression::Level::Seven,
225 8 => niffler::compression::Level::Eight,
226 _ => niffler::compression::Level::Nine,
227 };
228
229 niffler::get_writer(Box::new(&mut buffer),
230 niffler::compression::Format::Gzip,
231 level)?
232 } else {
233 Box::new(&mut buffer)
234 };
235 ng.save_to_writer(&mut writer)?;
236 }
237
238 let b = buffer.into_boxed_slice();
239 *size = b.len();
240
241 Ok(Box::into_raw(b) as *const u8)
243}
244}