1use openiap_client::protos::{
6 AggregateRequest, CountRequest, DistinctRequest, DownloadRequest, Envelope, InsertOneRequest,
7 QueryRequest, SigninRequest, UploadRequest, WatchEvent, WatchRequest,
8};
9use openiap_client::{Client, ClientEvent, CreateCollectionRequest, CreateIndexRequest, CustomCommandRequest, DeleteManyRequest, DeleteOneRequest, DeleteWorkitemRequest, DropCollectionRequest, DropIndexRequest, GetIndexesRequest, InsertManyRequest, InsertOrUpdateOneRequest, PopWorkitemRequest, PushWorkitemRequest, QueueEvent, QueueMessageRequest, RegisterExchangeRequest, RegisterQueueRequest, Timestamp, UpdateOneRequest, UpdateWorkitemRequest, Workitem, WorkitemFile};
10
11#[cfg(all(test, not(windows)))]
12mod tests;
13
14use std::collections::{HashMap, VecDeque};
15use std::ffi::CStr;
16use std::ffi::CString;
17use std::os::raw::c_char;
18use std::sync::Mutex;
19use std::vec;
20
21mod safe_wrappers;
22use safe_wrappers::{c_char_to_str, safe_wrapper};
23
24use lazy_static::lazy_static;
25lazy_static! {
26 static ref WATCH_EVENTS: std::sync::Mutex<HashMap<String, VecDeque<WatchEvent>>> = {
28 let m = HashMap::new();
29 Mutex::new(m)
30 };
31 static ref QUEUE_EVENTS: std::sync::Mutex<HashMap<String, VecDeque<QueueEvent>>> = {
32 let m = HashMap::new();
33 Mutex::new(m)
34 };
35 static ref CLIENT_EVENTS: std::sync::Mutex<HashMap<String, VecDeque<ClientEvent>>> = {
36 let m = HashMap::new();
37 Mutex::new(m)
38 };
39
40}
41
42use tracing::{error, info, warn, debug, trace};
43#[no_mangle]
44#[tracing::instrument(skip_all)]
45pub extern "C" fn error(message: *const c_char) {
46 let message = c_char_to_str(message);
47 error!("{}", message);
48}
49#[no_mangle]
50#[tracing::instrument(skip_all)]
51pub extern "C" fn info(message: *const c_char) {
52 let message = c_char_to_str(message);
53 info!("{}", message);
54}
55#[no_mangle]
56#[tracing::instrument(skip_all)]
57pub extern "C" fn warn(message: *const c_char) {
58 let message = c_char_to_str(message);
59 warn!("{}", message);
60}
61#[no_mangle]
62#[tracing::instrument(skip_all)]
63pub extern "C" fn debug(message: *const c_char) {
64 let message = c_char_to_str(message);
65 debug!("{}", message);
66}
67#[no_mangle]
68#[tracing::instrument(skip_all)]
69pub extern "C" fn trace(message: *const c_char) {
70 let message = c_char_to_str(message);
71 trace!("{}", message);
72}
73#[no_mangle]
74#[tracing::instrument(skip_all)]
75pub extern "C" fn set_f64_observable_gauge(name: *const c_char, value: f64, description: *const c_char) {
76 let name = c_char_to_str(name);
77 let description = c_char_to_str(description);
78 match openiap_client::set_f64_observable_gauge(&name, value, &description) {
79 Ok(_) => debug!("observable gauge '{}' created with inital value: {}", name, value),
80 Err(e) => error!("Failed to register custom metric: {}", e),
81 };
82}
83#[no_mangle]
84#[tracing::instrument(skip_all)]
85pub extern "C" fn set_u64_observable_gauge(name: *const c_char, value: u64, description: *const c_char) {
86 let name = c_char_to_str(name);
87 let description = c_char_to_str(description);
88 match openiap_client::set_u64_observable_gauge(&name, value, &description) {
89 Ok(_) => debug!("observable gauge '{}' created with inital value: {}", name, value),
90 Err(e) => error!("Failed to register custom metric: {}", e),
91 };
92}
93#[no_mangle]
94#[tracing::instrument(skip_all)]
95pub extern "C" fn set_i64_observable_gauge(name: *const c_char, value: i64, description: *const c_char) {
96 let name = c_char_to_str(name);
97 let description = c_char_to_str(description);
98 match openiap_client::set_i64_observable_gauge(&name, value, &description) {
99 Ok(_) => debug!("observable gauge '{}' created with inital value: {}", name, value),
100 Err(e) => error!("Failed to register custom metric: {}", e),
101 };
102}
103#[no_mangle]
104#[tracing::instrument(skip_all)]
105pub extern "C" fn disable_observable_gauge(name: *const c_char) {
106 let name = c_char_to_str(name);
107 openiap_client::disable_observable_gauge(&name);
108}
109
110#[repr(C)]
113pub struct ClientWrapper {
114 success: bool,
115 error: *const c_char,
116 client: Option<Client>
117}
118#[repr(C)]
120#[derive(Debug, Clone)]
121pub struct WatchEventWrapper {
122 id: *const c_char,
123 operation: *const c_char,
124 document: *const c_char,
125 request_id: i32,
126}
127impl Default for WatchEventWrapper {
128 fn default() -> Self {
129 WatchEventWrapper {
130 id: std::ptr::null(),
131 operation: std::ptr::null(),
132 document: std::ptr::null(),
133 request_id: 0,
134 }
135 }
136}
137#[repr(C)]
138pub struct UserWrapper {
139 id: *const c_char,
140 name: *const c_char,
141 username: *const c_char,
142 email: *const c_char,
143 roles: *const *const c_char,
144 roles_len: i32,
145}
146
147#[no_mangle]
149#[tracing::instrument(skip_all)]
150pub extern "C" fn client_user(
151 client: *mut ClientWrapper
152) -> *const UserWrapper {
153 let client_wrapper = match safe_wrapper(client) {
154 Some(client) => client,
155 None => {
156 return std::ptr::null();
157 }
158 };
159 let b = client_wrapper.client.clone().unwrap();
160 let user = b.get_user();
161 match user {
162 None => {
163 return std::ptr::null();
164 }
165 Some(user) => {
166 let role_ptrs: Vec<*const c_char> = user.roles.iter()
168 .map(|role| {
169 CString::new(role.name.clone())
170 .unwrap()
171 .into_raw() as *const c_char })
173 .collect();
174
175 let roles_len = role_ptrs.len(); let roles_buf = role_ptrs.into_boxed_slice();
178 let roles_ptr = Box::into_raw(roles_buf) as *const *const c_char;
179
180 let response = UserWrapper {
181 id: CString::new(user.id).unwrap().into_raw(),
182 name: CString::new(user.name).unwrap().into_raw(),
183 username: CString::new(user.username).unwrap().into_raw(),
184 email: CString::new(user.email).unwrap().into_raw(),
185 roles: roles_ptr,
186 roles_len: roles_len as i32,
187 };
188 return Box::into_raw(Box::new(response)) as *mut UserWrapper;
189 }
190 }
191}
192#[no_mangle]
194#[tracing::instrument(skip_all)]
195pub extern "C" fn free_user(user: *mut UserWrapper) {
196 if user.is_null() {
197 return;
198 }
199 unsafe {
200 if !(*user).id.is_null() {
201 let _ = CString::from_raw((*user).id as *mut c_char);
202 }
203 if !(*user).name.is_null() {
204 let _ = CString::from_raw((*user).name as *mut c_char);
205 }
206 if !(*user).username.is_null() {
207 let _ = CString::from_raw((*user).username as *mut c_char);
208 }
209 if !(*user).email.is_null() {
210 let _ = CString::from_raw((*user).email as *mut c_char);
211 }
212 if !(*user).roles.is_null() {
213 let roles = (*user).roles;
214 let mut i = 0;
215 while !roles.offset(i).is_null() {
216 let _ = CString::from_raw(roles.offset(i) as *mut c_char);
217 i += 1;
218 }
219 }
220 let _ = Box::from_raw(user);
221 }
222}
223
224#[repr(C)]
226pub struct QueryRequestWrapper {
227 collectionname: *const c_char,
228 query: *const c_char,
229 projection: *const c_char,
230 orderby: *const c_char,
231 queryas: *const c_char,
232 explain: bool,
233 skip: i32,
234 top: i32,
235 request_id: i32,
236}
237#[repr(C)]
239pub struct QueryResponseWrapper {
240 success: bool,
241 results: *const c_char,
242 error: *const c_char,
243 request_id: i32,
244}
245#[no_mangle]
247#[tracing::instrument(skip_all)]
248pub extern "C" fn query(
249 client: *mut ClientWrapper,
250 options: *mut QueryRequestWrapper,
251) -> *mut QueryResponseWrapper {
252 let options = match safe_wrapper(options) {
253 Some(options) => options,
254 None => {
255 let error_msg = CString::new("Invalid options").unwrap().into_raw();
256 let response = QueryResponseWrapper {
257 success: false,
258 results: std::ptr::null(),
259 error: error_msg,
260 request_id: 0,
261 };
262 return Box::into_raw(Box::new(response));
263 }
264 };
265 let client_wrapper = match safe_wrapper(client) {
266 Some(client) => client,
267 None => {
268 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
269 let response = QueryResponseWrapper {
270 success: false,
271 results: std::ptr::null(),
272 error: error_msg,
273 request_id: options.request_id,
274 };
275 return Box::into_raw(Box::new(response));
276 }
277 };
278 let request = QueryRequest {
279 collectionname: c_char_to_str(options.collectionname),
280 query: c_char_to_str(options.query),
281 projection: c_char_to_str(options.projection),
282 orderby: c_char_to_str(options.orderby),
283 queryas: c_char_to_str(options.queryas),
284 explain: options.explain,
285 skip: options.skip,
286 top: options.top
287 };
288 if client_wrapper.client.is_none() {
289 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
290 let response = QueryResponseWrapper {
291 success: false,
292 results: std::ptr::null(),
293 error: error_msg,
294 request_id: options.request_id,
295 };
296 return Box::into_raw(Box::new(response));
297 }
298 let client = client_wrapper.client.clone().unwrap();
299
300 let result = tokio::task::block_in_place(|| {
301 let handle = client.get_runtime_handle();
302 handle.block_on(client.query(request))
303 });
304 Box::into_raw(Box::new(match result {
305 Ok(data) => {
306 let results: *const c_char = CString::new(data.results).unwrap().into_raw();
307 QueryResponseWrapper {
308 success: true,
309 results,
310 error: std::ptr::null(),
311 request_id: options.request_id,
312 }
313 }
314 Err(e) => {
315 let error_msg = CString::new(format!("Query failed: {:?}", e))
316 .unwrap()
317 .into_raw();
318 QueryResponseWrapper {
319 success: false,
320 results: std::ptr::null(),
321 error: error_msg,
322 request_id: options.request_id,
323 }
324 }
325 }))
326}
327type QueryCallback = extern "C" fn(wrapper: *mut QueryResponseWrapper);
329#[no_mangle]
331#[tracing::instrument(skip_all)]
332pub extern "C" fn query_async(
333 client: *mut ClientWrapper,
334 options: *mut QueryRequestWrapper,
335 callback: QueryCallback,
336) {
337 debug!("Rust: query_async");
338 let options = match safe_wrapper(options) {
339 Some(options) => options,
340 None => {
341 let error_msg = CString::new("Invalid options").unwrap().into_raw();
342 let response = QueryResponseWrapper {
343 success: false,
344 results: std::ptr::null(),
345 error: error_msg,
346 request_id: 0,
347 };
348 return callback(Box::into_raw(Box::new(response)));
349 }
350 };
351 let client_wrapper = match safe_wrapper(client) {
352 Some(client) => client,
353 None => {
354 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
355 let response = QueryResponseWrapper {
356 success: false,
357 results: std::ptr::null(),
358 error: error_msg,
359 request_id: options.request_id,
360 };
361 return callback(Box::into_raw(Box::new(response)));
362 }
363 };
364 let client = client_wrapper.client.clone();
365 let collectionname = c_char_to_str(options.collectionname);
366 let query = c_char_to_str(options.query);
367 let projection = c_char_to_str(options.projection);
368 let orderby = c_char_to_str(options.orderby);
369 let queryas = c_char_to_str(options.queryas);
370 let explain = options.explain;
371 let skip = options.skip;
372 let top = options.top;
373 debug!("Rust: query_async: collectionname: {}, query: {}, projection: {}, orderby: {}, queryas: {}, explain: {}, skip: {}, top: {}", collectionname, query, projection, orderby, queryas, explain, skip, top);
374
375 let request = QueryRequest {
376 collectionname: collectionname.to_string(),
377 query: query.to_string(),
378 projection: projection.to_string(),
379 orderby: orderby.to_string(),
380 queryas: queryas.to_string(),
381 explain,
382 skip,
383 top
384 };
385 if client.is_none() {
386 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
387 let response = QueryResponseWrapper {
388 success: false,
389 results: std::ptr::null(),
390 error: error_msg,
391 request_id: options.request_id,
392 };
393 return callback(Box::into_raw(Box::new(response)));
394 }
395
396 debug!("Rust: runtime.spawn");
397 let client = client.unwrap();
398 let handle = client.get_runtime_handle();
399 let request_id = options.request_id;
400 let _guard = handle.enter();
402 handle.spawn(async move {
403 debug!("Rust: client.query");
404 let result = client.query(request).await;
405
406 let response = match result {
407 Ok(data) => {
408 let results: *const c_char = CString::new(data.results).unwrap().into_raw();
409 QueryResponseWrapper {
410 success: true,
411 results,
412 error: std::ptr::null(),
413 request_id: request_id,
414 }
415 }
416 Err(e) => {
417 let error_msg = CString::new(format!("Query failed: {:?}", e))
418 .unwrap()
419 .into_raw();
420 QueryResponseWrapper {
421 success: false,
422 results: std::ptr::null(),
423 error: error_msg,
424 request_id: request_id,
425 }
426 }
427 };
428 debug!("Rust: callback response");
429 callback(Box::into_raw(Box::new(response)));
430 });
431}
432#[no_mangle]
433#[tracing::instrument(skip_all)]
434pub extern "C" fn free_query_response(response: *mut QueryResponseWrapper) {
435 if response.is_null() {
436 return;
437 }
438 unsafe {
439 if !(*response).error.is_null() {
440 let _ = CString::from_raw((*response).error as *mut c_char);
441 }
442 if !(*response).results.is_null() {
443 let _ = CString::from_raw((*response).results as *mut c_char);
444 }
445 let _ = Box::from_raw(response);
446 }
447}
448
449#[repr(C)]
451pub struct CustomCommandRequestWrapper {
452 pub command: *const c_char,
453 pub id: *const c_char,
454 pub name: *const c_char,
455 pub data: *const c_char,
456 pub request_id: i32,
457}
458
459#[repr(C)]
461pub struct CustomCommandResponseWrapper {
462 pub success: bool,
463 pub result: *const c_char,
464 pub error: *const c_char,
465 pub request_id: i32,
466}
467#[no_mangle]
468#[tracing::instrument(skip_all)]
469pub extern "C" fn custom_command(
470 client: *mut ClientWrapper,
471 options: *mut CustomCommandRequestWrapper,
472 timeout: i32
473) -> *mut CustomCommandResponseWrapper {
474 let options = match safe_wrapper(options) {
475 Some(options) => options,
476 None => {
477 let error_msg = CString::new("Invalid options").unwrap().into_raw();
478 let response = CustomCommandResponseWrapper {
479 success: false,
480 result: std::ptr::null(),
481 error: error_msg,
482 request_id: 0,
483 };
484 return Box::into_raw(Box::new(response));
485 }
486 };
487 let client_wrapper = match safe_wrapper(client) {
488 Some(client) => client,
489 None => {
490 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
491 let response = CustomCommandResponseWrapper {
492 success: false,
493 result: std::ptr::null(),
494 error: error_msg,
495 request_id: options.request_id,
496 };
497 return Box::into_raw(Box::new(response));
498 }
499 };
500
501 if client_wrapper.client.is_none() {
502 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
503 let response = CustomCommandResponseWrapper {
504 success: false,
505 result: std::ptr::null(),
506 error: error_msg,
507 request_id: options.request_id,
508 };
509 return Box::into_raw(Box::new(response));
510 }
511
512 let request = CustomCommandRequest {
513 command: c_char_to_str(options.command).to_string(),
514 id: c_char_to_str(options.id).to_string(),
515 name: c_char_to_str(options.name).to_string(),
516 data: c_char_to_str(options.data).to_string(),
517 };
518
519 let client = client_wrapper.client.clone().unwrap();
520
521 let mut _timeout = client.get_default_timeout();
522 if timeout >= 0 {
523 _timeout = tokio::time::Duration::from_secs(timeout as u64);
524 }
525 let result = tokio::task::block_in_place(|| {
526 let handle = client.get_runtime_handle();
527 handle.block_on(client.custom_command(request, Some(_timeout)))
528 });
529
530 Box::into_raw(Box::new(match result {
531 Ok(data) => {
532 let result_str = CString::new(data).unwrap().into_raw();
533 CustomCommandResponseWrapper {
534 success: true,
535 result: result_str,
536 error: std::ptr::null(),
537 request_id: options.request_id,
538 }
539 }
540 Err(e) => {
541 let error_msg = CString::new(format!("Custom command failed: {:?}", e))
542 .unwrap()
543 .into_raw();
544 CustomCommandResponseWrapper {
545 success: false,
546 result: std::ptr::null(),
547 error: error_msg,
548 request_id: options.request_id,
549 }
550 }
551 }))
552}
553type CustomCommandCallback = extern "C" fn(wrapper: *mut CustomCommandResponseWrapper);
554#[no_mangle]
555#[tracing::instrument(skip_all)]
556pub extern "C" fn custom_command_async(
557 client: *mut ClientWrapper,
558 options: *mut CustomCommandRequestWrapper,
559 callback: CustomCommandCallback,
560 timeout: i32
561) {
562 let options = match safe_wrapper(options) {
563 Some(options) => options,
564 None => {
565 let error_msg = CString::new("Invalid options").unwrap().into_raw();
566 let response = CustomCommandResponseWrapper {
567 success: false,
568 result: std::ptr::null(),
569 error: error_msg,
570 request_id: 0,
571 };
572 return callback(Box::into_raw(Box::new(response)));
573 }
574 };
575 let client_wrapper = match safe_wrapper(client) {
576 Some(client) => client,
577 None => {
578 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
579 let response = CustomCommandResponseWrapper {
580 success: false,
581 result: std::ptr::null(),
582 error: error_msg,
583 request_id: options.request_id,
584 };
585 return callback(Box::into_raw(Box::new(response)));
586 }
587 };
588
589 let client = client_wrapper.client.clone();
590 let request_id = options.request_id;
591
592 let request = CustomCommandRequest {
593 command: c_char_to_str(options.command).to_string(),
594 id: c_char_to_str(options.id).to_string(),
595 name: c_char_to_str(options.name).to_string(),
596 data: c_char_to_str(options.data).to_string(),
597 };
598
599 if client.is_none() {
600 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
601 let response = CustomCommandResponseWrapper {
602 success: false,
603 result: std::ptr::null(),
604 error: error_msg,
605 request_id,
606 };
607 return callback(Box::into_raw(Box::new(response)));
608 }
609
610 let client = client.unwrap();
611 let handle = client.get_runtime_handle();
612 let _guard = handle.enter();
613
614 let mut _timeout = client.get_default_timeout();
615 if timeout >= 0 {
616 _timeout = tokio::time::Duration::from_secs(timeout as u64);
617 }
618
619 handle.spawn(async move {
620 let result = client.custom_command(request, Some(_timeout)).await;
621
622 let response = match result {
623 Ok(data) => {
624 let result_str = CString::new(data).unwrap().into_raw();
625 CustomCommandResponseWrapper {
626 success: true,
627 result: result_str,
628 error: std::ptr::null(),
629 request_id,
630 }
631 }
632 Err(e) => {
633 let error_msg = CString::new(format!("Custom command failed: {:?}", e))
634 .unwrap()
635 .into_raw();
636 CustomCommandResponseWrapper {
637 success: false,
638 result: std::ptr::null(),
639 error: error_msg,
640 request_id,
641 }
642 }
643 };
644 callback(Box::into_raw(Box::new(response)));
645 });
646}
647#[no_mangle]
648pub extern "C" fn free_custom_command_response(response: *mut CustomCommandResponseWrapper) {
649 if response.is_null() {
650 return;
651 }
652 unsafe {
653 if !(*response).error.is_null() {
654 let _ = CString::from_raw((*response).error as *mut c_char);
655 }
656 if !(*response).result.is_null() {
657 let _ = CString::from_raw((*response).result as *mut c_char);
658 }
659 let _ = Box::from_raw(response);
660 }
661}
662
663#[no_mangle]
664#[tracing::instrument(skip_all)]
665pub extern "C" fn enable_tracing(rust_log: *const c_char, tracing: *const c_char) {
666 let rust_log = c_char_to_str(rust_log);
667 let rust_log = rust_log.to_string();
668 let tracing = c_char_to_str(tracing);
669 let tracing = tracing.to_string();
670 openiap_client::enable_tracing(&rust_log, &tracing);
671}
672#[no_mangle]
673#[tracing::instrument(skip_all)]
674pub extern "C" fn disable_tracing() {
675 openiap_client::disable_tracing();
676}
677
678
679fn free<T>(ptr: *mut T) {
680 if ptr.is_null() {
681 return;
682 }
683 unsafe {
684 let _ = Box::from_raw(ptr);
685 }
686}
687
688#[no_mangle]
689pub extern "C" fn create_client() -> *mut ClientWrapper {
690 let client = Client::new();
691 client.set_agent_name("c");
692 trace!("create_client");
693 Box::into_raw(Box::new(ClientWrapper {
694 client: Some(client),
695 success: true,
696 error: std::ptr::null(),
697 }))
698}
699#[repr(C)]
702pub struct ConnectResponseWrapper {
703 success: bool,
704 error: *const c_char,
705 request_id: i32,
706}
707#[no_mangle]
708pub extern "C" fn client_connect(client_wrap: *mut ClientWrapper, server_address: *const c_char) -> *mut ConnectResponseWrapper {
709 let server_address = c_char_to_str(server_address);
710 trace!("server_address = {:?}", server_address);
711 let client = match safe_wrapper( client_wrap ) {
712 Some( wrap ) => wrap.client.clone().unwrap(),
713 None => {
714 Client::new()
715 }
716 };
717 trace!("connect::begin");
718 let res: Result<(), openiap_client::OpenIAPError> = client.connect(&server_address);
719 trace!("connect::complete");
720 if res.is_err() {
721 let e = res.err().unwrap();
722 debug!("error_msg = {:?}", format!("Connection failed: {:?}", e));
723 let error_msg = CString::new(format!("Connection failed: {:?}", e))
724 .unwrap()
725 .into_raw();
726
727 let result = Box::into_raw(Box::new(ConnectResponseWrapper {
728 success: false,
729 error: error_msg,
730 request_id: 0,
731 }));
732 debug!("connect::complete error result address: {:?}", result);
733 return result;
734 }
735 let result = Box::into_raw(Box::new(ConnectResponseWrapper {
736 success: true,
737 error: std::ptr::null(),
738 request_id: 0,
739 }));
740 trace!("connect::complete result address: {:?}", result);
741 result
742}
743type ConnectCallback = extern "C" fn(wrapper: *mut ConnectResponseWrapper);
744#[no_mangle]
745#[tracing::instrument(skip_all)]
746pub extern "C" fn connect_async(client: *mut ClientWrapper, server_address: *const c_char, request_id: i32, callback: ConnectCallback) {
747 debug!("connect_async");
748 let server_address = c_char_to_str(server_address);
749 debug!("server_address = {:?}", server_address);
750
751 let client = match safe_wrapper( client ) {
752 Some( wrap ) => wrap.client.clone().unwrap(),
753 None => {
754 Client::new()
755 }
756 };
757
758 trace!("Spawn the async task");
759 let client_result: Result<(), openiap_client::OpenIAPError> = client.connect(&server_address);
760 let handle = client.get_runtime_handle();
761 handle.spawn(async move {
762 let wrapper = if client_result.is_ok() {
763 Box::into_raw(Box::new(ConnectResponseWrapper {
764 success: true,
765 error: std::ptr::null(),
766 request_id,
767 }))
768 } else {
769 let e = client_result.err().unwrap();
770 let error_msg = CString::new(format!("Connection failed: {:?}", e))
771 .unwrap()
772 .into_raw();
773 Box::into_raw(Box::new(ConnectResponseWrapper {
774 success: false,
775 error: error_msg,
776 request_id,
777 }))
778 };
779 trace!("Client::Calling callback with result");
780 callback(wrapper);
781 });
782}
783#[no_mangle]
784pub extern "C" fn client_set_default_timeout(client_wrap: *mut ClientWrapper, timeout: i32) {
785 debug!("set_default_timeout = {:?}", timeout);
786 let client = match safe_wrapper( client_wrap ) {
787 Some( wrap ) => wrap.client.clone().unwrap(),
788 None => {
789 Client::new()
790 }
791 };
792 let mut _timeout = client.get_default_timeout();
793 if timeout >= 0 {
794 _timeout = tokio::time::Duration::from_secs(timeout as u64);
795 }
796 client.set_default_timeout(_timeout);
797}
798#[no_mangle]
799pub extern "C" fn client_set_agent_name(client_wrap: *mut ClientWrapper, agent_name: *const c_char) {
800 let agent_name = c_char_to_str(agent_name);
801 debug!("set_agent_name = {:?}", agent_name);
802 let client = match safe_wrapper( client_wrap ) {
803 Some( wrap ) => wrap.client.clone().unwrap(),
804 None => {
805 Client::new()
806 }
807 };
808 client.set_agent_name(&agent_name);
809}
810#[no_mangle]
811pub extern "C" fn client_set_agent_version(client_wrap: *mut ClientWrapper, agent_version: *const c_char) {
812 let agent_version = c_char_to_str(agent_version);
813 debug!("set_agent_version = {:?}", agent_version);
814 let client = match safe_wrapper( client_wrap ) {
815 Some( wrap ) => wrap.client.clone().unwrap(),
816 None => {
817 Client::new()
818 }
819 };
820 client.set_agent_version(&agent_version);
821}
822#[no_mangle]
823#[tracing::instrument(skip_all)]
824pub extern "C" fn free_connect_response(response: *mut ConnectResponseWrapper) {
825 free(response);
826}
827
828#[no_mangle]
829#[tracing::instrument(skip_all)]
830pub extern "C" fn client_disconnect(client_wrap: *mut ClientWrapper) {
831 let client = match safe_wrapper( client_wrap ) {
832 Some( wrap ) => wrap.client.clone().unwrap(),
833 None => {
834 Client::new()
835 }
836 };
837 client.disconnect();
838}
839#[no_mangle]
840#[tracing::instrument(skip_all)]
841pub extern "C" fn free_client(response: *mut ClientWrapper) {
842 if response.is_null() {
843 debug!("free_client: response is null");
844 return;
845 }
846 unsafe {
847 let response_ref: &ClientWrapper = match safe_wrapper(response) {
848 Some(response) => response,
849 None => {
850 debug!("free_client: response is not valid");
851 return;
852 }
853 };
854 if !response_ref.error.is_null() {
855 let error_cstr = CStr::from_ptr(response_ref.error);
856 if let Ok(error_str) = error_cstr.to_str() {
857 debug!("free_client: error = {}", error_str);
858 } else {
859 debug!("free_client: error = <invalid UTF-8>");
860 }
861 }
862
863 if let Some(client) = &response_ref.client {
864 client.disconnect();
866
867 let handle = client.get_runtime_handle();
868 handle.spawn(async move {
870 {
871 let inner = client.inner.lock().await;
873 let mut queries = inner.queries.lock().await;
874
875 for (id, response_tx) in queries.drain() {
877 debug!("free_client: canceling request with id: {:?}", id);
878 let _ = response_tx.send(Envelope {
879 command: "cancelled".to_string(),
880 ..Default::default()
881 });
882 }
883
884 } {
888 let inner = client.inner.lock().await;
889 let mut streams = inner.streams.lock().await;
890 let stream_keys = streams.keys().cloned().collect::<Vec<String>>();
891 stream_keys.iter().for_each(|k| {
892 debug!("free_client: client inner state: stream: {:?}", k);
893 streams.remove(k.clone().as_str());
894 });
895 } });
898 }
899 }
903 debug!("free_client::complete");
904}
905
906#[repr(C)]
907pub struct SigninRequestWrapper {
908 username: *const c_char,
909 password: *const c_char,
910 jwt: *const c_char,
911 agent: *const c_char,
912 version: *const c_char,
913 longtoken: bool,
914 validateonly: bool,
915 ping: bool,
916 request_id: i32
917}
918#[repr(C)]
919pub struct SigninResponseWrapper {
920 success: bool,
921 jwt: *const c_char,
922 error: *const c_char,
923 request_id: i32
924}
925
926#[no_mangle]
927#[tracing::instrument(skip_all)]
928pub extern "C" fn signin(
929 client: *mut ClientWrapper,
930 options: *mut SigninRequestWrapper,
931) -> *mut SigninResponseWrapper {
932 let options = match safe_wrapper( options ) {
933 Some( options ) => options,
934 None => {
935 let error_msg = CString::new("Invalid options").unwrap().into_raw();
936 let response = SigninResponseWrapper {
937 success: false,
938 jwt: std::ptr::null(),
939 error: error_msg,
940 request_id: 0,
941 };
942 return Box::into_raw(Box::new(response));
943 }
944 };
945 let client_wrapper: &mut ClientWrapper = match safe_wrapper( client ) {
946 Some( client ) => client,
947 None => {
948 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
949 let response = SigninResponseWrapper {
950 success: false,
951 jwt: std::ptr::null(),
952 error: error_msg,
953 request_id: options.request_id,
954 };
955 return Box::into_raw(Box::new(response));
956 }
957 };
958 let client = client_wrapper.client.clone();
959
960 let request = SigninRequest {
961 username: c_char_to_str(options.username),
962 password: c_char_to_str(options.password),
963 jwt: c_char_to_str(options.jwt),
964 agent: c_char_to_str(options.agent),
965 version: c_char_to_str(options.version),
966 longtoken: options.longtoken,
967 ping: options.ping,
968 validateonly: options.validateonly
969 };
970
971 if client.is_none() {
972 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
973 let response = SigninResponseWrapper {
974 success: false,
975 jwt: std::ptr::null(),
976 error: error_msg,
977 request_id: options.request_id,
978 };
979 return Box::into_raw(Box::new(response));
980 }
981 let client = client.unwrap();
982 let result = tokio::task::block_in_place(|| {
983 let handle = client.get_runtime_handle();
984 handle.block_on(client.signin(request))
985 });
986
987 let response = match result {
988 Ok(data) => {
989 let jwt = CString::new(data.jwt).unwrap().into_raw();
990 SigninResponseWrapper {
991 success: true,
992 jwt,
993 error: std::ptr::null(),
994 request_id: options.request_id,
995 }
996 }
997 Err(e) => {
998 let error_msg = CString::new(format!("Signin failed: {:?}", e))
999 .unwrap()
1000 .into_raw();
1001 SigninResponseWrapper {
1002 success: false,
1003 jwt: std::ptr::null(),
1004 error: error_msg,
1005 request_id: options.request_id,
1006 }
1007 }
1008 };
1009
1010 Box::into_raw(Box::new(response))
1011}
1012
1013type SigninCallback = extern "C" fn(wrapper: *mut SigninResponseWrapper);
1014#[no_mangle]
1015#[tracing::instrument(skip_all)]
1016pub extern "C" fn signin_async(
1017 client: *mut ClientWrapper,
1018 options: *mut SigninRequestWrapper,
1019 callback: SigninCallback,
1020) {
1021 let options = match safe_wrapper(options ) {
1022 Some( options ) => options,
1023 None => {
1024 let error_msg = CString::new("Invalid options").unwrap().into_raw();
1025 let response = SigninResponseWrapper {
1026 success: false,
1027 jwt: std::ptr::null(),
1028 error: error_msg,
1029 request_id: 0,
1030 };
1031 return callback(Box::into_raw(Box::new(response)));
1032 }
1033 };
1034 let client_wrapper = match safe_wrapper(client) {
1035 Some( client ) => client,
1036 None => {
1037 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1038 let response = SigninResponseWrapper {
1039 success: false,
1040 jwt: std::ptr::null(),
1041 error: error_msg,
1042 request_id: options.request_id,
1043 };
1044 return callback(Box::into_raw(Box::new(response)));
1045 }
1046 };
1047 let client = client_wrapper.client.clone();
1048
1049 let request = SigninRequest {
1050 username: c_char_to_str(options.username),
1051 password: c_char_to_str(options.password),
1052 jwt: c_char_to_str(options.jwt),
1053 agent: c_char_to_str(options.agent),
1054 version: c_char_to_str(options.version),
1055 longtoken: options.longtoken,
1056 ping: options.ping,
1057 validateonly: options.validateonly
1058 };
1059
1060 if client.is_none() {
1061 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1062 let response = SigninResponseWrapper {
1063 success: false,
1064 jwt: std::ptr::null(),
1065 error: error_msg,
1066 request_id: options.request_id,
1067 };
1068 return callback(Box::into_raw(Box::new(response)));
1069 }
1070 let client = client.unwrap();
1071 let handle = client.get_runtime_handle();
1072 let request_id = options.request_id;
1073 handle.spawn(async move {
1074 let result = client.signin(request).await;
1076
1077 let response = match result {
1078 Ok(data) => {
1079 let jwt = CString::new(data.jwt).unwrap().into_raw();
1080 Box::new(SigninResponseWrapper {
1081 success: true,
1082 jwt,
1083 error: std::ptr::null(),
1084 request_id
1085 })
1086 }
1087 Err(e) => {
1088 let error_msg = CString::new(format!("Signin failed: {:?}", e))
1089 .unwrap()
1090 .into_raw();
1091 Box::new(SigninResponseWrapper {
1092 success: false,
1093 jwt: std::ptr::null(),
1094 error: error_msg,
1095 request_id
1096 })
1097 }
1098 };
1099
1100 callback(Box::into_raw(response));
1101 });
1102
1103 std::thread::sleep(std::time::Duration::from_secs(2));
1105}
1106
1107#[no_mangle]
1108#[tracing::instrument(skip_all)]
1109pub extern "C" fn free_signin_response(response: *mut SigninResponseWrapper) {
1110 if response.is_null() {
1111 return;
1112 }
1113 unsafe {
1114 if !(*response).error.is_null() {
1115 let _ = CString::from_raw((*response).error as *mut c_char);
1116 }
1117 if !(*response).jwt.is_null() {
1118 let _ = CString::from_raw((*response).jwt as *mut c_char);
1119 }
1120 let _ = Box::from_raw(response);
1121 }
1122}
1123
1124#[repr(C)]
1125pub struct ListCollectionsResponseWrapper {
1126 success: bool,
1127 results: *const c_char,
1128 error: *const c_char,
1129 request_id: i32,
1130}
1131#[no_mangle]
1132#[tracing::instrument(skip_all)]
1133pub extern "C" fn list_collections(
1134 client: *mut ClientWrapper,
1135 includehist: bool,
1136) -> *mut ListCollectionsResponseWrapper {
1137 let client_wrapper = match safe_wrapper(client) {
1138 Some(client) => client,
1139 None => {
1140 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1141 let response = ListCollectionsResponseWrapper {
1142 success: false,
1143 results: std::ptr::null(),
1144 error: error_msg,
1145 request_id: 0,
1146 };
1147 return Box::into_raw(Box::new(response));
1148 }
1149 };
1150 let client = client_wrapper.client.clone();
1151 if client.is_none() {
1152 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1153 let response = ListCollectionsResponseWrapper {
1154 success: false,
1155 results: std::ptr::null(),
1156 error: error_msg,
1157 request_id: 0,
1158 };
1159 return Box::into_raw(Box::new(response));
1160 }
1161 let client = client.unwrap();
1162 let result = tokio::task::block_in_place(|| {
1163 let handle = client.get_runtime_handle();
1164 handle.block_on(client.list_collections(includehist))
1165 });
1166
1167 let response = match result {
1168 Ok(data) => {
1169 let results = CString::new(data).unwrap().into_raw();
1170 ListCollectionsResponseWrapper {
1171 success: true,
1172 results,
1173 error: std::ptr::null(),
1174 request_id: 0,
1175 }
1176 }
1177 Err(e) => {
1178 let error_msg = CString::new(format!("List collections failed: {:?}", e))
1179 .unwrap()
1180 .into_raw();
1181 ListCollectionsResponseWrapper {
1182 success: false,
1183 results: std::ptr::null(),
1184 error: error_msg,
1185 request_id: 0,
1186 }
1187 }
1188 };
1189
1190 Box::into_raw(Box::new(response))
1191}
1192type ListCollectionsCallback = extern "C" fn(wrapper: *mut ListCollectionsResponseWrapper);
1193#[no_mangle]
1194#[tracing::instrument(skip_all)]
1195pub extern "C" fn list_collections_async(
1196 client: *mut ClientWrapper,
1197 includehist: bool,
1198 request_id: i32,
1199 callback: ListCollectionsCallback,
1200) {
1201 let client_wrapper = match safe_wrapper(client) {
1202 Some(client) => client,
1203 None => {
1204 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1205 let response = ListCollectionsResponseWrapper {
1206 success: false,
1207 results: std::ptr::null(),
1208 error: error_msg,
1209 request_id: request_id,
1210 };
1211 return callback(Box::into_raw(Box::new(response)));
1212 }
1213 };
1214 let client = client_wrapper.client.clone();
1215 if client.is_none() {
1216 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1217 let response = ListCollectionsResponseWrapper {
1218 success: false,
1219 results: std::ptr::null(),
1220 error: error_msg,
1221 request_id: request_id,
1222 };
1223 return callback(Box::into_raw(Box::new(response)));
1224 }
1225 let client = client.unwrap();
1226 let handle = client.get_runtime_handle();
1227 handle.spawn(async move {
1228 let result = client.list_collections(includehist).await;
1229
1230 let response = match result {
1231 Ok(data) => {
1232 let results = CString::new(data).unwrap().into_raw();
1233 ListCollectionsResponseWrapper {
1234 success: true,
1235 results,
1236 error: std::ptr::null(),
1237 request_id: request_id,
1238 }
1239 }
1240 Err(e) => {
1241 let error_msg = CString::new(format!("List collections failed: {:?}", e))
1242 .unwrap()
1243 .into_raw();
1244 ListCollectionsResponseWrapper {
1245 success: false,
1246 results: std::ptr::null(),
1247 error: error_msg,
1248 request_id: request_id,
1249 }
1250 }
1251 };
1252
1253 callback(Box::into_raw(Box::new(response)));
1254 });
1255}
1256#[no_mangle]
1257#[tracing::instrument(skip_all)]
1258pub extern "C" fn free_list_collections_response(response: *mut ListCollectionsResponseWrapper) {
1259 if response.is_null() {
1260 return;
1261 }
1262 unsafe {
1263 if !(*response).error.is_null() {
1264 let _ = CString::from_raw((*response).error as *mut c_char);
1265 }
1266 if !(*response).results.is_null() {
1267 let _ = CString::from_raw((*response).results as *mut c_char);
1268 }
1269 let _ = Box::from_raw(response);
1270 }
1271}
1272
1273#[repr(C)]
1274pub struct ColCollationWrapper {
1275 locale: *const c_char,
1276 case_level: bool,
1277 case_first: *const c_char,
1278 strength: i32,
1279 numeric_ordering: bool,
1280 alternate: *const c_char,
1281 max_variable: *const c_char,
1282 backwards: bool,
1283}
1284#[repr(C)]
1285pub struct ColTimeseriesWrapper {
1286 time_field: *const c_char,
1287 meta_field: *const c_char,
1288 granularity: *const c_char,
1289}
1290#[repr(C)]
1291pub struct CreateCollectionRequestWrapper {
1292 collectionname: *const c_char,
1293 collation: *mut ColCollationWrapper,
1294 timeseries: *mut ColTimeseriesWrapper,
1295 expire_after_seconds: i32,
1296 change_stream_pre_and_post_images: bool,
1297 capped: bool,
1298 max: i32,
1299 size: i32,
1300 request_id: i32,
1301}
1302#[repr(C)]
1303pub struct CreateCollectionResponseWrapper {
1304 success: bool,
1305 error: *const c_char,
1306 request_id: i32,
1307}
1308#[no_mangle]
1309#[tracing::instrument(skip_all)]
1310pub extern "C" fn create_collection(
1311 client: *mut ClientWrapper,
1312 options: *mut CreateCollectionRequestWrapper,
1313) -> *mut CreateCollectionResponseWrapper {
1314 let options = match safe_wrapper(options) {
1315 Some(options) => options,
1316 None => {
1317 let error_msg = CString::new("Invalid options").unwrap().into_raw();
1318 let response = CreateCollectionResponseWrapper {
1319 success: false,
1320 error: error_msg,
1321 request_id: 0,
1322 };
1323 return Box::into_raw(Box::new(response));
1324 }
1325 };
1326 let client_wrapper = match safe_wrapper(client) {
1327 Some(client) => client,
1328 None => {
1329 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1330 let response = CreateCollectionResponseWrapper {
1331 success: false,
1332 error: error_msg,
1333 request_id: options.request_id,
1334 };
1335 return Box::into_raw(Box::new(response));
1336 }
1337 };
1338 let client = client_wrapper.client.clone();
1339 let request = CreateCollectionRequest {
1340 collectionname: c_char_to_str(options.collectionname),
1341 collation: match safe_wrapper(options.collation) {
1342 Some(collation) => {
1343 Some(openiap_client::protos::ColCollation {
1344 locale: c_char_to_str(collation.locale),
1345 case_level: collation.case_level,
1346 case_first: c_char_to_str(collation.case_first),
1347 strength: collation.strength,
1348 numeric_ordering: collation.numeric_ordering,
1349 alternate: c_char_to_str(collation.alternate),
1350 max_variable: c_char_to_str(collation.max_variable),
1351 backwards: collation.backwards,
1352 })
1353 }
1354 None => None,
1355 },
1356 timeseries: match safe_wrapper(options.timeseries) {
1357 Some(timeseries) => {
1358 Some(openiap_client::protos::ColTimeseries {
1359 time_field: c_char_to_str(timeseries.time_field),
1360 meta_field: c_char_to_str(timeseries.meta_field),
1361 granularity: c_char_to_str(timeseries.granularity),
1362 })
1363 }
1364 None => None,
1365 },
1366 expire_after_seconds: options.expire_after_seconds,
1367 change_stream_pre_and_post_images: options.change_stream_pre_and_post_images,
1368 capped: options.capped,
1369 max: options.max,
1370 size: options.size,
1371 };
1372 if client.is_none() {
1373 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1374 let response = CreateCollectionResponseWrapper {
1375 success: false,
1376 error: error_msg,
1377 request_id: options.request_id,
1378 };
1379 return Box::into_raw(Box::new(response));
1380 }
1381 let client = client.unwrap();
1382 let result = tokio::task::block_in_place(|| {
1383 let handle = client.get_runtime_handle();
1384 handle.block_on(client.create_collection(request))
1385 });
1386
1387 let response = match result {
1388 Ok(_) => {
1389 CreateCollectionResponseWrapper {
1390 success: true,
1391 error: std::ptr::null(),
1392 request_id: options.request_id,
1393 }
1394 }
1395 Err(e) => {
1396 let error_msg = CString::new(format!("Create collection failed: {:?}", e))
1397 .unwrap()
1398 .into_raw();
1399 CreateCollectionResponseWrapper {
1400 success: false,
1401 error: error_msg,
1402 request_id: options.request_id,
1403 }
1404 }
1405 };
1406 Box::into_raw(Box::new(response))
1407}
1408type CreateCollectionCallback = extern "C" fn(wrapper: *mut CreateCollectionResponseWrapper);
1409#[no_mangle]
1410#[tracing::instrument(skip_all)]
1411pub extern "C" fn create_collection_async(
1412 client: *mut ClientWrapper,
1413 options: *mut CreateCollectionRequestWrapper,
1414 callback: CreateCollectionCallback,
1415) {
1416 let options = match safe_wrapper(options) {
1417 Some(options) => options,
1418 None => {
1419 let error_msg = CString::new("Invalid options").unwrap().into_raw();
1420 let response = CreateCollectionResponseWrapper {
1421 success: false,
1422 error: error_msg,
1423 request_id: 0,
1424 };
1425 return callback(Box::into_raw(Box::new(response)));
1426 }
1427 };
1428 let client_wrapper = match safe_wrapper(client) {
1429 Some(client) => client,
1430 None => {
1431 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1432 let response = CreateCollectionResponseWrapper {
1433 success: false,
1434 error: error_msg,
1435 request_id: options.request_id,
1436 };
1437 return callback(Box::into_raw(Box::new(response)));
1438 }
1439 };
1440 let client = client_wrapper.client.clone();
1441 let request = CreateCollectionRequest {
1442 collectionname: c_char_to_str(options.collectionname),
1443 collation: match safe_wrapper(options.collation) {
1444 Some(collation) => {
1445 Some(openiap_client::protos::ColCollation {
1446 locale: c_char_to_str(collation.locale),
1447 case_level: collation.case_level,
1448 case_first: c_char_to_str(collation.case_first),
1449 strength: collation.strength,
1450 numeric_ordering: collation.numeric_ordering,
1451 alternate: c_char_to_str(collation.alternate),
1452 max_variable: c_char_to_str(collation.max_variable),
1453 backwards: collation.backwards,
1454 })
1455 }
1456 None => None,
1457 },
1458 timeseries: match safe_wrapper(options.timeseries) {
1459 Some(timeseries) => {
1460 Some(openiap_client::protos::ColTimeseries {
1461 time_field: c_char_to_str(timeseries.time_field),
1462 meta_field: c_char_to_str(timeseries.meta_field),
1463 granularity: c_char_to_str(timeseries.granularity),
1464 })
1465 }
1466 None => None,
1467 },
1468 expire_after_seconds: options.expire_after_seconds,
1469 change_stream_pre_and_post_images: options.change_stream_pre_and_post_images,
1470 capped: options.capped,
1471 max: options.max,
1472 size: options.size,
1473 };
1474 if client.is_none() {
1475 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1476 let response = CreateCollectionResponseWrapper {
1477 success: false,
1478 error: error_msg,
1479 request_id: options.request_id,
1480 };
1481 return callback(Box::into_raw(Box::new(response)));
1482 }
1483 let client = client.unwrap();
1484 let handle = client.get_runtime_handle();
1485 let request_id = options.request_id;
1486 handle.spawn(async move {
1487 let result = client.create_collection(request).await;
1488
1489 let response = match result {
1490 Ok(_) => {
1491 CreateCollectionResponseWrapper {
1492 success: true,
1493 error: std::ptr::null(),
1494 request_id
1495 }
1496 }
1497 Err(e) => {
1498 let error_msg = CString::new(format!("Create collection failed: {:?}", e))
1499 .unwrap()
1500 .into_raw();
1501 CreateCollectionResponseWrapper {
1502 success: false,
1503 error: error_msg,
1504 request_id
1505 }
1506 }
1507 };
1508
1509 callback(Box::into_raw(Box::new(response)));
1510 });
1511}
1512#[no_mangle]
1513#[tracing::instrument(skip_all)]
1514pub extern "C" fn free_create_collection_response(response: *mut CreateCollectionResponseWrapper) {
1515 if response.is_null() {
1516 return;
1517 }
1518 unsafe {
1519 if !(*response).error.is_null() {
1520 let _ = CString::from_raw((*response).error as *mut c_char);
1521 }
1522 let _ = Box::from_raw(response);
1523 }
1524}
1525
1526#[repr(C)]
1527pub struct DropCollectionResponseWrapper {
1528 success: bool,
1529 error: *const c_char,
1530 request_id: i32,
1531}
1532#[no_mangle]
1533#[tracing::instrument(skip_all)]
1534pub extern "C" fn drop_collection(
1535 client: *mut ClientWrapper,
1536 collectionname: *const c_char,
1537) -> *mut DropCollectionResponseWrapper {
1538 let client_wrapper = match safe_wrapper(client) {
1539 Some(client) => client,
1540 None => {
1541 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1542 let response = DropCollectionResponseWrapper {
1543 success: false,
1544 error: error_msg,
1545 request_id: 0,
1546 };
1547 return Box::into_raw(Box::new(response));
1548 }
1549 };
1550 let client = client_wrapper.client.clone();
1551 let request = DropCollectionRequest {
1552 collectionname: c_char_to_str(collectionname),
1553 };
1554 if client.is_none() {
1555 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1556 let response = DropCollectionResponseWrapper {
1557 success: false,
1558 error: error_msg,
1559 request_id: 0,
1560 };
1561 return Box::into_raw(Box::new(response));
1562 }
1563 let client = client.unwrap();
1564 let result = tokio::task::block_in_place(|| {
1565 let handle = client.get_runtime_handle();
1566 handle.block_on(client.drop_collection(request))
1567 });
1568
1569 let response = match result {
1570 Ok(_) => {
1571 DropCollectionResponseWrapper {
1572 success: true,
1573 error: std::ptr::null(),
1574 request_id: 0,
1575 }
1576 }
1577 Err(e) => {
1578 let error_msg = CString::new(format!("Drop collection failed: {:?}", e))
1579 .unwrap()
1580 .into_raw();
1581 DropCollectionResponseWrapper {
1582 success: false,
1583 error: error_msg,
1584 request_id: 0,
1585 }
1586 }
1587 };
1588
1589 Box::into_raw(Box::new(response))
1590}
1591type DropCollectionCallback = extern "C" fn(wrapper: *mut DropCollectionResponseWrapper);
1592#[no_mangle]
1593#[tracing::instrument(skip_all)]
1594pub extern "C" fn drop_collection_async(
1595 client: *mut ClientWrapper,
1596 collectionname: *const c_char,
1597 request_id: i32,
1598 callback: DropCollectionCallback,
1599) {
1600 let client_wrapper = match safe_wrapper(client) {
1601 Some(client) => client,
1602 None => {
1603 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1604 let response = DropCollectionResponseWrapper {
1605 success: false,
1606 error: error_msg,
1607 request_id: request_id,
1608 };
1609 return callback(Box::into_raw(Box::new(response)));
1610 }
1611 };
1612 let client = client_wrapper.client.clone();
1613 let request = DropCollectionRequest {
1614 collectionname: c_char_to_str(collectionname),
1615 };
1616 if client.is_none() {
1617 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1618 let response = DropCollectionResponseWrapper {
1619 success: false,
1620 error: error_msg,
1621 request_id,
1622 };
1623 return callback(Box::into_raw(Box::new(response)));
1624 }
1625 let client = client.unwrap();
1626 let handle = client.get_runtime_handle();
1627 handle.spawn(async move {
1628 let result = client.drop_collection(request).await;
1629
1630 let response = match result {
1631 Ok(_) => {
1632 DropCollectionResponseWrapper {
1633 success: true,
1634 error: std::ptr::null(),
1635 request_id,
1636 }
1637 }
1638 Err(e) => {
1639 let error_msg = CString::new(format!("Drop collection failed: {:?}", e))
1640 .unwrap()
1641 .into_raw();
1642 DropCollectionResponseWrapper {
1643 success: false,
1644 error: error_msg,
1645 request_id,
1646 }
1647 }
1648 };
1649
1650 callback(Box::into_raw(Box::new(response)));
1651 });
1652}
1653#[no_mangle]
1654#[tracing::instrument(skip_all)]
1655pub extern "C" fn free_drop_collection_response(response: *mut DropCollectionResponseWrapper) {
1656 if response.is_null() {
1657 return;
1658 }
1659 unsafe {
1660 if !(*response).error.is_null() {
1661 let _ = CString::from_raw((*response).error as *mut c_char);
1662 }
1663 let _ = Box::from_raw(response);
1664 }
1665}
1666
1667#[repr(C)]
1668pub struct GetIndexesResponseWrapper {
1669 success: bool,
1670 results: *const c_char,
1671 error: *const c_char,
1672 request_id: i32,
1673}
1674#[no_mangle]
1675#[tracing::instrument(skip_all)]
1676pub extern "C" fn get_indexes(
1677 client: *mut ClientWrapper,
1678 collectionname: *const c_char,
1679) -> *mut GetIndexesResponseWrapper {
1680 let client_wrapper = match safe_wrapper(client) {
1681 Some(client) => client,
1682 None => {
1683 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1684 let response = GetIndexesResponseWrapper {
1685 success: false,
1686 results: std::ptr::null(),
1687 error: error_msg,
1688 request_id: 0,
1689 };
1690 return Box::into_raw(Box::new(response));
1691 }
1692 };
1693 let client = client_wrapper.client.clone();
1694 let request = GetIndexesRequest {
1695 collectionname: c_char_to_str(collectionname),
1696 };
1697 if client.is_none() {
1698 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1699 let response = GetIndexesResponseWrapper {
1700 success: false,
1701 results: std::ptr::null(),
1702 error: error_msg,
1703 request_id: 0,
1704 };
1705 return Box::into_raw(Box::new(response));
1706 }
1707 let client = client.unwrap();
1708 let result = tokio::task::block_in_place(|| {
1709 let handle = client.get_runtime_handle();
1710 handle.block_on(client.get_indexes(request))
1711 });
1712
1713 let response = match result {
1714 Ok(data) => {
1715 let results = CString::new(data).unwrap().into_raw();
1716 GetIndexesResponseWrapper {
1717 success: true,
1718 results,
1719 error: std::ptr::null(),
1720 request_id: 0,
1721 }
1722 }
1723 Err(e) => {
1724 let error_msg = CString::new(format!("Get indexes failed: {:?}", e))
1725 .unwrap()
1726 .into_raw();
1727 GetIndexesResponseWrapper {
1728 success: false,
1729 results: std::ptr::null(),
1730 error: error_msg,
1731 request_id: 0,
1732 }
1733 }
1734 };
1735
1736 Box::into_raw(Box::new(response))
1737}
1738type GetIndexesCallback = extern "C" fn(wrapper: *mut GetIndexesResponseWrapper);
1739#[no_mangle]
1740#[tracing::instrument(skip_all)]
1741pub extern "C" fn get_indexes_async(
1742 client: *mut ClientWrapper,
1743 collectionname: *const c_char,
1744 request_id: i32,
1745 callback: GetIndexesCallback,
1746) {
1747 let client_wrapper = match safe_wrapper(client) {
1748 Some(client) => client,
1749 None => {
1750 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1751 let response = GetIndexesResponseWrapper {
1752 success: false,
1753 results: std::ptr::null(),
1754 error: error_msg,
1755 request_id,
1756 };
1757 return callback(Box::into_raw(Box::new(response)));
1758 }
1759 };
1760 let client = client_wrapper.client.clone();
1761 let request = GetIndexesRequest {
1762 collectionname: c_char_to_str(collectionname),
1763 };
1764 if client.is_none() {
1765 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1766 let response = GetIndexesResponseWrapper {
1767 success: false,
1768 results: std::ptr::null(),
1769 error: error_msg,
1770 request_id,
1771 };
1772 return callback(Box::into_raw(Box::new(response)));
1773 }
1774 let client = client.unwrap();
1775 let handle = client.get_runtime_handle();
1776 handle.spawn(async move {
1777 let result = client.get_indexes(request).await;
1778
1779 let response = match result {
1780 Ok(data) => {
1781 let results = CString::new(data).unwrap().into_raw();
1782 GetIndexesResponseWrapper {
1783 success: true,
1784 results,
1785 error: std::ptr::null(),
1786 request_id,
1787 }
1788 }
1789 Err(e) => {
1790 let error_msg = CString::new(format!("Get indexes failed: {:?}", e))
1791 .unwrap()
1792 .into_raw();
1793 GetIndexesResponseWrapper {
1794 success: false,
1795 results: std::ptr::null(),
1796 error: error_msg,
1797 request_id,
1798 }
1799 }
1800 };
1801
1802 callback(Box::into_raw(Box::new(response)));
1803 });
1804
1805}
1806#[no_mangle]
1807#[tracing::instrument(skip_all)]
1808pub extern "C" fn free_get_indexes_response(response: *mut GetIndexesResponseWrapper) {
1809 if response.is_null() {
1810 return;
1811 }
1812 unsafe {
1813 if !(*response).error.is_null() {
1814 let _ = CString::from_raw((*response).error as *mut c_char);
1815 }
1816 if !(*response).results.is_null() {
1817 let _ = CString::from_raw((*response).results as *mut c_char);
1818 }
1819 let _ = Box::from_raw(response);
1820 }
1821}
1822
1823#[repr(C)]
1824pub struct CreateIndexRequestWrapper {
1825 collectionname: *const c_char,
1826 index: *const c_char,
1827 options: *const c_char,
1828 name: *const c_char,
1829 request_id: i32,
1830}
1831#[repr(C)]
1832pub struct CreateIndexResponseWrapper {
1833 success: bool,
1834 error: *const c_char,
1835 request_id: i32,
1836}
1837#[no_mangle]
1838#[tracing::instrument(skip_all)]
1839pub extern "C" fn create_index(
1840 client: *mut ClientWrapper,
1841 options: *mut CreateIndexRequestWrapper,
1842) -> *mut CreateIndexResponseWrapper {
1843 let options = match safe_wrapper(options) {
1844 Some(options) => options,
1845 None => {
1846 let error_msg = CString::new("Invalid options").unwrap().into_raw();
1847 let response = CreateIndexResponseWrapper {
1848 success: false,
1849 error: error_msg,
1850 request_id: 0,
1851 };
1852 return Box::into_raw(Box::new(response));
1853 }
1854 };
1855 let client_wrapper = match safe_wrapper(client) {
1856 Some(client) => client,
1857 None => {
1858 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1859 let response = CreateIndexResponseWrapper {
1860 success: false,
1861 error: error_msg,
1862 request_id: options.request_id,
1863 };
1864 return Box::into_raw(Box::new(response));
1865 }
1866 };
1867 let client = client_wrapper.client.clone();
1868 let request = CreateIndexRequest {
1869 collectionname: c_char_to_str(options.collectionname),
1870 index: c_char_to_str(options.index),
1871 options: c_char_to_str(options.options),
1872 name: c_char_to_str(options.name),
1873 };
1874 if client.is_none() {
1875 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1876 let response = CreateIndexResponseWrapper {
1877 success: false,
1878 error: error_msg,
1879 request_id: options.request_id,
1880 };
1881 return Box::into_raw(Box::new(response));
1882 }
1883 let client = client.unwrap();
1884 let result = tokio::task::block_in_place(|| {
1885 let handle = client.get_runtime_handle();
1886 handle.block_on(client.create_index(request))
1887 });
1888
1889 let response = match result {
1890 Ok(_) => {
1891 CreateIndexResponseWrapper {
1892 success: true,
1893 error: std::ptr::null(),
1894 request_id: options.request_id,
1895 }
1896 }
1897 Err(e) => {
1898 let error_msg = CString::new(format!("Create index failed: {:?}", e))
1899 .unwrap()
1900 .into_raw();
1901 CreateIndexResponseWrapper {
1902 success: false,
1903 error: error_msg,
1904 request_id: options.request_id,
1905 }
1906 }
1907 };
1908
1909 Box::into_raw(Box::new(response))
1910}
1911type CreateIndexCallback = extern "C" fn(wrapper: *mut CreateIndexResponseWrapper);
1912#[no_mangle]
1913#[tracing::instrument(skip_all)]
1914pub extern "C" fn create_index_async(
1915 client: *mut ClientWrapper,
1916 options: *mut CreateIndexRequestWrapper,
1917 callback: CreateIndexCallback,
1918) {
1919 let options = match safe_wrapper(options) {
1920 Some(options) => options,
1921 None => {
1922 let error_msg = CString::new("Invalid options").unwrap().into_raw();
1923 let response = CreateIndexResponseWrapper {
1924 success: false,
1925 error: error_msg,
1926 request_id: 0,
1927 };
1928 return callback(Box::into_raw(Box::new(response)));
1929 }
1930 };
1931 let client_wrapper = match safe_wrapper(client) {
1932 Some(client) => client,
1933 None => {
1934 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1935 let response = CreateIndexResponseWrapper {
1936 success: false,
1937 error: error_msg,
1938 request_id: options.request_id,
1939 };
1940 return callback(Box::into_raw(Box::new(response)));
1941 }
1942 };
1943 let client = client_wrapper.client.clone();
1944 let request = CreateIndexRequest {
1945 collectionname: c_char_to_str(options.collectionname),
1946 index: c_char_to_str(options.index),
1947 options: c_char_to_str(options.options),
1948 name: c_char_to_str(options.name),
1949 };
1950 if client.is_none() {
1951 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
1952 let response = CreateIndexResponseWrapper {
1953 success: false,
1954 error: error_msg,
1955 request_id: options.request_id,
1956 };
1957 return callback(Box::into_raw(Box::new(response)));
1958 }
1959 let client = client.unwrap();
1960 let handle = client.get_runtime_handle();
1961 let request_id = options.request_id;
1962 handle.spawn(async move {
1963 let result = client.create_index(request).await;
1964
1965 let response = match result {
1966 Ok(_) => {
1967 CreateIndexResponseWrapper {
1968 success: true,
1969 error: std::ptr::null(),
1970 request_id
1971 }
1972 }
1973 Err(e) => {
1974 let error_msg = CString::new(format!("Create index failed: {:?}", e))
1975 .unwrap()
1976 .into_raw();
1977 CreateIndexResponseWrapper {
1978 success: false,
1979 error: error_msg,
1980 request_id
1981 }
1982 }
1983 };
1984
1985 callback(Box::into_raw(Box::new(response)));
1986 });
1987}
1988#[no_mangle]
1989#[tracing::instrument(skip_all)]
1990pub extern "C" fn free_create_index_response(response: *mut CreateIndexResponseWrapper) {
1991 if response.is_null() {
1992 return;
1993 }
1994 unsafe {
1995 if !(*response).error.is_null() {
1996 let _ = CString::from_raw((*response).error as *mut c_char);
1997 }
1998 let _ = Box::from_raw(response);
1999 }
2000}
2001
2002#[repr(C)]
2003pub struct DropIndexResponseWrapper {
2004 success: bool,
2005 error: *const c_char,
2006 request_id: i32,
2007}
2008#[no_mangle]
2009#[tracing::instrument(skip_all)]
2010pub extern "C" fn drop_index(
2011 client: *mut ClientWrapper,
2012 collectionname: *const c_char,
2013 name: *const c_char,
2014) -> *mut DropIndexResponseWrapper {
2015 let client_wrapper = match safe_wrapper(client) {
2016 Some(client) => client,
2017 None => {
2018 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2019 let response = DropIndexResponseWrapper {
2020 success: false,
2021 error: error_msg,
2022 request_id: 0,
2023 };
2024 return Box::into_raw(Box::new(response));
2025 }
2026 };
2027 let client = client_wrapper.client.clone();
2028 let request = DropIndexRequest {
2029 collectionname: c_char_to_str(collectionname),
2030 name: c_char_to_str(name),
2031 };
2032 if client.is_none() {
2033 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2034 let response = DropIndexResponseWrapper {
2035 success: false,
2036 error: error_msg,
2037 request_id: 0,
2038 };
2039 return Box::into_raw(Box::new(response));
2040 }
2041 let client = client.unwrap();
2042 let result = tokio::task::block_in_place(|| {
2043 let handle = client.get_runtime_handle();
2044 handle.block_on(client.drop_index(request))
2045 });
2046
2047 let response = match result {
2048 Ok(_) => {
2049 DropIndexResponseWrapper {
2050 success: true,
2051 error: std::ptr::null(),
2052 request_id: 0,
2053 }
2054 }
2055 Err(e) => {
2056 let error_msg = CString::new(format!("Drop index failed: {:?}", e))
2057 .unwrap()
2058 .into_raw();
2059 DropIndexResponseWrapper {
2060 success: false,
2061 error: error_msg,
2062 request_id: 0,
2063 }
2064 }
2065 };
2066
2067 Box::into_raw(Box::new(response))
2068}
2069type DropIndexCallback = extern "C" fn(wrapper: *mut DropIndexResponseWrapper);
2070#[no_mangle]
2071#[tracing::instrument(skip_all)]
2072pub extern "C" fn drop_index_async(
2073 client: *mut ClientWrapper,
2074 collectionname: *const c_char,
2075 name: *const c_char,
2076 request_id: i32,
2077 callback: DropIndexCallback,
2078) {
2079 let client_wrapper = match safe_wrapper(client) {
2080 Some(client) => client,
2081 None => {
2082 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2083 let response = DropIndexResponseWrapper {
2084 success: false,
2085 error: error_msg,
2086 request_id
2087 };
2088 return callback(Box::into_raw(Box::new(response)));
2089 }
2090 };
2091 let client = client_wrapper.client.clone();
2092 let request = DropIndexRequest {
2093 collectionname: c_char_to_str(collectionname),
2094 name: c_char_to_str(name),
2095 };
2096 if client.is_none() {
2097 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2098 let response = DropIndexResponseWrapper {
2099 success: false,
2100 error: error_msg,
2101 request_id
2102 };
2103 return callback(Box::into_raw(Box::new(response)));
2104 }
2105 let client = client.unwrap();
2106 let handle = client.get_runtime_handle();
2107 handle.spawn(async move {
2108 let result = client.drop_index(request).await;
2109
2110 let response = match result {
2111 Ok(_) => {
2112 DropIndexResponseWrapper {
2113 success: true,
2114 error: std::ptr::null(),
2115 request_id
2116 }
2117 }
2118 Err(e) => {
2119 let error_msg = CString::new(format!("Drop index failed: {:?}", e))
2120 .unwrap()
2121 .into_raw();
2122 DropIndexResponseWrapper {
2123 success: false,
2124 error: error_msg,
2125 request_id
2126 }
2127 }
2128 };
2129
2130 callback(Box::into_raw(Box::new(response)));
2131 });
2132}
2133#[no_mangle]
2134#[tracing::instrument(skip_all)]
2135pub extern "C" fn free_drop_index_response(response: *mut DropIndexResponseWrapper) {
2136 if response.is_null() {
2137 return;
2138 }
2139 unsafe {
2140 if !(*response).error.is_null() {
2141 let _ = CString::from_raw((*response).error as *mut c_char);
2142 }
2143 let _ = Box::from_raw(response);
2144 }
2145}
2146
2147#[repr(C)]
2148pub struct AggregateRequestWrapper {
2149 collectionname: *const c_char,
2150 aggregates: *const c_char,
2151 queryas: *const c_char,
2152 hint: *const c_char,
2153 explain: bool,
2154 request_id: i32
2155}
2156#[repr(C)]
2157pub struct AggregateResponseWrapper {
2158 success: bool,
2159 results: *const c_char,
2160 error: *const c_char,
2161 request_id: i32
2162}
2163#[no_mangle]
2164#[tracing::instrument(skip_all)]
2165pub extern "C" fn aggregate(
2166 client: *mut ClientWrapper,
2167 options: *mut AggregateRequestWrapper,
2168) -> *mut AggregateResponseWrapper {
2169 let options = match safe_wrapper(options) {
2170 Some(options) => options,
2171 None => {
2172 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2173 let response = AggregateResponseWrapper {
2174 success: false,
2175 results: std::ptr::null(),
2176 error: error_msg,
2177 request_id: 0,
2178 };
2179 return Box::into_raw(Box::new(response));
2180 }
2181 };
2182 let client_wrapper = match safe_wrapper(client ) {
2183 Some(client) => client,
2184 None => {
2185 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2186 let response = AggregateResponseWrapper {
2187 success: false,
2188 results: std::ptr::null(),
2189 error: error_msg,
2190 request_id: options.request_id,
2191 };
2192 return Box::into_raw(Box::new(response));
2193 }
2194 };
2195 let client = client_wrapper.client.clone();
2196 let request = AggregateRequest {
2197 collectionname: c_char_to_str(options.collectionname),
2198 aggregates: c_char_to_str(options.aggregates),
2199 queryas: c_char_to_str(options.queryas),
2200 hint: c_char_to_str(options.hint),
2201 explain: options.explain
2202 };
2203 if client.is_none() {
2204 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2205 let response = AggregateResponseWrapper {
2206 success: false,
2207 results: std::ptr::null(),
2208 error: error_msg,
2209 request_id: options.request_id,
2210 };
2211 return Box::into_raw(Box::new(response));
2212 }
2213 let client = client.unwrap();
2214 let result = tokio::task::block_in_place(|| {
2215 let handle = client.get_runtime_handle();
2216 handle.block_on(client.aggregate(request))
2217 });
2218
2219 let response = match result {
2220 Ok(data) => {
2221 let results = CString::new(data.results).unwrap().into_raw();
2222 AggregateResponseWrapper {
2223 success: true,
2224 results,
2225 error: std::ptr::null(),
2226 request_id: options.request_id,
2227 }
2228 }
2229 Err(e) => {
2230 let error_msg = CString::new(format!("Aggregate failed: {:?}", e))
2231 .unwrap()
2232 .into_raw();
2233 AggregateResponseWrapper {
2234 success: false,
2235 results: std::ptr::null(),
2236 error: error_msg,
2237 request_id: options.request_id,
2238 }
2239 }
2240 };
2241
2242 Box::into_raw(Box::new(response))
2243}
2244
2245type AggregateCallback = extern "C" fn(wrapper: *mut AggregateResponseWrapper);
2246#[no_mangle]
2247#[tracing::instrument(skip_all)]
2248pub extern "C" fn aggregate_async(
2249 client: *mut ClientWrapper,
2250 options: *mut AggregateRequestWrapper,
2251 callback: AggregateCallback,
2252) {
2253 debug!("Rust: aggregate_async");
2254 let options = match safe_wrapper(options ) {
2255 Some( options ) => options,
2256 None => {
2257 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2258 let response = AggregateResponseWrapper {
2259 success: false,
2260 results: std::ptr::null(),
2261 error: error_msg,
2262 request_id: 0,
2263 };
2264 return callback(Box::into_raw(Box::new(response)));
2265 }
2266 };
2267 let client_wrapper = match safe_wrapper(client) {
2268 Some( client ) => client,
2269 None => {
2270 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2271 let response = AggregateResponseWrapper {
2272 success: false,
2273 results: std::ptr::null(),
2274 error: error_msg,
2275 request_id: options.request_id,
2276 };
2277 return callback(Box::into_raw(Box::new(response)));
2278 }
2279 };
2280 let client = client_wrapper.client.clone();
2281 let request = AggregateRequest {
2282 collectionname: c_char_to_str(options.collectionname),
2283 aggregates: c_char_to_str(options.aggregates),
2284 queryas: c_char_to_str(options.queryas),
2285 hint: c_char_to_str(options.hint),
2286 explain: options.explain
2287 };
2288 if client.is_none() {
2289 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2290 let response = AggregateResponseWrapper {
2291 success: false,
2292 results: std::ptr::null(),
2293 error: error_msg,
2294 request_id: options.request_id,
2295 };
2296 return callback(Box::into_raw(Box::new(response)));
2297 }
2298
2299 let client = client.unwrap();
2300 let handle = client.get_runtime_handle();
2301 let request_id = options.request_id;
2302 debug!("Rust: runtime.spawn");
2303 handle.spawn(async move {
2304 debug!("Rust: client.aggregate");
2305 let result = client.aggregate(request).await;
2306 let response = match result {
2307 Ok(data) => {
2308 let results = CString::new(data.results).unwrap().into_raw();
2309 AggregateResponseWrapper {
2310 success: true,
2311 results,
2312 error: std::ptr::null(),
2313 request_id,
2314 }
2315 }
2316 Err(e) => {
2317 let error_msg = CString::new(format!("Aggregate failed: {:?}", e))
2318 .unwrap()
2319 .into_raw();
2320 AggregateResponseWrapper {
2321 success: false,
2322 results: std::ptr::null(),
2323 error: error_msg,
2324 request_id,
2325 }
2326 }
2327 };
2328 debug!("Rust: callback response");
2329 callback(Box::into_raw(Box::new(response)));
2330 });
2331}
2332#[no_mangle]
2333#[tracing::instrument(skip_all)]
2334pub extern "C" fn free_aggregate_response(response: *mut AggregateResponseWrapper) {
2335 if response.is_null() {
2336 return;
2337 }
2338 unsafe {
2339 if !(*response).error.is_null() {
2340 let _ = CString::from_raw((*response).error as *mut c_char);
2341 }
2342 if !(*response).results.is_null() {
2343 let _ = CString::from_raw((*response).results as *mut c_char);
2344 }
2345 let _ = Box::from_raw(response);
2346 }
2347}
2348
2349#[repr(C)]
2350pub struct CountRequestWrapper {
2351 collectionname: *const c_char,
2352 query: *const c_char,
2353 queryas: *const c_char,
2354 explain: bool,
2355 request_id: i32
2356}
2357#[repr(C)]
2358pub struct CountResponseWrapper {
2359 success: bool,
2360 result: i32,
2361 error: *const c_char,
2362 request_id: i32
2363}
2364#[no_mangle]
2365#[tracing::instrument(skip_all)]
2366pub extern "C" fn count(
2367 client: *mut ClientWrapper,
2368 options: *mut CountRequestWrapper,
2369) -> *mut CountResponseWrapper {
2370 let options = match safe_wrapper(options) {
2371 Some(options) => options,
2372 None => {
2373 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2374 let response = CountResponseWrapper {
2375 success: false,
2376 result: 0,
2377 error: error_msg,
2378 request_id: 0,
2379 };
2380 return Box::into_raw(Box::new(response));
2381 }
2382 };
2383 let client_wrapper = match safe_wrapper(client) {
2384 Some(client) => client,
2385 None => {
2386 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2387 let response = CountResponseWrapper {
2388 success: false,
2389 result: 0,
2390 error: error_msg,
2391 request_id: options.request_id,
2392 };
2393 return Box::into_raw(Box::new(response));
2394 }
2395 };
2396 let client = client_wrapper.client.clone();
2397 let request = CountRequest {
2398 collectionname: c_char_to_str(options.collectionname),
2399 query: c_char_to_str(options.query),
2400 queryas: c_char_to_str(options.queryas),
2401 explain: options.explain
2402 };
2403 if client.is_none() {
2404 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2405 let response = CountResponseWrapper {
2406 success: false,
2407 result: 0,
2408 error: error_msg,
2409 request_id: options.request_id,
2410 };
2411 return Box::into_raw(Box::new(response));
2412 }
2413
2414 let client = client.unwrap();
2415 let result = tokio::task::block_in_place(|| {
2416 let handle = client.get_runtime_handle();
2417 handle.block_on(client.count(request))
2418 });
2419
2420 let response = match result {
2421 Ok(data) => {
2422 let result = data.result;
2423 CountResponseWrapper {
2424 success: true,
2425 result,
2426 error: std::ptr::null(),
2427 request_id: options.request_id,
2428 }
2429 }
2430 Err(e) => {
2431 let error_msg = CString::new(format!("Count failed: {:?}", e))
2432 .unwrap()
2433 .into_raw();
2434 CountResponseWrapper {
2435 success: false,
2436 result: 0,
2437 error: error_msg,
2438 request_id: options.request_id,
2439 }
2440 }
2441 };
2442
2443 Box::into_raw(Box::new(response))
2444}
2445
2446type CountCallback = extern "C" fn(wrapper: *mut CountResponseWrapper);
2447#[no_mangle]
2448#[tracing::instrument(skip_all)]
2449pub extern "C" fn count_async(
2450 client: *mut ClientWrapper,
2451 options: *mut CountRequestWrapper,
2452 callback: CountCallback,
2453) {
2454 let options = match safe_wrapper(options) {
2455 Some(options) => options,
2456 None => {
2457 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2458 let response = CountResponseWrapper {
2459 success: false,
2460 result: 0,
2461 error: error_msg,
2462 request_id: 0,
2463 };
2464 return callback(Box::into_raw(Box::new(response)));
2465 }
2466 };
2467 let client_wrapper = match safe_wrapper(client) {
2468 Some(client) => client,
2469 None => {
2470 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2471 let response = CountResponseWrapper {
2472 success: false,
2473 result: 0,
2474 error: error_msg,
2475 request_id: options.request_id,
2476 };
2477 return callback(Box::into_raw(Box::new(response)));
2478 }
2479 };
2480 let client = client_wrapper.client.clone();
2481 let request = CountRequest {
2482 collectionname: c_char_to_str(options.collectionname),
2483 query: c_char_to_str(options.query),
2484 queryas: c_char_to_str(options.queryas),
2485 explain: options.explain
2486 };
2487 if client.is_none() {
2488 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2489 let response = CountResponseWrapper {
2490 success: false,
2491 result: 0,
2492 error: error_msg,
2493 request_id: options.request_id,
2494 };
2495 return callback(Box::into_raw(Box::new(response)));
2496 }
2497 let client = client.unwrap();
2498 let handle = client.get_runtime_handle();
2499 let request_id = options.request_id;
2500 handle.spawn(async move {
2501 let result = client.count(request).await;
2502 let response = match result {
2503 Ok(data) => {
2504 let result = data.result;
2505 CountResponseWrapper {
2506 success: true,
2507 result,
2508 error: std::ptr::null(),
2509 request_id,
2510 }
2511 }
2512 Err(e) => {
2513 let error_msg = CString::new(format!("Count failed: {:?}", e))
2514 .unwrap()
2515 .into_raw();
2516 CountResponseWrapper {
2517 success: false,
2518 result: 0,
2519 error: error_msg,
2520 request_id,
2521 }
2522 }
2523 };
2524
2525 callback(Box::into_raw(Box::new(response)));
2526 });
2527}
2528#[no_mangle]
2529#[tracing::instrument(skip_all)]
2530pub extern "C" fn free_count_response(response: *mut CountResponseWrapper) {
2531 if response.is_null() {
2532 return;
2533 }
2534 unsafe {
2535 if !(*response).error.is_null() {
2536 let _ = CString::from_raw((*response).error as *mut c_char);
2537 }
2538 let _ = Box::from_raw(response);
2539 }
2540}
2541
2542#[repr(C)]
2543pub struct DistinctRequestWrapper {
2544 collectionname: *const c_char,
2545 field: *const c_char,
2546 query: *const c_char,
2547 queryas: *const c_char,
2548 explain: bool,
2549 request_id: i32
2550}
2551#[repr(C)]
2552pub struct DistinctResponseWrapper {
2553 success: bool,
2554 results: *mut *const c_char,
2556 error: *const c_char,
2557 results_len: i32,
2558 request_id: i32
2559}
2560#[no_mangle]
2561#[tracing::instrument(skip_all)]
2562pub extern "C" fn distinct(
2563 client: *mut ClientWrapper,
2564 options: *mut DistinctRequestWrapper,
2565) -> *mut DistinctResponseWrapper {
2566 let options = match safe_wrapper(options) {
2567 Some(options) => options,
2568 None => {
2569 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2570 let response = DistinctResponseWrapper {
2571 success: false,
2572 results: std::ptr::null_mut(),
2573 error: error_msg,
2574 results_len: 0,
2575 request_id: 0,
2576 };
2577 return Box::into_raw(Box::new(response));
2578 }
2579 };
2580 let client_wrapper = match safe_wrapper(client) {
2581 Some(client) => client,
2582 None => {
2583 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2584 let response = DistinctResponseWrapper {
2585 success: false,
2586 results: std::ptr::null_mut(),
2587 error: error_msg,
2588 results_len: 0,
2589 request_id: options.request_id,
2590 };
2591 return Box::into_raw(Box::new(response));
2592 }
2593 };
2594 let client = client_wrapper.client.clone();
2595 let request = DistinctRequest {
2596 collectionname: c_char_to_str(options.collectionname),
2597 field: c_char_to_str(options.field),
2598 query: c_char_to_str(options.query),
2599 queryas: c_char_to_str(options.queryas),
2600 explain: options.explain,
2601 ..Default::default()
2602 };
2603 if client.is_none() {
2604 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2605 let response = DistinctResponseWrapper {
2606 success: false,
2607 results: std::ptr::null_mut(),
2608 error: error_msg,
2609 results_len: 0,
2610 request_id: options.request_id,
2611 };
2612 return Box::into_raw(Box::new(response));
2613 }
2614 let client = client.unwrap();
2615 let result = tokio::task::block_in_place(|| {
2616 let handle = client.get_runtime_handle();
2617 handle.block_on( client.distinct(request))
2618 });
2619
2620 let response = match result {
2621 Ok(data) => {
2622 let results_cstrings: Vec<CString> = data
2623 .results
2624 .iter()
2625 .map(|s| CString::new(s.as_str()).unwrap())
2626 .collect();
2627 let results_ptrs: Vec<*const c_char> =
2628 results_cstrings.iter().map(|s| s.as_ptr()).collect();
2629 let results_array =
2630 Box::into_raw(results_ptrs.clone().into_boxed_slice()) as *mut *const c_char;
2631
2632 std::mem::forget(results_cstrings);
2633
2634 DistinctResponseWrapper {
2635 success: true,
2636 results: results_array,
2637 error: std::ptr::null(),
2638 results_len: data.results.len().try_into().unwrap(),
2639 request_id: options.request_id,
2640 }
2641 }
2642 Err(e) => {
2643 let error_msg = CString::new(format!("Distinct failed: {:?}", e))
2644 .unwrap()
2645 .into_raw();
2646 DistinctResponseWrapper {
2647 success: false,
2648 results: std::ptr::null_mut(),
2649 error: error_msg,
2650 results_len: 0,
2651 request_id: options.request_id,
2652 }
2653 }
2654 };
2655
2656 Box::into_raw(Box::new(response))
2657}
2658
2659type DistinctCallback = extern "C" fn(wrapper: *mut DistinctResponseWrapper);
2660#[no_mangle]
2661#[tracing::instrument(skip_all)]
2662pub extern "C" fn distinct_async(
2663 client: *mut ClientWrapper,
2664 options: *mut DistinctRequestWrapper,
2665 callback: DistinctCallback,
2666) {
2667 let options = match safe_wrapper(options) {
2668 Some(options) => options,
2669 None => {
2670 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2671 let response = DistinctResponseWrapper {
2672 success: false,
2673 results: std::ptr::null_mut(),
2674 error: error_msg,
2675 results_len: 0,
2676 request_id: 0,
2677 };
2678 return callback(Box::into_raw(Box::new(response)));
2679 }
2680 };
2681 let client_wrapper = match safe_wrapper(client) {
2682 Some(client) => client,
2683 None => {
2684 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2685 let response = DistinctResponseWrapper {
2686 success: false,
2687 results: std::ptr::null_mut(),
2688 error: error_msg,
2689 results_len: 0,
2690 request_id: options.request_id,
2691 };
2692 return callback(Box::into_raw(Box::new(response)));
2693 }
2694 };
2695 let client = client_wrapper.client.clone();
2696 let request = DistinctRequest {
2697 collectionname: c_char_to_str(options.collectionname),
2698 field: c_char_to_str(options.field),
2699 query: c_char_to_str(options.query),
2700 queryas: c_char_to_str(options.queryas),
2701 explain: options.explain,
2702 ..Default::default()
2703 };
2704 if client.is_none() {
2705 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2706 let response = DistinctResponseWrapper {
2707 success: false,
2708 results: std::ptr::null_mut(),
2709 error: error_msg,
2710 results_len: 0,
2711 request_id: options.request_id,
2712 };
2713 return callback(Box::into_raw(Box::new(response)));
2714 }
2715 let client = client.unwrap();
2716 let handle = client.get_runtime_handle();
2717 let request_id = options.request_id;
2718 handle.spawn(async move {
2719 let result = client.distinct(request).await;
2720 let response = match result {
2721 Ok(data) => {
2722 let results_cstrings: Vec<CString> = data
2723 .results
2724 .iter()
2725 .map(|s| CString::new(s.as_str()).unwrap())
2726 .collect();
2727 let results_ptrs: Vec<*const c_char> =
2728 results_cstrings.iter().map(|s| s.as_ptr()).collect();
2729 let results_array =
2730 Box::into_raw(results_ptrs.clone().into_boxed_slice()) as *mut *const c_char;
2731
2732 std::mem::forget(results_cstrings);
2733
2734 debug!("Rust: results_array: {:?}", results_array);
2735 for (i, ptr) in results_ptrs.iter().enumerate() {
2736 debug!("Rust: results_ptrs[{}]: {:?}: {:?}", i, ptr, unsafe {
2737 CStr::from_ptr(*ptr).to_str().unwrap()
2738 });
2739 }
2740
2741 DistinctResponseWrapper {
2742 success: true,
2743 results: results_array,
2744 error: std::ptr::null(),
2745 results_len: data.results.len().try_into().unwrap(),
2746 request_id,
2747 }
2748 }
2749 Err(e) => {
2750 let error_msg = CString::new(format!("Distinct failed: {:?}", e))
2751 .unwrap()
2752 .into_raw();
2753 DistinctResponseWrapper {
2754 success: false,
2755 results: std::ptr::null_mut(),
2756 error: error_msg,
2757 results_len: 0,
2758 request_id,
2759 }
2760 }
2761 };
2762
2763 callback(Box::into_raw(Box::new(response)));
2764 });
2765}
2766#[no_mangle]
2767#[tracing::instrument(skip_all)]
2768pub extern "C" fn free_distinct_response(response: *mut DistinctResponseWrapper) {
2769 if response.is_null() {
2770 return;
2771 }
2772 unsafe {
2773 if !(*response).results.is_null() {
2774 for i in 0..(*response).results_len {
2775 let c_str_ptr = *(*response).results.add(i as usize);
2776 if !c_str_ptr.is_null() {
2777 let _ = CString::from_raw(c_str_ptr as *mut c_char); }
2779 }
2780 let _ = Box::from_raw((*response).results);
2781 }
2782
2783 if !(*response).error.is_null() {
2784 let _ = CString::from_raw((*response).error as *mut c_char);
2785 }
2786 let _ = Box::from_raw(response);
2787 }
2788}
2789#[repr(C)]
2790pub struct InsertOneRequestWrapper {
2791 collectionname: *const c_char,
2792 item: *const c_char,
2793 w: i32,
2794 j: bool,
2795 request_id: i32
2796}
2797#[repr(C)]
2798pub struct InsertOneResponseWrapper {
2799 success: bool,
2800 result: *const c_char,
2801 error: *const c_char,
2802 request_id: i32
2803}
2804#[no_mangle]
2805#[tracing::instrument(skip_all)]
2806pub extern "C" fn insert_one(
2807 client: *mut ClientWrapper,
2808 options: *mut InsertOneRequestWrapper,
2809) -> *mut InsertOneResponseWrapper {
2810 let options = match safe_wrapper(options) {
2811 Some(options) => options,
2812 None => {
2813 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2814 let response = InsertOneResponseWrapper {
2815 success: false,
2816 result: std::ptr::null(),
2817 error: error_msg,
2818 request_id: 0,
2819 };
2820 return Box::into_raw(Box::new(response));
2821 }
2822 };
2823 let client_wrapper = match safe_wrapper(client) {
2824 Some(client) => client,
2825 None => {
2826 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2827 let response = InsertOneResponseWrapper {
2828 success: false,
2829 result: std::ptr::null(),
2830 error: error_msg,
2831 request_id: options.request_id,
2832 };
2833 return Box::into_raw(Box::new(response));
2834 }
2835 };
2836 let client = client_wrapper.client.clone();
2837 let request = InsertOneRequest {
2838 collectionname: c_char_to_str(options.collectionname),
2839 item: c_char_to_str(options.item),
2840 w: options.w,
2841 j: options.j,
2842 };
2843 if client.is_none() {
2844 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2845 let response = InsertOneResponseWrapper {
2846 success: false,
2847 result: std::ptr::null(),
2848 error: error_msg,
2849 request_id: options.request_id,
2850 };
2851 return Box::into_raw(Box::new(response));
2852 }
2853 let client = client.unwrap();
2854 let result = tokio::task::block_in_place(|| {
2855 let handle = client.get_runtime_handle();
2856 handle.block_on( client.insert_one(request))
2857 });
2858
2859 let response = match result {
2860 Ok(data) => {
2861 let result = CString::new(data.result).unwrap().into_raw();
2862 InsertOneResponseWrapper {
2863 success: true,
2864 result,
2865 error: std::ptr::null(),
2866 request_id: options.request_id,
2867 }
2868 }
2869 Err(e) => {
2870 let error_msg = CString::new(format!("InsertOne failed: {:?}", e))
2871 .unwrap()
2872 .into_raw();
2873 InsertOneResponseWrapper {
2874 success: false,
2875 result: std::ptr::null(),
2876 error: error_msg,
2877 request_id: options.request_id,
2878 }
2879 }
2880 };
2881
2882 Box::into_raw(Box::new(response))
2883}
2884
2885type InsertOneCallback = extern "C" fn(wrapper: *mut InsertOneResponseWrapper);
2886#[no_mangle]
2887#[tracing::instrument(skip_all)]
2888pub extern "C" fn insert_one_async(
2889 client: *mut ClientWrapper,
2890 options: *mut InsertOneRequestWrapper,
2891 callback: InsertOneCallback,
2892) {
2893 let options = match safe_wrapper(options) {
2894 Some(options) => options,
2895 None => {
2896 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2897 let response = InsertOneResponseWrapper {
2898 success: false,
2899 result: std::ptr::null(),
2900 error: error_msg,
2901 request_id: 0,
2902 };
2903 return callback(Box::into_raw(Box::new(response)));
2904 }
2905 };
2906 let client_wrapper = match safe_wrapper(client) {
2907 Some(client) => client,
2908 None => {
2909 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2910 let response = InsertOneResponseWrapper {
2911 success: false,
2912 result: std::ptr::null(),
2913 error: error_msg,
2914 request_id: options.request_id,
2915 };
2916 return callback(Box::into_raw(Box::new(response)));
2917 }
2918 };
2919 let client = client_wrapper.client.clone();
2920 let request = InsertOneRequest {
2921 collectionname: c_char_to_str(options.collectionname),
2922 item: c_char_to_str(options.item),
2923 w: options.w,
2924 j: options.j,
2925 };
2926 if client.is_none() {
2927 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2928 let response = InsertOneResponseWrapper {
2929 success: false,
2930 result: std::ptr::null(),
2931 error: error_msg,
2932 request_id: options.request_id,
2933 };
2934 return callback(Box::into_raw(Box::new(response)));
2935 }
2936
2937 let client = client.unwrap();
2938 let handle = client.get_runtime_handle();
2939 let request_id = options.request_id;
2940 handle.spawn(async move {
2941 let result = client.insert_one(request).await;
2942 let response = match result {
2943 Ok(data) => {
2944 let result = CString::new(data.result).unwrap().into_raw();
2945 InsertOneResponseWrapper {
2946 success: true,
2947 result,
2948 error: std::ptr::null(),
2949 request_id,
2950 }
2951 }
2952 Err(e) => {
2953 let error_msg = CString::new(format!("InsertOne failed: {:?}", e))
2954 .unwrap()
2955 .into_raw();
2956 InsertOneResponseWrapper {
2957 success: false,
2958 result: std::ptr::null(),
2959 error: error_msg,
2960 request_id,
2961 }
2962 }
2963 };
2964
2965 callback(Box::into_raw(Box::new(response)));
2966 });
2967}
2968#[no_mangle]
2969#[tracing::instrument(skip_all)]
2970pub extern "C" fn free_insert_one_response(response: *mut InsertOneResponseWrapper) {
2971 if response.is_null() {
2972 return;
2973 }
2974 unsafe {
2975 if !(*response).error.is_null() {
2976 let _ = CString::from_raw((*response).error as *mut c_char);
2977 }
2978 if !(*response).result.is_null() {
2979 let _ = CString::from_raw((*response).result as *mut c_char);
2980 }
2981 let _ = Box::from_raw(response);
2982 }
2983}
2984#[repr(C)]
2985pub struct InsertManyRequestWrapper {
2986 collectionname: *const c_char,
2987 items: *const c_char,
2988 w: i32,
2989 j: bool,
2990 skipresults: bool,
2991 request_id: i32
2992}
2993#[repr(C)]
2994pub struct InsertManyResponseWrapper {
2995 success: bool,
2996 results: *const c_char,
2997 error: *const c_char,
2998 request_id: i32,
2999}
3000#[no_mangle]
3001#[tracing::instrument(skip_all)]
3002pub extern "C" fn insert_many(
3003 client: *mut ClientWrapper,
3004 options: *mut InsertManyRequestWrapper,
3005) -> *mut InsertManyResponseWrapper {
3006 let options = match safe_wrapper(options) {
3007 Some(options) => options,
3008 None => {
3009 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3010 let response = InsertManyResponseWrapper {
3011 success: false,
3012 results: std::ptr::null(),
3013 error: error_msg,
3014 request_id: 0,
3015 };
3016 return Box::into_raw(Box::new(response));
3017 }
3018 };
3019 let client_wrapper = match safe_wrapper(client) {
3020 Some(client) => client,
3021 None => {
3022 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3023 let response = InsertManyResponseWrapper {
3024 success: false,
3025 results: std::ptr::null(),
3026 error: error_msg,
3027 request_id: options.request_id,
3028 };
3029 return Box::into_raw(Box::new(response));
3030 }
3031 };
3032 let client = client_wrapper.client.clone();
3033 let request = InsertManyRequest {
3034 collectionname: c_char_to_str(options.collectionname),
3035 items: c_char_to_str(options.items),
3036 w: options.w,
3037 j: options.j,
3038 skipresults: options.skipresults
3039 };
3040 if client.is_none() {
3041 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3042 let response = InsertManyResponseWrapper {
3043 success: false,
3044 results: std::ptr::null(),
3045 error: error_msg,
3046 request_id: options.request_id,
3047 };
3048 return Box::into_raw(Box::new(response));
3049 }
3050 let client = client.unwrap();
3051 let result = tokio::task::block_in_place(|| {
3052 let handle = client.get_runtime_handle();
3053 handle.block_on( client.insert_many(request))
3054 });
3055
3056 let response = match result {
3057 Ok(data) => {
3058 let results = CString::new(data.results).unwrap().into_raw();
3059 InsertManyResponseWrapper {
3060 success: true,
3061 results,
3062 error: std::ptr::null(),
3063 request_id: options.request_id,
3064 }
3065 }
3066 Err(e) => {
3067 let error_msg = CString::new(format!("InsertMany failed: {:?}", e))
3068 .unwrap()
3069 .into_raw();
3070 InsertManyResponseWrapper {
3071 success: false,
3072 results: std::ptr::null(),
3073 error: error_msg,
3074 request_id: options.request_id,
3075 }
3076 }
3077 };
3078
3079 Box::into_raw(Box::new(response))
3080}
3081
3082type InsertManyCallback = extern "C" fn(wrapper: *mut InsertManyResponseWrapper);
3083#[no_mangle]
3084#[tracing::instrument(skip_all)]
3085pub extern "C" fn insert_many_async(
3086 client: *mut ClientWrapper,
3087 options: *mut InsertManyRequestWrapper,
3088 callback: InsertManyCallback,
3089) {
3090 let options = match safe_wrapper(options) {
3091 Some(options) => options,
3092 None => {
3093 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3094 let response = InsertManyResponseWrapper {
3095 success: false,
3096 results: std::ptr::null(),
3097 error: error_msg,
3098 request_id: 0,
3099 };
3100 return callback(Box::into_raw(Box::new(response)));
3101 }
3102 };
3103 let client_wrapper = match safe_wrapper(client) {
3104 Some(client) => client,
3105 None => {
3106 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3107 let response = InsertManyResponseWrapper {
3108 success: false,
3109 results: std::ptr::null(),
3110 error: error_msg,
3111 request_id: options.request_id,
3112 };
3113 return callback(Box::into_raw(Box::new(response)));
3114 }
3115 };
3116 let client = client_wrapper.client.clone();
3117 let request = InsertManyRequest {
3118 collectionname: c_char_to_str(options.collectionname),
3119 items: c_char_to_str(options.items),
3120 w: options.w,
3121 j: options.j,
3122 skipresults: options.skipresults
3123 };
3124 if client.is_none() {
3125 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3126 let response = InsertManyResponseWrapper {
3127 success: false,
3128 results: std::ptr::null(),
3129 error: error_msg,
3130 request_id: options.request_id,
3131 };
3132 return callback(Box::into_raw(Box::new(response)));
3133 }
3134
3135 let client = client.unwrap();
3136 let handle = client.get_runtime_handle();
3137 let request_id = options.request_id;
3138 handle.spawn(async move {
3139 let result = client.insert_many(request).await;
3140 let response = match result {
3141 Ok(data) => {
3142 let results = CString::new(data.results.clone()).unwrap().into_raw();
3143 InsertManyResponseWrapper {
3144 success: true,
3145 results,
3146 error: std::ptr::null(),
3147 request_id,
3148 }
3149 }
3150 Err(e) => {
3151 let error_msg = CString::new(format!("InsertMany failed: {:?}", e))
3152 .unwrap()
3153 .into_raw();
3154 InsertManyResponseWrapper {
3155 success: false,
3156 results: std::ptr::null(),
3157 error: error_msg,
3158 request_id,
3159 }
3160 }
3161 };
3162
3163 callback(Box::into_raw(Box::new(response)));
3164 });
3165}
3166
3167#[no_mangle]
3168#[tracing::instrument(skip_all)]
3169pub extern "C" fn free_insert_many_response(response: *mut InsertManyResponseWrapper) {
3170 if response.is_null() {
3171 return;
3172 }
3173 unsafe {
3174 if !(*response).results.is_null() {
3175 let _ = CString::from_raw((*response).results as *mut c_char);
3176 }
3177 let _ = Box::from_raw(response);
3178 }
3179}
3180
3181#[repr(C)]
3182pub struct UpdateOneRequestWrapper {
3183 collectionname: *const c_char,
3184 item: *const c_char,
3185 w: i32,
3186 j: bool,
3187 request_id: i32
3188}
3189#[repr(C)]
3190pub struct UpdateOneResponseWrapper {
3191 success: bool,
3192 result: *const c_char,
3193 error: *const c_char,
3194 request_id: i32
3195}
3196#[no_mangle]
3197#[tracing::instrument(skip_all)]
3198pub extern "C" fn update_one(
3199 client: *mut ClientWrapper,
3200 options: *mut UpdateOneRequestWrapper,
3201) -> *mut UpdateOneResponseWrapper {
3202 let options = match safe_wrapper(options) {
3203 Some(options) => options,
3204 None => {
3205 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3206 let response = UpdateOneResponseWrapper {
3207 success: false,
3208 result: std::ptr::null(),
3209 error: error_msg,
3210 request_id: 0,
3211 };
3212 return Box::into_raw(Box::new(response));
3213 }
3214 };
3215 let client_wrapper = match safe_wrapper(client) {
3216 Some(client) => client,
3217 None => {
3218 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3219 let response = UpdateOneResponseWrapper {
3220 success: false,
3221 result: std::ptr::null(),
3222 error: error_msg,
3223 request_id: options.request_id,
3224 };
3225 return Box::into_raw(Box::new(response));
3226 }
3227 };
3228 let client = client_wrapper.client.clone();
3229 let request = UpdateOneRequest {
3230 collectionname: c_char_to_str(options.collectionname),
3231 item: c_char_to_str(options.item),
3232 w: options.w,
3233 j: options.j
3234 };
3235 if client.is_none() {
3236 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3237 let response = UpdateOneResponseWrapper {
3238 success: false,
3239 result: std::ptr::null(),
3240 error: error_msg,
3241 request_id: options.request_id,
3242 };
3243 return Box::into_raw(Box::new(response));
3244 }
3245 let client = client.unwrap();
3246 let result = tokio::task::block_in_place(|| {
3247 let handle = client.get_runtime_handle();
3248 handle.block_on( client.update_one(request))
3249 });
3250
3251 let response = match result {
3252 Ok(data) => {
3253 let result = CString::new(data.result).unwrap().into_raw();
3254 UpdateOneResponseWrapper {
3255 success: true,
3256 result,
3257 error: std::ptr::null(),
3258 request_id: options.request_id,
3259 }
3260 }
3261 Err(e) => {
3262 let error_msg = CString::new(format!("UpdateOne failed: {:?}", e))
3263 .unwrap()
3264 .into_raw();
3265 UpdateOneResponseWrapper {
3266 success: false,
3267 result: std::ptr::null(),
3268 error: error_msg,
3269 request_id: options.request_id,
3270 }
3271 }
3272 };
3273
3274 Box::into_raw(Box::new(response))
3275}
3276
3277type UpdateOneCallback = extern "C" fn(wrapper: *mut UpdateOneResponseWrapper);
3278#[no_mangle]
3279#[tracing::instrument(skip_all)]
3280pub extern "C" fn update_one_async(
3281 client: *mut ClientWrapper,
3282 options: *mut UpdateOneRequestWrapper,
3283 callback: UpdateOneCallback,
3284) {
3285 let options = match safe_wrapper(options) {
3286 Some(options) => options,
3287 None => {
3288 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3289 let response = UpdateOneResponseWrapper {
3290 success: false,
3291 result: std::ptr::null(),
3292 error: error_msg,
3293 request_id: 0,
3294 };
3295 return callback(Box::into_raw(Box::new(response)));
3296 }
3297 };
3298 let client_wrapper = match safe_wrapper(client) {
3299 Some(client) => client,
3300 None => {
3301 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3302 let response = UpdateOneResponseWrapper {
3303 success: false,
3304 result: std::ptr::null(),
3305 error: error_msg,
3306 request_id: options.request_id,
3307 };
3308 return callback(Box::into_raw(Box::new(response)));
3309 }
3310 };
3311 let client = client_wrapper.client.clone();
3312 let request = UpdateOneRequest {
3313 collectionname: c_char_to_str(options.collectionname),
3314 item: c_char_to_str(options.item),
3315 w: options.w,
3316 j: options.j
3317 };
3318 if client.is_none() {
3319 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3320 let response = UpdateOneResponseWrapper {
3321 success: false,
3322 result: std::ptr::null(),
3323 error: error_msg,
3324 request_id: options.request_id,
3325 };
3326 return callback(Box::into_raw(Box::new(response)));
3327 }
3328
3329 let client = client.unwrap();
3330 let handle = client.get_runtime_handle();
3331 let request_id = options.request_id;
3332 handle.spawn(async move {
3333 let result = client.update_one(request).await;
3334 let response = match result {
3335 Ok(data) => {
3336 let result = CString::new(data.result).unwrap().into_raw();
3337 UpdateOneResponseWrapper {
3338 success: true,
3339 result,
3340 error: std::ptr::null(),
3341 request_id,
3342 }
3343 }
3344 Err(e) => {
3345 let error_msg = CString::new(format!("UpdateOne failed: {:?}", e))
3346 .unwrap()
3347 .into_raw();
3348 UpdateOneResponseWrapper {
3349 success: false,
3350 result: std::ptr::null(),
3351 error: error_msg,
3352 request_id,
3353 }
3354 }
3355 };
3356
3357 callback(Box::into_raw(Box::new(response)));
3358 });
3359}
3360
3361#[no_mangle]
3362#[tracing::instrument(skip_all)]
3363pub extern "C" fn free_update_one_response(response: *mut UpdateOneResponseWrapper) {
3364 if response.is_null() {
3365 return;
3366 }
3367 unsafe {
3368 if !(*response).error.is_null() {
3369 let _ = CString::from_raw((*response).error as *mut c_char);
3370 }
3371 if !(*response).result.is_null() {
3372 let _ = CString::from_raw((*response).result as *mut c_char);
3373 }
3374 let _ = Box::from_raw(response);
3375 }
3376}
3377
3378#[repr(C)]
3379pub struct InsertOrUpdateOneRequestWrapper {
3380 collectionname: *const c_char,
3381 uniqeness: *const c_char,
3382 item: *const c_char,
3383 w: i32,
3384 j: bool,
3385 request_id: i32
3386}
3387#[repr(C)]
3388pub struct InsertOrUpdateOneResponseWrapper {
3389 success: bool,
3390 result: *const c_char,
3391 error: *const c_char,
3392 request_id: i32
3393}
3394#[no_mangle]
3395#[tracing::instrument(skip_all)]
3396pub extern "C" fn insert_or_update_one(
3397 client: *mut ClientWrapper,
3398 options: *mut InsertOrUpdateOneRequestWrapper,
3399) -> *mut InsertOrUpdateOneResponseWrapper {
3400 let options = match safe_wrapper(options) {
3401 Some(options) => options,
3402 None => {
3403 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3404 let response = InsertOrUpdateOneResponseWrapper {
3405 success: false,
3406 result: std::ptr::null(),
3407 error: error_msg,
3408 request_id: 0,
3409 };
3410 return Box::into_raw(Box::new(response));
3411 }
3412 };
3413 let client_wrapper = match safe_wrapper(client) {
3414 Some(client) => client,
3415 None => {
3416 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3417 let response = InsertOrUpdateOneResponseWrapper {
3418 success: false,
3419 result: std::ptr::null(),
3420 error: error_msg,
3421 request_id: options.request_id,
3422 };
3423 return Box::into_raw(Box::new(response));
3424 }
3425 };
3426 let client = client_wrapper.client.clone();
3427 debug!("Rust: insert_or_update_one create request");
3428
3429 trace!("Rust: parse collectionname");
3430 let collectionname = c_char_to_str(options.collectionname);
3431 trace!("Rust: parse uniqeness");
3432 let uniqeness = c_char_to_str(options.uniqeness);
3433 trace!("Rust: parse item");
3434 let item = c_char_to_str(options.item);
3435 trace!("Rust: parse w");
3436 let w = options.w;
3437 trace!("Rust: parse j");
3438 let j = options.j;
3439 let request = InsertOrUpdateOneRequest {
3440 collectionname,
3441 uniqeness,
3442 item,
3443 w,
3444 j
3445 };
3446 if client.is_none() {
3447 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3448 let response = InsertOrUpdateOneResponseWrapper {
3449 success: false,
3450 result: std::ptr::null(),
3451 error: error_msg,
3452 request_id: options.request_id,
3453 };
3454 return Box::into_raw(Box::new(response));
3455 }
3456 let client = client.unwrap();
3457 debug!("Rust: run insert_or_update_one in runtime");
3458 let result = tokio::task::block_in_place(|| {
3459 let handle = client.get_runtime_handle();
3460 handle.block_on( client.insert_or_update_one(request))
3461 });
3462
3463 let response = match result {
3464 Ok(data) => {
3465 let result = CString::new(data).unwrap().into_raw();
3466 InsertOrUpdateOneResponseWrapper {
3467 success: true,
3468 result,
3469 error: std::ptr::null(),
3470 request_id: options.request_id,
3471 }
3472 }
3473 Err(e) => {
3474 let error_msg = CString::new(format!("InsertOrUpdateOne failed: {:?}", e))
3475 .unwrap()
3476 .into_raw();
3477 InsertOrUpdateOneResponseWrapper {
3478 success: false,
3479 result: std::ptr::null(),
3480 error: error_msg,
3481 request_id: options.request_id,
3482 }
3483 }
3484 };
3485
3486 Box::into_raw(Box::new(response))
3487}
3488
3489type InsertOrUpdateOneCallback = extern "C" fn(wrapper: *mut InsertOrUpdateOneResponseWrapper);
3490#[no_mangle]
3491#[tracing::instrument(skip_all)]
3492pub extern "C" fn insert_or_update_one_async(
3493 client: *mut ClientWrapper,
3494 options: *mut InsertOrUpdateOneRequestWrapper,
3495 callback: InsertOrUpdateOneCallback,
3496) {
3497 let options = match safe_wrapper(options) {
3498 Some(options) => options,
3499 None => {
3500 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3501 let response = InsertOrUpdateOneResponseWrapper {
3502 success: false,
3503 result: std::ptr::null(),
3504 error: error_msg,
3505 request_id: 0,
3506 };
3507 return callback(Box::into_raw(Box::new(response)));
3508 }
3509 };
3510 let client_wrapper = match safe_wrapper(client) {
3511 Some(client) => client,
3512 None => {
3513 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3514 let response = InsertOrUpdateOneResponseWrapper {
3515 success: false,
3516 result: std::ptr::null(),
3517 error: error_msg,
3518 request_id: options.request_id,
3519 };
3520 return callback(Box::into_raw(Box::new(response)));
3521 }
3522 };
3523 let client = client_wrapper.client.clone();
3524 debug!("Rust: insert_or_update_one_async create request");
3525 let request = InsertOrUpdateOneRequest {
3526 collectionname: c_char_to_str(options.collectionname),
3527 uniqeness: c_char_to_str(options.uniqeness),
3528 item: c_char_to_str(options.item),
3529 w: options.w,
3530 j: options.j
3531 };
3532 if client.is_none() {
3533 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3534 let response = InsertOrUpdateOneResponseWrapper {
3535 success: false,
3536 result: std::ptr::null(),
3537 error: error_msg,
3538 request_id: options.request_id,
3539 };
3540 return callback(Box::into_raw(Box::new(response)));
3541 }
3542 let client = client.unwrap();
3543 let handle = client.get_runtime_handle();
3544 let request_id = options.request_id;
3545 handle.spawn(async move {
3546 let result = client.insert_or_update_one(request).await;
3547
3548 let response = match result {
3549 Ok(data) => {
3550 let result = CString::new(data).unwrap().into_raw();
3551 InsertOrUpdateOneResponseWrapper {
3552 success: true,
3553 result,
3554 error: std::ptr::null(),
3555 request_id,
3556 }
3557 }
3558 Err(e) => {
3559 let error_msg = CString::new(format!("InsertOrUpdateOne failed: {:?}", e))
3560 .unwrap()
3561 .into_raw();
3562 InsertOrUpdateOneResponseWrapper {
3563 success: false,
3564 result: std::ptr::null(),
3565 error: error_msg,
3566 request_id,
3567 }
3568 }
3569 };
3570
3571 callback(Box::into_raw(Box::new(response)));
3572 });
3573}
3574#[no_mangle]
3575#[tracing::instrument(skip_all)]
3576pub extern "C" fn free_insert_or_update_one_response(response: *mut InsertOrUpdateOneResponseWrapper) {
3577 if response.is_null() {
3578 return;
3579 }
3580 unsafe {
3581 if !(*response).error.is_null() {
3582 let _ = CString::from_raw((*response).error as *mut c_char);
3583 }
3584 if !(*response).result.is_null() {
3585 let _ = CString::from_raw((*response).result as *mut c_char);
3586 }
3587 let _ = Box::from_raw(response);
3588 }
3589}
3590
3591#[repr(C)]
3592pub struct DeleteOneRequestWrapper {
3593 collectionname: *const c_char,
3594 id: *const c_char,
3595 recursive: bool,
3596 request_id: i32
3597}
3598#[repr(C)]
3599pub struct DeleteOneResponseWrapper {
3600 success: bool,
3601 affectedrows: i32,
3602 error: *const c_char,
3603 request_id: i32
3604}
3605#[no_mangle]
3606#[tracing::instrument(skip_all)]
3607pub extern "C" fn delete_one(
3608 client: *mut ClientWrapper,
3609 options: *mut DeleteOneRequestWrapper,
3610) -> *mut DeleteOneResponseWrapper {
3611 let options = match safe_wrapper(options) {
3612 Some(options) => options,
3613 None => {
3614 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3615 let response = DeleteOneResponseWrapper {
3616 success: false,
3617 affectedrows: 0,
3618 error: error_msg,
3619 request_id: 0,
3620 };
3621 return Box::into_raw(Box::new(response));
3622 }
3623 };
3624 let client_wrapper = match safe_wrapper(client) {
3625 Some(client) => client,
3626 None => {
3627 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3628 let response = DeleteOneResponseWrapper {
3629 success: false,
3630 affectedrows: 0,
3631 error: error_msg,
3632 request_id: options.request_id,
3633 };
3634 return Box::into_raw(Box::new(response));
3635 }
3636 };
3637 let client = client_wrapper.client.clone();
3638 let request = DeleteOneRequest {
3639 collectionname: c_char_to_str(options.collectionname),
3640 id: c_char_to_str(options.id),
3641 recursive: options.recursive
3642 };
3643 if client.is_none() {
3644 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3645 let response = DeleteOneResponseWrapper {
3646 success: false,
3647 affectedrows: 0,
3648 error: error_msg,
3649 request_id: options.request_id,
3650 };
3651 return Box::into_raw(Box::new(response));
3652 }
3653 let client = client.unwrap();
3654 let result = tokio::task::block_in_place(|| {
3655 let handle = client.get_runtime_handle();
3656 handle.block_on( client.delete_one(request))
3657 });
3658
3659 let response = match result {
3660 Ok(data) => {
3661 let affectedrows = data;
3662 DeleteOneResponseWrapper {
3663 success: true,
3664 affectedrows,
3665 error: std::ptr::null(),
3666 request_id: options.request_id,
3667 }
3668 }
3669 Err(e) => {
3670 let error_msg = CString::new(format!("DeleteOne failed: {:?}", e))
3671 .unwrap()
3672 .into_raw();
3673 DeleteOneResponseWrapper {
3674 success: false,
3675 affectedrows: 0,
3676 error: error_msg,
3677 request_id: options.request_id,
3678 }
3679 }
3680 };
3681
3682 Box::into_raw(Box::new(response))
3683}
3684type DeleteOneCallback = extern "C" fn(wrapper: *mut DeleteOneResponseWrapper);
3685#[no_mangle]
3686#[tracing::instrument(skip_all)]
3687pub extern "C" fn delete_one_async(
3688 client: *mut ClientWrapper,
3689 options: *mut DeleteOneRequestWrapper,
3690 callback: DeleteOneCallback,
3691) {
3692 let options = match safe_wrapper(options) {
3693 Some(options) => options,
3694 None => {
3695 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3696 let response = DeleteOneResponseWrapper {
3697 success: false,
3698 affectedrows: 0,
3699 error: error_msg,
3700 request_id: 0,
3701 };
3702 return callback(Box::into_raw(Box::new(response)));
3703 }
3704 };
3705 let client_wrapper = match safe_wrapper(client) {
3706 Some(client) => client,
3707 None => {
3708 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3709 let response = DeleteOneResponseWrapper {
3710 success: false,
3711 affectedrows: 0,
3712 error: error_msg,
3713 request_id: options.request_id,
3714 };
3715 return callback(Box::into_raw(Box::new(response)));
3716 }
3717 };
3718 let client = client_wrapper.client.clone();
3719 let request = DeleteOneRequest {
3720 collectionname: c_char_to_str(options.collectionname),
3721 id: c_char_to_str(options.id),
3722 recursive: options.recursive
3723 };
3724 if client.is_none() {
3725 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3726 let response = DeleteOneResponseWrapper {
3727 success: false,
3728 affectedrows: 0,
3729 error: error_msg,
3730 request_id: options.request_id,
3731 };
3732 return callback(Box::into_raw(Box::new(response)));
3733 }
3734
3735 let client = client.unwrap();
3736 let handle = client.get_runtime_handle();
3737 let request_id = options.request_id;
3738 handle.spawn(async move {
3739 let result = client.delete_one(request).await;
3740 let response = match result {
3741 Ok(data) => {
3742 let affectedrows = data;
3743 DeleteOneResponseWrapper {
3744 success: true,
3745 affectedrows,
3746 error: std::ptr::null(),
3747 request_id,
3748 }
3749 }
3750 Err(e) => {
3751 let error_msg = CString::new(format!("DeleteOne failed: {:?}", e))
3752 .unwrap()
3753 .into_raw();
3754 DeleteOneResponseWrapper {
3755 success: false,
3756 affectedrows: 0,
3757 error: error_msg,
3758 request_id,
3759 }
3760 }
3761 };
3762
3763 callback(Box::into_raw(Box::new(response)));
3764 });
3765}
3766#[no_mangle]
3767#[tracing::instrument(skip_all)]
3768pub extern "C" fn free_delete_one_response(response: *mut DeleteOneResponseWrapper) {
3769 if response.is_null() {
3770 return;
3771 }
3772 unsafe {
3773 if !(*response).error.is_null() {
3774 let _ = CString::from_raw((*response).error as *mut c_char);
3775 }
3776 let _ = Box::from_raw(response);
3777 }
3778}
3779
3780#[repr(C)]
3781pub struct DeleteManyRequestWrapper {
3782 collectionname: *const c_char,
3783 query: *const c_char,
3784 recursive: bool,
3785 ids: *const *const c_char,
3786 request_id: i32
3787}
3788#[repr(C)]
3789pub struct DeleteManyResponseWrapper {
3790 success: bool,
3791 affectedrows: i32,
3792 error: *const c_char,
3793 request_id: i32
3794}
3795#[no_mangle]
3796#[tracing::instrument(skip_all)]
3797pub extern "C" fn delete_many(
3798 client: *mut ClientWrapper,
3799 options: *mut DeleteManyRequestWrapper,
3800) -> *mut DeleteManyResponseWrapper {
3801 let options = match safe_wrapper(options) {
3802 Some(options) => options,
3803 None => {
3804 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3805 let response = DeleteManyResponseWrapper {
3806 success: false,
3807 affectedrows: 0,
3808 error: error_msg,
3809 request_id: 0,
3810 };
3811 return Box::into_raw(Box::new(response));
3812 }
3813 };
3814 let client_wrapper = match safe_wrapper(client) {
3815 Some(client) => client,
3816 None => {
3817 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3818 let response = DeleteManyResponseWrapper {
3819 success: false,
3820 affectedrows: 0,
3821 error: error_msg,
3822 request_id: options.request_id,
3823 };
3824 return Box::into_raw(Box::new(response));
3825 }
3826 };
3827 let client = client_wrapper.client.clone();
3828 let request = DeleteManyRequest {
3829 collectionname: c_char_to_str(options.collectionname),
3830 query: c_char_to_str(options.query),
3831 recursive: options.recursive,
3832 ids: {
3833 let mut ids = vec![];
3834 if !options.ids.is_null() {
3835 let mut i = 0;
3836 loop {
3837 let id = unsafe { *options.ids.add(i) };
3838 if id.is_null() {
3839 break;
3840 }
3841 ids.push(c_char_to_str(id));
3842 i += 1;
3843 }
3844 }
3845 ids
3846 }
3847 };
3848 if client.is_none() {
3849 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3850 let response = DeleteManyResponseWrapper {
3851 success: false,
3852 affectedrows: 0,
3853 error: error_msg,
3854 request_id: options.request_id,
3855 };
3856 return Box::into_raw(Box::new(response));
3857 }
3858 let client = client.unwrap();
3859 let result = tokio::task::block_in_place(|| {
3860 let handle = client.get_runtime_handle();
3861 handle.block_on( client.delete_many(request))
3862 });
3863
3864 let response = match result {
3865 Ok(data) => {
3866 let affectedrows = data;
3867 DeleteManyResponseWrapper {
3868 success: true,
3869 affectedrows,
3870 error: std::ptr::null(),
3871 request_id: options.request_id,
3872 }
3873 }
3874 Err(e) => {
3875 let error_msg = CString::new(format!("DeleteMany failed: {:?}", e))
3876 .unwrap()
3877 .into_raw();
3878 DeleteManyResponseWrapper {
3879 success: false,
3880 affectedrows: 0,
3881 error: error_msg,
3882 request_id: options.request_id,
3883 }
3884 }
3885 };
3886
3887 Box::into_raw(Box::new(response))
3888}
3889type DeleteManyCallback = extern "C" fn(wrapper: *mut DeleteManyResponseWrapper);
3890#[no_mangle]
3891#[tracing::instrument(skip_all)]
3892pub extern "C" fn delete_many_async(
3893 client: *mut ClientWrapper,
3894 options: *mut DeleteManyRequestWrapper,
3895 callback: DeleteManyCallback,
3896) {
3897 let options = match safe_wrapper(options) {
3898 Some(options) => options,
3899 None => {
3900 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3901 let response = DeleteManyResponseWrapper {
3902 success: false,
3903 affectedrows: 0,
3904 error: error_msg,
3905 request_id: 0,
3906 };
3907 return callback(Box::into_raw(Box::new(response)));
3908 }
3909 };
3910 let client_wrapper = match safe_wrapper(client) {
3911 Some(client) => client,
3912 None => {
3913 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3914 let response = DeleteManyResponseWrapper {
3915 success: false,
3916 affectedrows: 0,
3917 error: error_msg,
3918 request_id: options.request_id,
3919 };
3920 return callback(Box::into_raw(Box::new(response)));
3921 }
3922 };
3923 let client = client_wrapper.client.clone();
3924 let request = DeleteManyRequest {
3925 collectionname: c_char_to_str(options.collectionname),
3926 query: c_char_to_str(options.query),
3927 recursive: options.recursive,
3928 ids: {
3929 let mut ids = vec![];
3930 let mut i = 0;
3931 loop {
3932 let id = unsafe { *options.ids.add(i) };
3933 if id.is_null() {
3934 break;
3935 }
3936 let id = c_char_to_str(id);
3937 ids.push(id);
3938 i += 1;
3939 }
3940 ids
3941 }
3942 };
3943 if client.is_none() {
3944 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3945 let response = DeleteManyResponseWrapper {
3946 success: false,
3947 affectedrows: 0,
3948 error: error_msg,
3949 request_id: options.request_id,
3950 };
3951 return callback(Box::into_raw(Box::new(response)));
3952 }
3953 let client = client.unwrap();
3954 let handle = client.get_runtime_handle();
3955 let request_id = options.request_id;
3956 handle.spawn(async move {
3957 let result = client.delete_many(request).await;
3958 let response = match result {
3959 Ok(data) => {
3960 let affectedrows = data;
3961 DeleteManyResponseWrapper {
3962 success: true,
3963 affectedrows,
3964 error: std::ptr::null(),
3965 request_id,
3966 }
3967 }
3968 Err(e) => {
3969 let error_msg = CString::new(format!("DeleteMany failed: {:?}", e))
3970 .unwrap()
3971 .into_raw();
3972 DeleteManyResponseWrapper {
3973 success: false,
3974 affectedrows: 0,
3975 error: error_msg,
3976 request_id,
3977 }
3978 }
3979 };
3980
3981 callback(Box::into_raw(Box::new(response)));
3982 });
3983}
3984#[no_mangle]
3985#[tracing::instrument(skip_all)]
3986pub extern "C" fn free_delete_many_response(response: *mut DeleteManyResponseWrapper) {
3987 if response.is_null() {
3988 return;
3989 }
3990 unsafe {
3991 if !(*response).error.is_null() {
3992 let _ = CString::from_raw((*response).error as *mut c_char);
3993 }
3994 let _ = Box::from_raw(response);
3995 }
3996}
3997
3998#[repr(C)]
3999pub struct DownloadRequestWrapper {
4000 collectionname: *const c_char,
4001 id: *const c_char,
4002 folder: *const c_char,
4003 filename: *const c_char,
4004 request_id: i32
4005}
4006#[repr(C)]
4007pub struct DownloadResponseWrapper {
4008 success: bool,
4009 filename: *const c_char,
4010 error: *const c_char,
4011 request_id: i32
4012}
4013#[no_mangle]
4014#[tracing::instrument(skip_all)]
4015pub extern "C" fn download(
4016 client: *mut ClientWrapper,
4017 options: *mut DownloadRequestWrapper,
4018) -> *mut DownloadResponseWrapper {
4019 let options = match safe_wrapper(options) {
4020 Some(options) => options,
4021 None => {
4022 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4023 let response = DownloadResponseWrapper {
4024 success: false,
4025 filename: std::ptr::null(),
4026 error: error_msg,
4027 request_id: 0,
4028 };
4029 return Box::into_raw(Box::new(response));
4030 }
4031 };
4032 let client_wrapper = match safe_wrapper(client) {
4033 Some(client) => client,
4034 None => {
4035 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4036 let response = DownloadResponseWrapper {
4037 success: false,
4038 filename: std::ptr::null(),
4039 error: error_msg,
4040 request_id: options.request_id,
4041 };
4042 return Box::into_raw(Box::new(response));
4043 }
4044 };
4045 let client = client_wrapper.client.clone();
4046 let folder = c_char_to_str(options.folder);
4047 let filename = c_char_to_str(options.filename);
4048 let request = DownloadRequest {
4049 collectionname: c_char_to_str(options.collectionname),
4050 filename: c_char_to_str(options.filename),
4051 id: c_char_to_str(options.id)
4052 };
4053 if client.is_none() {
4054 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4055 let response = DownloadResponseWrapper {
4056 success: false,
4057 filename: std::ptr::null(),
4058 error: error_msg,
4059 request_id: options.request_id,
4060 };
4061 return Box::into_raw(Box::new(response));
4062 }
4063 let client = client.unwrap();
4064 let result = tokio::task::block_in_place(|| {
4065 let handle = client.get_runtime_handle();
4066 handle.block_on( client.download(request, Some(&folder), Some(&filename)))
4067 });
4068
4069 let response = match result {
4070 Ok(data) => {
4071 let filename = CString::new(data.filename).unwrap().into_raw();
4072 DownloadResponseWrapper {
4073 success: true,
4074 filename,
4075 error: std::ptr::null(),
4076 request_id: options.request_id,
4077 }
4078 }
4079 Err(e) => {
4080 let error_msg = CString::new(format!("Download failed: {:?}", e))
4081 .unwrap()
4082 .into_raw();
4083 DownloadResponseWrapper {
4084 success: false,
4085 filename: std::ptr::null(),
4086 error: error_msg,
4087 request_id: options.request_id,
4088 }
4089 }
4090 };
4091
4092 Box::into_raw(Box::new(response))
4093}
4094
4095type DownloadCallback = extern "C" fn(wrapper: *mut DownloadResponseWrapper);
4096#[no_mangle]
4097#[tracing::instrument(skip_all)]
4098pub extern "C" fn download_async(
4099 client: *mut ClientWrapper,
4100 options: *mut DownloadRequestWrapper,
4101 callback: DownloadCallback,
4102) {
4103 let options = match safe_wrapper(options) {
4104 Some(options) => options,
4105 None => {
4106 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4107 let response = DownloadResponseWrapper {
4108 success: false,
4109 filename: std::ptr::null(),
4110 error: error_msg,
4111 request_id: 0,
4112 };
4113 return callback(Box::into_raw(Box::new(response)));
4114 }
4115 };
4116 let client_wrapper = match safe_wrapper(client) {
4117 Some(client) => client,
4118 None => {
4119 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4120 let response = DownloadResponseWrapper {
4121 success: false,
4122 filename: std::ptr::null(),
4123 error: error_msg,
4124 request_id: options.request_id,
4125 };
4126 return callback(Box::into_raw(Box::new(response)));
4127 }
4128 };
4129 let client = client_wrapper.client.clone();
4130 let folder = c_char_to_str(options.folder);
4131 let filename = c_char_to_str(options.filename);
4132 let request = DownloadRequest {
4133 collectionname: c_char_to_str(options.collectionname),
4134 filename: c_char_to_str(options.filename),
4135 id: c_char_to_str(options.id)
4136 };
4137 if client.is_none() {
4138 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4139 let response = DownloadResponseWrapper {
4140 success: false,
4141 filename: std::ptr::null(),
4142 error: error_msg,
4143 request_id: options.request_id,
4144 };
4145 return callback(Box::into_raw(Box::new(response)));
4146 }
4147 let client = client.unwrap();
4148 let handle = client.get_runtime_handle();
4149 let request_id = options.request_id;
4150 handle.spawn(async move {
4151 let result = client
4152 .download(request, Some(&folder), Some(&filename))
4153 .await;
4154
4155 let response = match result {
4156 Ok(data) => {
4157 let filename = CString::new(data.filename).unwrap().into_raw();
4158 DownloadResponseWrapper {
4159 success: true,
4160 filename,
4161 error: std::ptr::null(),
4162 request_id,
4163 }
4164 }
4165 Err(e) => {
4166 let error_msg = CString::new(format!("Download failed: {:?}", e))
4167 .unwrap()
4168 .into_raw();
4169 DownloadResponseWrapper {
4170 success: false,
4171 filename: std::ptr::null(),
4172 error: error_msg,
4173 request_id,
4174 }
4175 }
4176 };
4177
4178 callback(Box::into_raw(Box::new(response)));
4179 });
4180}
4181#[no_mangle]
4182#[tracing::instrument(skip_all)]
4183pub extern "C" fn free_download_response(response: *mut DownloadResponseWrapper) {
4184 if response.is_null() {
4185 return;
4186 }
4187 unsafe {
4188 if !(*response).error.is_null() {
4189 let _ = CString::from_raw((*response).error as *mut c_char);
4190 }
4191 if !(*response).filename.is_null() {
4192 let _ = CString::from_raw((*response).filename as *mut c_char);
4193 }
4194 let _ = Box::from_raw(response);
4195 }
4196}
4197
4198#[repr(C)]
4199pub struct UploadRequestWrapper {
4200 filepath: *const c_char,
4201 filename: *const c_char,
4202 mimetype: *const c_char,
4203 metadata: *const c_char,
4204 collectionname: *const c_char,
4205 request_id: i32
4206}
4207#[repr(C)]
4208pub struct UploadResponseWrapper {
4209 success: bool,
4210 id: *const c_char,
4211 error: *const c_char,
4212 request_id: i32
4213}
4214#[no_mangle]
4215#[tracing::instrument(skip_all)]
4216pub extern "C" fn upload(
4217 client: *mut ClientWrapper,
4218 options: *mut UploadRequestWrapper,
4219) -> *mut UploadResponseWrapper {
4220 let options = match safe_wrapper(options) {
4221 Some(options) => options,
4222 None => {
4223 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4224 let response = UploadResponseWrapper {
4225 success: false,
4226 id: std::ptr::null(),
4227 error: error_msg,
4228 request_id: 0,
4229 };
4230 return Box::into_raw(Box::new(response));
4231 }
4232 };
4233 let client_wrapper = match safe_wrapper(client) {
4234 Some(client) => client,
4235 None => {
4236 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4237 let response = UploadResponseWrapper {
4238 success: false,
4239 id: std::ptr::null(),
4240 error: error_msg,
4241 request_id: options.request_id,
4242 };
4243 return Box::into_raw(Box::new(response));
4244 }
4245 };
4246 let client = client_wrapper.client.clone();
4247 let filepath = c_char_to_str(options.filepath);
4248 if filepath.is_empty() {
4249 let error_msg = CString::new("Filepath is required").unwrap().into_raw();
4250 let response = UploadResponseWrapper {
4251 success: false,
4252 id: std::ptr::null(),
4253 error: error_msg,
4254 request_id: options.request_id,
4255 };
4256 return Box::into_raw(Box::new(response));
4257 }
4258 let filepath = filepath.to_string();
4259 debug!("upload: filepath: {}", filepath);
4260 let filename = c_char_to_str(options.filename);
4261 if filename.is_empty() {
4262 let error_msg = CString::new("Filename is required").unwrap().into_raw();
4263 let response = UploadResponseWrapper {
4264 success: false,
4265 id: std::ptr::null(),
4266 error: error_msg,
4267 request_id: options.request_id,
4268 };
4269 return Box::into_raw(Box::new(response));
4270 }
4271
4272 let request = UploadRequest {
4273 filename: filename.to_string(),
4274 mimetype: c_char_to_str(options.mimetype),
4275 metadata: c_char_to_str(options.metadata),
4276 collectionname: c_char_to_str(options.collectionname)
4277 };
4278 if client.is_none() {
4279 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4280 let response = UploadResponseWrapper {
4281 success: false,
4282 id: std::ptr::null(),
4283 error: error_msg,
4284 request_id: options.request_id,
4285 };
4286 return Box::into_raw(Box::new(response));
4287 }
4288 let client = client.unwrap();
4289 debug!("upload: runtime.block_on");
4290 let result = tokio::task::block_in_place(|| {
4291 let handle = client.get_runtime_handle();
4295 handle.block_on( client.upload(request, &filepath))
4296 });
4297
4298 let response = match result {
4299 Ok(data) => {
4300 let id = CString::new(data.id).unwrap().into_raw();
4301 UploadResponseWrapper {
4302 success: true,
4303 id,
4304 error: std::ptr::null(),
4305 request_id: options.request_id,
4306 }
4307 }
4308 Err(e) => {
4309 let error_msg = CString::new(format!("Upload failed: {:?}", e))
4310 .unwrap()
4311 .into_raw();
4312 UploadResponseWrapper {
4313 success: false,
4314 id: std::ptr::null(),
4315 error: error_msg,
4316 request_id: options.request_id,
4317 }
4318 }
4319 };
4320 Box::into_raw(Box::new(response))
4321}
4322
4323type UploadCallback = extern "C" fn(wrapper: *mut UploadResponseWrapper);
4324#[no_mangle]
4325#[tracing::instrument(skip_all)]
4326pub extern "C" fn upload_async(
4327 client: *mut ClientWrapper,
4328 options: *mut UploadRequestWrapper,
4329 callback: UploadCallback,
4330) {
4331 let options = match safe_wrapper(options) {
4332 Some(options) => options,
4333 None => {
4334 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4335 let response = UploadResponseWrapper {
4336 success: false,
4337 id: std::ptr::null(),
4338 error: error_msg,
4339 request_id: 0,
4340 };
4341 return callback(Box::into_raw(Box::new(response)));
4342 }
4343 };
4344 let client_wrapper = match safe_wrapper(client) {
4345 Some(client) => client,
4346 None => {
4347 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4348 let response = UploadResponseWrapper {
4349 success: false,
4350 id: std::ptr::null(),
4351 error: error_msg,
4352 request_id: options.request_id,
4353 };
4354 return callback(Box::into_raw(Box::new(response)));
4355 }
4356 };
4357 let client = client_wrapper.client.clone();
4358 let filepath = c_char_to_str(options.filepath);
4359 if filepath.is_empty() {
4360 let error_msg = CString::new("Filepath is required").unwrap().into_raw();
4361 let response = UploadResponseWrapper {
4362 success: false,
4363 id: std::ptr::null(),
4364 error: error_msg,
4365 request_id: options.request_id,
4366 };
4367 return callback(Box::into_raw(Box::new(response)));
4368 }
4369 let filepath = filepath.to_string();
4370 debug!("upload_async: filepath: {}", filepath);
4371 let filename = c_char_to_str(options.filename);
4372 if filename.is_empty() {
4373 let error_msg = CString::new("Filename is required").unwrap().into_raw();
4374 let response = UploadResponseWrapper {
4375 success: false,
4376 id: std::ptr::null(),
4377 error: error_msg,
4378 request_id: options.request_id,
4379 };
4380 return callback(Box::into_raw(Box::new(response)));
4381 }
4382
4383 let request = UploadRequest {
4384 filename: filename.to_string(),
4385 mimetype: c_char_to_str(options.mimetype),
4386 metadata: c_char_to_str(options.metadata),
4387 collectionname: c_char_to_str(options.collectionname)
4388 };
4389 if client.is_none() {
4390 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4391 let response = UploadResponseWrapper {
4392 success: false,
4393 id: std::ptr::null(),
4394 error: error_msg,
4395 request_id: options.request_id,
4396 };
4397 return callback(Box::into_raw(Box::new(response)));
4398 }
4399 debug!("upload_async: runtime.spawn");
4400 let client = client.unwrap();
4401 let handle = client.get_runtime_handle();
4402 let request_id = options.request_id;
4403 handle.spawn(async move {
4404 debug!("upload_async: call client.upload");
4405 let result = client.upload(request, &filepath).await;
4406
4407 debug!("upload_async: call client.upload done");
4408 let response = match result {
4409 Ok(data) => {
4410 let id = CString::new(data.id).unwrap().into_raw();
4411 UploadResponseWrapper {
4412 success: true,
4413 id,
4414 error: std::ptr::null(),
4415 request_id,
4416 }
4417 }
4418 Err(e) => {
4419 let error_msg = CString::new(format!("Upload failed: {:?}", e))
4420 .unwrap()
4421 .into_raw();
4422 UploadResponseWrapper {
4423 success: false,
4424 id: std::ptr::null(),
4425 error: error_msg,
4426 request_id,
4427 }
4428 }
4429 };
4430 debug!("upload_async: call callback with response");
4431 callback(Box::into_raw(Box::new(response)));
4432 });
4433}
4434#[no_mangle]
4435#[tracing::instrument(skip_all)]
4436pub extern "C" fn free_upload_response(response: *mut UploadResponseWrapper) {
4437 if response.is_null() {
4438 return;
4439 }
4440 unsafe {
4441 if !(*response).error.is_null() {
4442 let _ = CString::from_raw((*response).error as *mut c_char);
4443 }
4444 if !(*response).id.is_null() {
4445 let _ = CString::from_raw((*response).id as *mut c_char);
4446 }
4447 let _ = Box::from_raw(response);
4448 }
4449}
4450
4451#[repr(C)]
4452pub struct WatchRequestWrapper {
4453 collectionname: *const c_char,
4454 paths: *const c_char,
4455 request_id: i32
4456}
4457#[repr(C)]
4458pub struct WatchResponseWrapper {
4459 success: bool,
4460 watchid: *const c_char,
4461 error: *const c_char,
4462 request_id: i32
4463}
4464#[no_mangle]
4465#[tracing::instrument(skip_all)]
4466pub extern "C" fn watch(
4467 client: *mut ClientWrapper,
4468 options: *mut WatchRequestWrapper,
4469) -> *mut WatchResponseWrapper {
4470 let options = match safe_wrapper(options) {
4471 Some(options) => options,
4472 None => {
4473 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4474 let response = WatchResponseWrapper {
4475 success: false,
4476 watchid: std::ptr::null(),
4477 error: error_msg,
4478 request_id: 0,
4479 };
4480 return Box::into_raw(Box::new(response));
4481 }
4482 };
4483 let client_wrapper = match safe_wrapper(client) {
4484 Some(client) => client,
4485 None => {
4486 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4487 let response = WatchResponseWrapper {
4488 success: false,
4489 watchid: std::ptr::null(),
4490 error: error_msg,
4491 request_id: options.request_id,
4492 };
4493 return Box::into_raw(Box::new(response));
4494 }
4495 };
4496 let client = client_wrapper.client.clone();
4497 let paths = c_char_to_str(options.paths);
4499 let paths = paths.split(",").map(|s| s.to_string()).collect();
4500 let request = WatchRequest {
4501 collectionname: c_char_to_str(options.collectionname),
4502 paths,
4503 };
4504 if client.is_none() {
4505 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4506 let response = WatchResponseWrapper {
4507 success: false,
4508 watchid: std::ptr::null(),
4509 error: error_msg,
4510 request_id: options.request_id,
4511 };
4512 return Box::into_raw(Box::new(response));
4513 }
4514 let client = client.unwrap();
4515 let request_id = options.request_id;
4516 let result = tokio::task::block_in_place(|| {
4517 let handle = client.get_runtime_handle();
4518 handle.block_on(
4519 client
4520 .watch(
4521 request,
4522 Box::new(move |event: WatchEvent| {
4523 debug!("watch: event: {:?}", event);
4527 let watchid = CString::new(event.id.clone())
4528 .unwrap()
4529 .into_string()
4530 .unwrap();
4531 let mut e = WATCH_EVENTS.lock().unwrap();
4532 let queue = e.get_mut(&watchid);
4533 match queue {
4534 Some(q) => {
4535 q.push_back(event);
4536 }
4537 None => {
4538 let mut q = std::collections::VecDeque::new();
4539 q.push_back(event);
4540 e.insert(watchid, q);
4541 }
4542 }
4543 }),
4544 )
4545 )
4546 });
4547
4548 let response = match result {
4549 Ok(data) => {
4550 let id = String::from(&data);
4551 let mut events = WATCH_EVENTS.lock().unwrap();
4552 let queue = events.get_mut(&id);
4553 if queue.is_none() {
4554 let q = std::collections::VecDeque::new();
4555 let k = String::from(&data);
4556 events.insert(k, q);
4557 }
4558 let watchid = CString::new(id).unwrap().into_raw();
4559 WatchResponseWrapper {
4560 success: true,
4561 watchid,
4562 error: std::ptr::null(),
4563 request_id,
4564 }
4565 }
4566 Err(e) => {
4567 let error_msg = CString::new(format!("Watch failed: {:?}", e))
4568 .unwrap()
4569 .into_raw();
4570 WatchResponseWrapper {
4571 success: false,
4572 watchid: std::ptr::null(),
4573 error: error_msg,
4574 request_id,
4575 }
4576 }
4577 };
4578
4579 Box::into_raw(Box::new(response))
4580}
4581#[no_mangle]
4582#[tracing::instrument(skip_all)]
4583pub extern "C" fn next_watch_event (
4584 watchid: *const c_char,
4585) -> *mut WatchEventWrapper {
4586 trace!("unwrap watchid");
4587 let watchid = c_char_to_str(watchid);
4588 trace!("watchid {:}", watchid);
4589 let watchid = watchid.to_string();
4590 trace!("unwrap events");
4591 let mut e = WATCH_EVENTS.lock().unwrap();
4592 trace!("get queue");
4593 let queue = e.get_mut(&watchid);
4594 match queue {
4595 Some(q) => {
4596 match q.pop_front() {
4597 Some(event) => {
4598 debug!("got event");
4599 let id = CString::new(event.id).unwrap().into_raw();
4600 let operation = CString::new(event.operation).unwrap().into_raw();
4601 let document = CString::new(event.document).unwrap().into_raw();
4602 let event = Box::new(WatchEventWrapper {
4603 id,
4604 operation,
4605 document,
4606 request_id: 0
4607 });
4608 Box::into_raw(event)
4609 }
4610 None => {
4611 trace!("No event");
4612 Box::into_raw(Box::new(WatchEventWrapper::default()))
4613 },
4614 }
4615 },
4616 None => {
4617 debug!("Queue for {:} not found", watchid);
4618 Box::into_raw(Box::new(WatchEventWrapper::default()))
4619 },
4620 }
4621}
4622#[no_mangle]
4623#[tracing::instrument(skip_all)]
4624pub extern "C" fn free_watch_event(response: *mut WatchEventWrapper) {
4625 if response.is_null() {
4626 return;
4627 }
4628 unsafe {
4629 if !(*response).id.is_null() {
4630 let _ = CString::from_raw((*response).id as *mut c_char);
4631 }
4632 if !(*response).operation.is_null() {
4633 let _ = CString::from_raw((*response).operation as *mut c_char);
4634 }
4635 if !(*response).document.is_null() {
4636 let _ = CString::from_raw((*response).document as *mut c_char);
4637 }
4638 let _ = Box::from_raw(response);
4639 }
4640}
4641
4642type WatchEventCallback = extern "C" fn(*mut WatchEventWrapper);
4643type WatchCallback = extern "C" fn(wrapper: *mut WatchResponseWrapper);
4644#[no_mangle]
4645#[tracing::instrument(skip_all)]
4646pub extern "C" fn watch_async_async(
4647 client: *mut ClientWrapper,
4648 options: *mut WatchRequestWrapper,
4649 callback: WatchCallback,
4650 event_callback: WatchEventCallback,
4652 ) {
4654 debug!("watch_async_async");
4655 let options = match safe_wrapper(options) {
4656 Some(options) => options,
4657 None => {
4658 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4659 let response = WatchResponseWrapper {
4660 success: false,
4661 watchid: std::ptr::null(),
4662 error: error_msg,
4663 request_id: 0,
4664 };
4665 return callback(Box::into_raw(Box::new(response)));
4666 }
4667 };
4668 let client_wrapper = match safe_wrapper(client) {
4669 Some(client) => client,
4670 None => {
4671 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4672 let response = WatchResponseWrapper {
4673 success: false,
4674 watchid: std::ptr::null(),
4675 error: error_msg,
4676 request_id: options.request_id,
4677 };
4678 return callback(Box::into_raw(Box::new(response)));
4679 }
4680 };
4681 let client = client_wrapper.client.clone();
4682 let paths = c_char_to_str(options.paths);
4683 let paths = paths.split(",").map(|s| s.to_string()).collect();
4684 let request = WatchRequest {
4685 collectionname: c_char_to_str(options.collectionname),
4686 paths,
4687 };
4688 if client.is_none() {
4689 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4690 let response = WatchResponseWrapper {
4691 success: false,
4692 watchid: std::ptr::null(),
4693 error: error_msg,
4694 request_id: options.request_id,
4695 };
4696 return callback(Box::into_raw(Box::new(response)));
4697 }
4698 debug!("watch_async: runtime.spawn");
4699 let client = client.unwrap();
4700 let handle = client.get_runtime_handle();
4701 let request_id = options.request_id;
4702 handle.spawn(async move {
4703 debug!("watch_async: call client.watch");
4704 let result = client
4705 .watch(
4706 request,
4707 Box::new(move |_event: WatchEvent| {
4708 debug!("watch_async: spawn new task, to call event_callback");
4709 trace!("watch_async: call event_callback");
4710 let id = CString::new(_event.id).unwrap().into_raw();
4711 let operation = CString::new(_event.operation).unwrap().into_raw();
4712 let document = CString::new(_event.document).unwrap().into_raw();
4713 let event = Box::into_raw(Box::new(WatchEventWrapper {
4714 id,
4715 operation,
4716 document,
4717 request_id
4718 }));
4719
4720 event_callback(event);
4721 }),
4722 )
4723 .await;
4724
4725 let response = match result {
4726 Ok(data) => {
4727 let watchid = CString::new(data).unwrap().into_raw();
4728 WatchResponseWrapper {
4729 success: true,
4730 watchid,
4731 error: std::ptr::null(),
4732 request_id,
4733 }
4734 }
4735 Err(e) => {
4736 let error_msg = CString::new(format!("Watch failed: {:?}", e))
4737 .unwrap()
4738 .into_raw();
4739 WatchResponseWrapper {
4740 success: false,
4741 watchid: std::ptr::null(),
4742 error: error_msg,
4743 request_id,
4744 }
4745 }
4746 };
4747
4748 debug!("watch_async: call callback with response");
4749 callback(Box::into_raw(Box::new(response)));
4750 });
4751}
4752
4753#[no_mangle]
4754#[tracing::instrument(skip_all)]
4755pub extern "C" fn free_watch_response(response: *mut WatchResponseWrapper) {
4756 if response.is_null() {
4757 return;
4758 }
4759 unsafe {
4760 if !(*response).error.is_null() {
4761 let _ = CString::from_raw((*response).error as *mut c_char);
4762 }
4763 if !(*response).watchid.is_null() {
4764 let _ = CString::from_raw((*response).watchid as *mut c_char);
4765 }
4766 let _ = Box::from_raw(response);
4767 }
4768}
4769
4770#[repr(C)]
4771pub struct UnWatchResponseWrapper {
4772 success: bool,
4773 error: *const c_char,
4774 request_id: i32
4775}
4776#[no_mangle]
4777#[tracing::instrument(skip_all)]
4778pub extern "C" fn unwatch(
4779 client: *mut ClientWrapper,
4780 watchid: *const c_char
4781) -> *mut UnWatchResponseWrapper {
4782 let client_wrapper = match safe_wrapper(client) {
4783 Some(client) => client,
4784 None => {
4785 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4786 let response = UnWatchResponseWrapper {
4787 success: false,
4788 error: error_msg,
4789 request_id: 0,
4790 };
4791 return Box::into_raw(Box::new(response));
4792 }
4793 };
4794 let client = client_wrapper.client.clone();
4795 let watchid = c_char_to_str(watchid);
4796 if watchid.is_empty() {
4797 let error_msg = CString::new("Watchid is required").unwrap().into_raw();
4798 let response = UnWatchResponseWrapper {
4799 success: false,
4800 error: error_msg,
4801 request_id: 0,
4802 };
4803 return Box::into_raw(Box::new(response));
4804 }
4805 if client.is_none() {
4806 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4807 let response = UnWatchResponseWrapper {
4808 success: false,
4809 error: error_msg,
4810 request_id: 0
4811 };
4812 return Box::into_raw(Box::new(response));
4813 }
4814 let client = client.unwrap();
4815 trace!("watchid: {:?}", watchid);
4816 let result = tokio::task::block_in_place(|| {
4817 let handle = client.get_runtime_handle();
4818 handle.block_on( client.unwatch(&watchid))
4819 });
4820 trace!("completed, parsing result");
4821 match result {
4822 Ok(_) => {
4823 let response = UnWatchResponseWrapper {
4824 success: true,
4825 error: std::ptr::null(),
4826 request_id: 0
4827 };
4828 debug!("Unwatch success");
4829 Box::into_raw(Box::new(response))
4830 }
4831 Err(e) => {
4832 let error_msg = CString::new(format!("Unwatch failed: {:?}", e))
4833 .unwrap()
4834 .into_raw();
4835 debug!("Unwatch failed: {:?}", error_msg);
4836 let response = UnWatchResponseWrapper {
4837 success: false,
4838 error: error_msg,
4839 request_id: 0
4840 };
4841 Box::into_raw(Box::new(response))
4842 }
4843 }
4844}
4845#[no_mangle]
4846#[tracing::instrument(skip_all)]
4847pub extern "C" fn unwatch_async(
4848 client: *mut ClientWrapper,
4849 watchid: *const c_char,
4850 request_id: i32,
4851 callback: extern "C" fn(*mut UnWatchResponseWrapper),
4852) {
4853 let client_wrapper = match safe_wrapper(client) {
4854 Some(client) => client,
4855 None => {
4856 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4857 let response = UnWatchResponseWrapper {
4858 success: false,
4859 error: error_msg,
4860 request_id,
4861 };
4862 return callback(Box::into_raw(Box::new(response)));
4863 }
4864 };
4865 let client = client_wrapper.client.clone();
4866 let watchid = c_char_to_str(watchid);
4867 if client.is_none() {
4868 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4869 let response = UnWatchResponseWrapper {
4870 success: false,
4871 error: error_msg,
4872 request_id,
4873 };
4874 return callback(Box::into_raw(Box::new(response)));
4875 }
4876 let client = client.unwrap();
4877 let handle = client.get_runtime_handle();
4878 handle.spawn(async move {
4879 let result = client.unwatch(&watchid).await;
4880 match result {
4881 Ok(_) => {
4882 let response = UnWatchResponseWrapper {
4883 success: true,
4884 error: std::ptr::null(),
4885 request_id,
4886 };
4887 callback(Box::into_raw(Box::new(response)));
4888 }
4889 Err(e) => {
4890 let error_msg = CString::new(format!("Unwatch failed: {:?}", e))
4891 .unwrap()
4892 .into_raw();
4893 let response = UnWatchResponseWrapper {
4894 success: false,
4895 error: error_msg,
4896 request_id,
4897 };
4898 callback(Box::into_raw(Box::new(response)));
4899 }
4900 }
4901 });
4902}
4903#[no_mangle]
4904#[tracing::instrument(skip_all)]
4905pub extern "C" fn free_unwatch_response(response: *mut UnWatchResponseWrapper) {
4906 if response.is_null() {
4907 return;
4908 }
4909 unsafe {
4910 if !(*response).error.is_null() {
4911 let _ = CString::from_raw((*response).error as *mut c_char);
4912 }
4913 let _ = Box::from_raw(response);
4914 }
4915}
4916
4917
4918#[repr(C)]
4919pub struct RegisterQueueRequestWrapper {
4920 queuename: *const c_char,
4921 request_id: i32
4922}
4923#[repr(C)]
4924pub struct RegisterQueueResponseWrapper {
4925 success: bool,
4926 queuename: *const c_char,
4927 error: *const c_char,
4928 request_id: i32
4929}
4930
4931#[no_mangle]
4932#[tracing::instrument(skip_all)]
4933pub extern "C" fn register_queue(
4934 client: *mut ClientWrapper,
4935 options: *mut RegisterQueueRequestWrapper,
4936) -> *mut RegisterQueueResponseWrapper {
4937 let options = match safe_wrapper(options) {
4938 Some(options) => options,
4939 None => {
4940 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4941 let response = RegisterQueueResponseWrapper {
4942 success: false,
4943 queuename: std::ptr::null(),
4944 error: error_msg,
4945 request_id: 0,
4946 };
4947 return Box::into_raw(Box::new(response));
4948 }
4949 };
4950 let client_wrapper = match safe_wrapper(client) {
4951 Some(client) => client,
4952 None => {
4953 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4954 let response = RegisterQueueResponseWrapper {
4955 success: false,
4956 queuename: std::ptr::null(),
4957 error: error_msg,
4958 request_id: options.request_id,
4959 };
4960 return Box::into_raw(Box::new(response));
4961 }
4962 };
4963 let client = client_wrapper.client.clone();
4964 let request = RegisterQueueRequest {
4966 queuename: c_char_to_str(options.queuename),
4967 };
4968 if client.is_none() {
4969 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4970 let response = RegisterQueueResponseWrapper {
4971 success: false,
4972 queuename: std::ptr::null(),
4973 error: error_msg,
4974 request_id: options.request_id,
4975 };
4976 return Box::into_raw(Box::new(response));
4977 }
4978 let client = client.unwrap();
4979 let result = tokio::task::block_in_place(|| {
4980 let handle = client.get_runtime_handle();
4981 handle.block_on(
4982 client
4983 .register_queue(
4984 request,
4985 std::sync::Arc::new(move |_client, event: QueueEvent| {
4986 trace!("queue: event: {:?}", event);
4987 let queuename = CString::new(event.queuename.clone())
4988 .unwrap()
4989 .into_string()
4990 .unwrap();
4991 let mut e = QUEUE_EVENTS.lock().unwrap();
4992 let queue = e.get_mut(&queuename);
4993 match queue {
4994 Some(q) => {
4995 q.push_back(event);
4996 }
4997 None => {
4998 let mut q = std::collections::VecDeque::new();
4999 q.push_back(event);
5000 e.insert(queuename, q);
5001 }
5002 }
5003 Box::pin(async { None })
5004 }),
5005 )
5006 )
5007 });
5008
5009 let response = match result {
5010 Ok(data) => {
5011 let id = String::from(&data);
5012 let mut events = QUEUE_EVENTS.lock().unwrap();
5013 let queue = events.get_mut(&id);
5014 if queue.is_none() {
5015 let q = std::collections::VecDeque::new();
5016 let k = String::from(&data);
5017 events.insert(k, q);
5018 }
5019 let queuename = CString::new(id).unwrap().into_raw();
5020 RegisterQueueResponseWrapper {
5021 success: true,
5022 queuename,
5023 error: std::ptr::null(),
5024 request_id: options.request_id,
5025 }
5026 }
5027 Err(e) => {
5028 let error_msg = CString::new(format!("queue failed: {:?}", e))
5029 .unwrap()
5030 .into_raw();
5031 RegisterQueueResponseWrapper {
5032 success: false,
5033 queuename: std::ptr::null(),
5034 error: error_msg,
5035 request_id: options.request_id,
5036 }
5037 }
5038 };
5039 Box::into_raw(Box::new(response))
5040}
5041
5042type QueueEventCallback = extern "C" fn(*mut QueueEventWrapper) -> *const c_char;
5043#[no_mangle]
5044#[tracing::instrument(skip_all)]
5045pub extern "C" fn register_queue_async(
5046 client: *mut ClientWrapper,
5047 options: *mut RegisterQueueRequestWrapper,
5048 event_callback: QueueEventCallback,
5049) -> *mut RegisterQueueResponseWrapper {
5050 debug!("register_queue_async");
5051 let options = match safe_wrapper(options) {
5052 Some(options) => options,
5053 None => {
5054 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5055 let response = RegisterQueueResponseWrapper {
5056 success: false,
5057 queuename: std::ptr::null(),
5058 error: error_msg,
5059 request_id: 0,
5060 };
5061 return Box::into_raw(Box::new(response))
5062 }
5063 };
5064 let client_wrapper = match safe_wrapper(client) {
5065 Some(client) => client,
5066 None => {
5067 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5068 let response = RegisterQueueResponseWrapper {
5069 success: false,
5070 queuename: std::ptr::null(),
5071 error: error_msg,
5072 request_id: options.request_id,
5073 };
5074 return Box::into_raw(Box::new(response))
5075 }
5076 };
5077 let client = client_wrapper.client.clone();
5078 let request = RegisterQueueRequest {
5079 queuename: c_char_to_str(options.queuename),
5080 };
5081 if client.is_none() {
5082 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5083 let response = RegisterQueueResponseWrapper {
5084 success: false,
5085 queuename: std::ptr::null(),
5086 error: error_msg,
5087 request_id: options.request_id,
5088 };
5089 return Box::into_raw(Box::new(response))
5090 }
5091 let client = client.unwrap();
5092 debug!("register_queue_async: runtime.spawn");
5093 let request_id = options.request_id;
5094 let result = tokio::task::block_in_place(|| {
5095 let handle = client.get_runtime_handle();
5096 handle.block_on(
5097 client
5098 .register_queue(
5099 request,
5100 std::sync::Arc::new(move |_client, event: QueueEvent| {
5101 debug!("register_queue_async: spawn new task, to call event_callback");
5102 trace!("register_queue_async: call event_callback");
5103 let queuename = CString::new(event.queuename).unwrap().into_raw();
5104 let correlation_id = CString::new(event.correlation_id).unwrap().into_raw();
5105 let replyto = CString::new(event.replyto).unwrap().into_raw();
5106 let routingkey = CString::new(event.routingkey).unwrap().into_raw();
5107 let exchangename = CString::new(event.exchangename).unwrap().into_raw();
5108 let data = CString::new(event.data).unwrap().into_raw();
5109 let event = Box::new(QueueEventWrapper {
5110 queuename,
5111 correlation_id,
5112 replyto,
5113 routingkey,
5114 exchangename,
5115 data,
5116 request_id
5117 });
5118 let result = event_callback(Box::into_raw(event));
5119 let result = c_char_to_str(result);
5120 if result.is_empty() {
5121 return Box::pin(async { None })
5122 }
5123 let result = result.to_string();
5124 Box::pin(async { Some(result) })
5125 }),
5126 )
5127 )
5128 });
5129
5130 debug!("register_queue_async: parse result");
5131 let response = match result {
5132 Ok(data) => {
5133 let queuename = CString::new(data).unwrap().into_raw();
5134 RegisterQueueResponseWrapper {
5135 success: true,
5136 queuename,
5137 error: std::ptr::null(),
5138 request_id: options.request_id,
5139 }
5140 }
5141 Err(e) => {
5142 let error_msg = CString::new(format!("RegisterQueue failed: {:?}", e))
5143 .unwrap()
5144 .into_raw();
5145 RegisterQueueResponseWrapper {
5146 success: false,
5147 queuename: std::ptr::null(),
5148 error: error_msg,
5149 request_id: options.request_id,
5150 }
5151 }
5152 };
5153
5154 Box::into_raw(Box::new(response))
5155}
5156
5157
5158
5159#[no_mangle]
5160#[tracing::instrument(skip_all)]
5161pub extern "C" fn free_register_queue_response(response: *mut RegisterQueueResponseWrapper) {
5162 if response.is_null() {
5163 return;
5164 }
5165 unsafe {
5166 if !(*response).error.is_null() {
5167 let _ = CString::from_raw((*response).error as *mut c_char);
5168 }
5169 if !(*response).queuename.is_null() {
5170 let _ = CString::from_raw((*response).queuename as *mut c_char);
5171 }
5172 let _ = Box::from_raw(response);
5173 }
5174}
5175
5176
5177#[repr(C)]
5178pub struct RegisterExchangeRequestWrapper {
5179 exchangename: *const c_char,
5180 algorithm: *const c_char,
5181 routingkey: *const c_char,
5182 addqueue: bool,
5183 request_id: i32
5184}
5185#[repr(C)]
5186pub struct RegisterExchangeResponseWrapper {
5187 success: bool,
5188 queuename: *const c_char,
5189 error: *const c_char,
5190 request_id: i32
5191}
5192#[no_mangle]
5193#[tracing::instrument(skip_all)]
5194pub extern "C" fn register_exchange (
5195 client: *mut ClientWrapper,
5196 options: *mut RegisterExchangeRequestWrapper,
5197) -> *mut RegisterExchangeResponseWrapper {
5198 let options = match safe_wrapper(options) {
5199 Some(options) => options,
5200 None => {
5201 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5202 let response = RegisterExchangeResponseWrapper {
5203 success: false,
5204 queuename: std::ptr::null(),
5205 error: error_msg,
5206 request_id: 0,
5207 };
5208 return Box::into_raw(Box::new(response));
5209 }
5210 };
5211 let client_wrapper = match safe_wrapper(client) {
5212 Some(client) => client,
5213 None => {
5214 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5215 let response = RegisterExchangeResponseWrapper {
5216 success: false,
5217 queuename: std::ptr::null(),
5218 error: error_msg,
5219 request_id: options.request_id,
5220 };
5221 return Box::into_raw(Box::new(response));
5222 }
5223 };
5224 let client = client_wrapper.client.clone();
5225 let request = RegisterExchangeRequest {
5226 exchangename: c_char_to_str(options.exchangename),
5227 algorithm: c_char_to_str(options.algorithm),
5228 routingkey: c_char_to_str(options.routingkey),
5229 addqueue: options.addqueue,
5230 };
5231 if client.is_none() {
5232 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5233 let response = RegisterExchangeResponseWrapper {
5234 success: false,
5235 queuename: std::ptr::null(),
5236 error: error_msg,
5237 request_id: options.request_id,
5238 };
5239 return Box::into_raw(Box::new(response));
5240 }
5241 let client = client.unwrap();
5242 let result = tokio::task::block_in_place(|| {
5243 let handle = client.get_runtime_handle();
5244 handle.block_on(
5245 client
5246 .register_exchange(request,
5247 std::sync::Arc::new(move |_client, event: QueueEvent| {
5248 trace!("exchange: event: {:?}", event);
5249 let queuename = CString::new(event.queuename.clone())
5250 .unwrap()
5251 .into_string()
5252 .unwrap();
5253 let mut e = QUEUE_EVENTS.lock().unwrap();
5254 let queue = e.get_mut(&queuename);
5255 match queue {
5256 Some(q) => {
5257 q.push_back(event);
5258 }
5259 None => {
5260 let mut q = std::collections::VecDeque::new();
5261 q.push_back(event);
5262 e.insert(queuename, q);
5263 }
5264 }
5265 Box::pin(async { None })
5266 }),
5267
5268 )
5269 )
5270 });
5271
5272 let response = match result {
5273 Ok(data) => {
5274 let queuename = CString::new(data).unwrap().into_raw();
5275 RegisterExchangeResponseWrapper {
5276 success: true,
5277 queuename,
5278 error: std::ptr::null(),
5279 request_id: options.request_id,
5280 }
5281 }
5282 Err(e) => {
5283 let error_msg = CString::new(format!("RegisterExchange failed: {:?}", e))
5284 .unwrap()
5285 .into_raw();
5286 RegisterExchangeResponseWrapper {
5287 success: false,
5288 queuename: std::ptr::null(),
5289 error: error_msg,
5290 request_id: options.request_id,
5291 }
5292 }
5293 };
5294
5295 Box::into_raw(Box::new(response))
5296}
5297type ExchangeEventCallback = extern "C" fn(*mut QueueEventWrapper);
5298#[no_mangle]
5299#[tracing::instrument(skip_all)]
5300pub extern "C" fn register_exchange_async(
5301 client: *mut ClientWrapper,
5302 options: *mut RegisterExchangeRequestWrapper,
5303 event_callback: ExchangeEventCallback,
5304) -> *mut RegisterExchangeResponseWrapper {
5305 debug!("register_exchange_async");
5306 let options = match safe_wrapper(options) {
5307 Some(options) => options,
5308 None => {
5309 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5310 let response = RegisterExchangeResponseWrapper {
5311 success: false,
5312 queuename: std::ptr::null(),
5313 error: error_msg,
5314 request_id: 0,
5315 };
5316 return Box::into_raw(Box::new(response))
5317 }
5318 };
5319 let client_wrapper = match safe_wrapper(client) {
5320 Some(client) => client,
5321 None => {
5322 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5323 let response = RegisterExchangeResponseWrapper {
5324 success: false,
5325 queuename: std::ptr::null(),
5326 error: error_msg,
5327 request_id: options.request_id,
5328 };
5329 return Box::into_raw(Box::new(response))
5330 }
5331 };
5332 let client = client_wrapper.client.clone();
5333 let request = RegisterExchangeRequest {
5334 exchangename: c_char_to_str(options.exchangename),
5335 algorithm: c_char_to_str(options.algorithm),
5336 routingkey: c_char_to_str(options.routingkey),
5337 addqueue: options.addqueue,
5338 };
5339 if client.is_none() {
5340 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5341 let response = RegisterExchangeResponseWrapper {
5342 success: false,
5343 queuename: std::ptr::null(),
5344 error: error_msg,
5345 request_id: options.request_id,
5346 };
5347 return Box::into_raw(Box::new(response))
5348 }
5349 let client = client.unwrap();
5350 debug!("register_exchange_async: runtime.spawn");
5351 let request_id = options.request_id;
5352 let result = tokio::task::block_in_place(|| {
5353 let handle = client.get_runtime_handle();
5354 handle.block_on(
5355 client
5356 .register_exchange(request,
5357 std::sync::Arc::new(move |_client, event: QueueEvent| {
5358 debug!("register_exchange_async: spawn new task, to call event_callback");
5359 trace!("register_exchange_async: call event_callback");
5360 let queuename = CString::new(event.queuename).unwrap().into_raw();
5361 let correlation_id = CString::new(event.correlation_id).unwrap().into_raw();
5362 let replyto = CString::new(event.replyto).unwrap().into_raw();
5363 let routingkey = CString::new(event.routingkey).unwrap().into_raw();
5364 let exchangename = CString::new(event.exchangename).unwrap().into_raw();
5365 let data = CString::new(event.data).unwrap().into_raw();
5366 let event = Box::new(QueueEventWrapper {
5367 queuename,
5368 correlation_id,
5369 replyto,
5370 routingkey,
5371 exchangename,
5372 data,
5373 request_id
5374 });
5375 event_callback(Box::into_raw(event));
5376 Box::pin(async { None })
5377 }),
5378
5379 )
5380 )
5381 });
5382
5383 debug!("register_exchange_async: parse result");
5384 let response = match result {
5385 Ok(data) => {
5386 let queuename = CString::new(data).unwrap().into_raw();
5387 RegisterExchangeResponseWrapper {
5388 success: true,
5389 queuename,
5390 error: std::ptr::null(),
5391 request_id: options.request_id,
5392 }
5393 }
5394 Err(e) => {
5395 let error_msg = CString::new(format!("RegisterExchange failed: {:?}", e))
5396 .unwrap()
5397 .into_raw();
5398 RegisterExchangeResponseWrapper {
5399 success: false,
5400 queuename: std::ptr::null(),
5401 error: error_msg,
5402 request_id: options.request_id,
5403 }
5404 }
5405 };
5406 Box::into_raw(Box::new(response))
5407}
5408
5409#[no_mangle]
5410#[tracing::instrument(skip_all)]
5411pub extern "C" fn free_register_exchange_response(response: *mut RegisterExchangeResponseWrapper) {
5412 if response.is_null() {
5413 return;
5414 }
5415 unsafe {
5416 if !(*response).error.is_null() {
5417 let _ = CString::from_raw((*response).error as *mut c_char);
5418 }
5419 if !(*response).queuename.is_null() {
5420 let _ = CString::from_raw((*response).queuename as *mut c_char);
5421 }
5422 let _ = Box::from_raw(response);
5423 }
5424}
5425
5426#[repr(C)]
5427#[derive(Debug, Clone)]
5428pub struct QueueEventWrapper {
5429 queuename: *const c_char,
5430 correlation_id: *const c_char,
5431 replyto: *const c_char,
5432 routingkey: *const c_char,
5433 exchangename: *const c_char,
5434 data: *const c_char,
5435 request_id: i32,
5436}
5437impl Default for QueueEventWrapper {
5438 fn default() -> Self {
5439 QueueEventWrapper {
5440 queuename: std::ptr::null(),
5441 correlation_id: std::ptr::null(),
5442 replyto: std::ptr::null(),
5443 routingkey: std::ptr::null(),
5444 exchangename: std::ptr::null(),
5445 data: std::ptr::null(),
5446 request_id: 0,
5447 }
5448 }
5449}
5450
5451#[no_mangle]
5452#[tracing::instrument(skip_all)]
5453pub extern "C" fn next_queue_event (
5454 queuename: *const c_char,
5455) -> *mut QueueEventWrapper {
5456 trace!("unwrap watchid");
5457 let queuename = c_char_to_str(queuename);
5458 trace!("queuename {:}", queuename);
5459 let queuename = queuename.to_string();
5460 trace!("unwrap events");
5461 let mut e = QUEUE_EVENTS.lock().unwrap();
5462 trace!("get queue");
5463 let queue = e.get_mut(&queuename);
5464 match queue {
5465 Some(q) => {
5466 match q.pop_front() {
5467 Some(event) => {
5468 debug!("got event");
5469 let queuename = CString::new(event.queuename).unwrap().into_raw();
5470 let correlation_id = CString::new(event.correlation_id).unwrap().into_raw();
5471 let replyto = CString::new(event.replyto).unwrap().into_raw();
5472 let routingkey = CString::new(event.routingkey).unwrap().into_raw();
5473 let exchangename = CString::new(event.exchangename).unwrap().into_raw();
5474 let data = CString::new(event.data).unwrap().into_raw();
5475 let event = Box::new(QueueEventWrapper {
5476 queuename,
5477 correlation_id,
5478 replyto,
5479 routingkey,
5480 exchangename,
5481 data,
5482 request_id: 0
5483 });
5484 Box::into_raw(event)
5485 }
5486 None => {
5487 trace!("No event");
5488 Box::into_raw(Box::new(QueueEventWrapper::default()))
5489 },
5490 }
5491 },
5492 None => {
5493 debug!("Queue for {:} not found", queuename);
5494 Box::into_raw(Box::new(QueueEventWrapper::default()))
5495 },
5496 }
5497}
5498#[no_mangle]
5499#[tracing::instrument(skip_all)]
5500pub extern "C" fn free_queue_event(response: *mut QueueEventWrapper) {
5501 if response.is_null() {
5502 return;
5503 }
5504 unsafe {
5505 if !(*response).queuename.is_null() {
5506 let _ = CString::from_raw((*response).queuename as *mut c_char);
5507 }
5508 if !(*response).correlation_id.is_null() {
5509 let _ = CString::from_raw((*response).correlation_id as *mut c_char);
5510 }
5511 if !(*response).replyto.is_null() {
5512 let _ = CString::from_raw((*response).replyto as *mut c_char);
5513 }
5514 if !(*response).routingkey.is_null() {
5515 let _ = CString::from_raw((*response).routingkey as *mut c_char);
5516 }
5517 if !(*response).exchangename.is_null() {
5518 let _ = CString::from_raw((*response).exchangename as *mut c_char);
5519 }
5520 if !(*response).data.is_null() {
5521 let _ = CString::from_raw((*response).data as *mut c_char);
5522 }
5523 let _ = Box::from_raw(response);
5524 }
5525}
5526
5527#[repr(C)]
5528pub struct QueueMessageRequestWrapper {
5529 queuename: *const c_char,
5530 correlation_id: *const c_char,
5531 replyto: *const c_char,
5532 routingkey: *const c_char,
5533 exchangename: *const c_char,
5534 data: *const c_char,
5535 striptoken: bool,
5536 expiration: i32,
5537 request_id: i32,
5538}
5539#[repr(C)]
5540pub struct QueueMessageResponseWrapper {
5541 success: bool,
5542 error: *const c_char,
5543}
5544#[no_mangle]
5545#[tracing::instrument(skip_all)]
5546pub extern "C" fn queue_message(
5547 client: *mut ClientWrapper,
5548 options: *mut QueueMessageRequestWrapper,
5549) -> *mut QueueMessageResponseWrapper {
5550 let options = match safe_wrapper(options) {
5551 Some(options) => options,
5552 None => {
5553 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5554 let response = QueueMessageResponseWrapper {
5555 success: false,
5556 error: error_msg,
5557 };
5558 return Box::into_raw(Box::new(response));
5559 }
5560 };
5561 let client_wrapper = match safe_wrapper(client) {
5562 Some(client) => client,
5563 None => {
5564 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5565 let response = QueueMessageResponseWrapper {
5566 success: false,
5567 error: error_msg,
5568 };
5569 return Box::into_raw(Box::new(response));
5570 }
5571 };
5572 let client = client_wrapper.client.clone();
5573 let request = QueueMessageRequest {
5574 queuename: c_char_to_str(options.queuename),
5575 correlation_id: c_char_to_str(options.correlation_id),
5576 replyto: c_char_to_str(options.replyto),
5577 routingkey: c_char_to_str(options.routingkey),
5578 exchangename: c_char_to_str(options.exchangename),
5579 data: c_char_to_str(options.data),
5580 striptoken: options.striptoken,
5581 expiration: options.expiration,
5582 };
5583 if client.is_none() {
5584 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5585 let response = QueueMessageResponseWrapper {
5586 success: false,
5587 error: error_msg,
5588 };
5589 return Box::into_raw(Box::new(response));
5590 }
5591 let client = client.unwrap();
5592 let result = tokio::task::block_in_place(|| {
5593 let handle = client.get_runtime_handle();
5594 handle.block_on(
5595 client
5596 .queue_message(request)
5597 )
5598 });
5599 match result {
5600 Ok(_) => {
5601 let response = QueueMessageResponseWrapper {
5602 success: true,
5603 error: std::ptr::null(),
5604 };
5605 Box::into_raw(Box::new(response))
5606 }
5607 Err(e) => {
5608 let error_msg = CString::new(format!("Queue message failed: {:?}", e))
5609 .unwrap()
5610 .into_raw();
5611 let response = QueueMessageResponseWrapper {
5612 success: false,
5613 error: error_msg,
5614 };
5615 Box::into_raw(Box::new(response))
5616 }
5617 }
5618}
5619#[no_mangle]
5620#[tracing::instrument(skip_all)]
5621pub extern "C" fn free_queue_message_response(response: *mut QueueMessageResponseWrapper) {
5622 if response.is_null() {
5623 return;
5624 }
5625 unsafe {
5626 if !(*response).error.is_null() {
5627 let _ = CString::from_raw((*response).error as *mut c_char);
5628 }
5629 let _ = Box::from_raw(response);
5630 }
5631}
5632
5633#[repr(C)]
5634pub struct UnRegisterQueueResponseWrapper {
5635 success: bool,
5636 error: *const c_char,
5637}
5638#[no_mangle]
5639#[tracing::instrument(skip_all)]
5640pub extern "C" fn unregister_queue(
5641 client: *mut ClientWrapper,
5642 queuename: *const c_char,
5643) -> *mut UnRegisterQueueResponseWrapper {
5644 let client_wrapper = match safe_wrapper(client) {
5645 Some(client) => client,
5646 None => {
5647 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5648 let response = UnRegisterQueueResponseWrapper {
5649 success: false,
5650 error: error_msg,
5651 };
5652 return Box::into_raw(Box::new(response));
5653 }
5654 };
5655 let client = client_wrapper.client.clone();
5656 let queuename = c_char_to_str(queuename);
5657 if client.is_none() {
5658 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5659 let response = UnRegisterQueueResponseWrapper {
5660 success: false,
5661 error: error_msg,
5662 };
5663 return Box::into_raw(Box::new(response));
5664 }
5665 let client = client.unwrap();
5666 let result = tokio::task::block_in_place(|| {
5667 let handle = client.get_runtime_handle();
5668 handle.block_on( client.unregister_queue(&queuename))
5669 });
5670 match result {
5671 Ok(_) => {
5672 let response = UnRegisterQueueResponseWrapper {
5673 success: true,
5674 error: std::ptr::null(),
5675 };
5676 Box::into_raw(Box::new(response))
5677 }
5678 Err(e) => {
5679 let error_msg = CString::new(format!("Unregister queue failed: {:?}", e))
5680 .unwrap()
5681 .into_raw();
5682 let response = UnRegisterQueueResponseWrapper {
5683 success: false,
5684 error: error_msg,
5685 };
5686 Box::into_raw(Box::new(response))
5687 }
5688 }
5689}
5690#[no_mangle]
5691#[tracing::instrument(skip_all)]
5692pub extern "C" fn free_unregister_queue_response(response: *mut UnRegisterQueueResponseWrapper) {
5693 if response.is_null() {
5694 return;
5695 }
5696 unsafe {
5697 if !(*response).error.is_null() {
5698 let _ = CString::from_raw((*response).error as *mut c_char);
5699 }
5700 let _ = Box::from_raw(response);
5701 }
5702}
5703
5704
5705
5706#[repr(C)]
5707#[derive(Debug, Clone)]
5708pub struct WorkitemFileWrapper {
5709 filename: *const c_char,
5710 id: *const c_char,
5711 compressed: bool,
5712 }
5714impl WorkitemFileWrapper {
5715 pub fn new(filename: &str, id: &str, compressed: bool) -> Self {
5716 trace!("filename: {:?}", filename);
5717 let filename = CString::new(filename).unwrap().into_raw();
5718 trace!("filename: {:?}", filename);
5719 trace!("id: {:?}", id);
5720 let id = CString::new(id).unwrap().into_raw();
5721 trace!("id: {:?}", id);
5722 WorkitemFileWrapper {
5724 filename,
5725 id,
5726 compressed,
5728 }
5729 }
5738}
5739
5740#[repr(C)]
5741#[derive(Debug, Clone)]
5742pub struct WorkitemWrapper {
5743 id: *const c_char,
5744 name: *const c_char,
5745 payload: *const c_char,
5746 priority: i32,
5747 nextrun: u64,
5748 lastrun: u64,
5749 files: *const *const WorkitemFileWrapper,
5750 files_len: i32,
5751 state: *const c_char,
5752 wiq: *const c_char,
5753 wiqid: *const c_char,
5754 retries: i32,
5755 username: *const c_char,
5756 success_wiqid: *const c_char,
5757 failed_wiqid: *const c_char,
5758 success_wiq: *const c_char,
5759 failed_wiq: *const c_char,
5760 errormessage: *const c_char,
5761 errorsource: *const c_char,
5762 errortype: *const c_char,
5763}
5764impl WorkitemWrapper {
5765 #[tracing::instrument(skip_all)]
5766 pub fn as_workitem(&self) -> Workitem {
5767 let files_len = self.files_len;
5768 let mut files: Vec<WorkitemFile> = vec![];
5769 if files_len > 0 {
5770 let _files = unsafe { &*self.files };
5771 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
5772 files = _files.iter().map(|f| {
5773 let file = unsafe { &**f };
5774 WorkitemFile {
5775 filename: c_char_to_str(file.filename),
5776 id: c_char_to_str(file.id),
5777 ..Default::default()
5778 }
5781 }).collect();
5782 }
5783 trace!("nextrun: {:?}", self.nextrun);
5784 let mut nextrun = Some(Timestamp::from(
5786 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(self.nextrun)
5787 ));
5788 trace!("nextrun: {:?}", nextrun);
5789 if self.nextrun == 0 {
5790 nextrun = None;
5791 }
5792 trace!("lastrun: {:?}", self.lastrun);
5793 let mut lastrun = Some(Timestamp::from(
5795 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(self.lastrun)
5796 ));
5797 trace!("lastrun: {:?}", lastrun);
5798 if self.lastrun == 0 {
5799 lastrun = None;
5800 }
5801 Workitem {
5802 id: c_char_to_str(self.id),
5803 name: c_char_to_str(self.name),
5804 payload: c_char_to_str(self.payload),
5805 priority: self.priority,
5806 nextrun,
5807 lastrun,
5808 files,
5809 state: c_char_to_str(self.state),
5810 wiq: c_char_to_str(self.wiq),
5811 wiqid: c_char_to_str(self.wiqid),
5812 retries: self.retries,
5813 username: c_char_to_str(self.username),
5814 success_wiqid: c_char_to_str(self.success_wiqid),
5815 failed_wiqid: c_char_to_str(self.failed_wiqid),
5816 success_wiq: c_char_to_str(self.success_wiq),
5817 failed_wiq: c_char_to_str(self.failed_wiq),
5818 errormessage: c_char_to_str(self.errormessage),
5819 errorsource: c_char_to_str(self.errorsource),
5820 errortype: c_char_to_str(self.errortype),
5821 }
5822 }
5823}
5824#[tracing::instrument(skip_all)]
5825pub fn wrap_workitem(workitem: Workitem ) -> WorkitemWrapper {
5826 trace!("parse workitem: {:?}", workitem);
5827 let id = CString::new(workitem.id).unwrap().into_raw();
5828 let name = CString::new(workitem.name).unwrap().into_raw();
5829 let payload = CString::new(workitem.payload).unwrap().into_raw();
5830 let state = CString::new(workitem.state).unwrap().into_raw();
5831 let wiq = CString::new(workitem.wiq).unwrap().into_raw();
5832 let wiqid = CString::new(workitem.wiqid).unwrap().into_raw();
5833 let username = CString::new(workitem.username).unwrap().into_raw();
5834 let success_wiqid = CString::new(workitem.success_wiqid).unwrap().into_raw();
5835 let failed_wiqid = CString::new(workitem.failed_wiqid).unwrap().into_raw();
5836 let success_wiq = CString::new(workitem.success_wiq).unwrap().into_raw();
5837 let failed_wiq = CString::new(workitem.failed_wiq).unwrap().into_raw();
5838 let errormessage = CString::new(workitem.errormessage).unwrap().into_raw();
5839 let errorsource = CString::new(workitem.errorsource).unwrap().into_raw();
5840 let errortype = CString::new(workitem.errortype).unwrap().into_raw();
5841 let mut files: Vec<*const WorkitemFileWrapper> = vec![];
5842 for f in &workitem.files {
5843 let file = Box::into_raw(Box::new(WorkitemFileWrapper::new(&f.filename, &f.id, f.compressed)));
5855 files.push(file);
5856 }
5857 trace!("files: {:?} at {:?}", files.len(), files);
5858 trace!("read nextrun");
5859 let nextrun = workitem.nextrun.map(|t| t.seconds as u64).unwrap_or(0);
5860 trace!("nextrun: {:?}", nextrun);
5861 let lastrun = workitem.lastrun.map(|t| t.seconds as u64).unwrap_or(0);
5862 trace!("lastrun: {:?}", lastrun);
5863 let _files = files.as_ptr();
5864 trace!("files: {:?}", files);
5865 let files_len = workitem.files.len() as i32;
5866 trace!("files_len: {:?}", files_len);
5867 let workitem = WorkitemWrapper {
5868 id,
5869 name,
5870 payload,
5871 priority: workitem.priority,
5872 nextrun,
5873 lastrun,
5874 files: _files,
5875 files_len,
5876 state,
5877 wiq,
5878 wiqid,
5879 retries: workitem.retries,
5880 username,
5881 success_wiqid,
5882 failed_wiqid,
5883 success_wiq,
5884 failed_wiq,
5885 errormessage,
5886 errorsource,
5887 errortype,
5888 };
5889 trace!("forget files");
5890 std::mem::forget(files);
5891 trace!("return workitem");
5892 workitem
5893}
5894#[repr(C)]
5895#[derive(Debug, Clone)]
5896pub struct PushWorkitemRequestWrapper {
5897 wiq: *const c_char,
5898 wiqid: *const c_char,
5899 name: *const c_char,
5900 payload: *const c_char,
5901 nextrun: u64,
5902 success_wiqid: *const c_char,
5903 failed_wiqid: *const c_char,
5904 success_wiq: *const c_char,
5905 failed_wiq: *const c_char,
5906 priority: i32,
5907 files: *const *const WorkitemFileWrapper,
5908 files_len: i32,
5909 request_id: i32
5910}
5911#[repr(C)]
5912#[derive(Debug, Clone)]
5913pub struct PushWorkitemResponseWrapper {
5914 success: bool,
5915 error: *const c_char,
5916 workitem: *const WorkitemWrapper,
5917 request_id: i32
5918}
5919#[no_mangle]
5920#[tracing::instrument(skip_all)]
5921pub extern "C" fn push_workitem(
5922 client: *mut ClientWrapper,
5923 options: *mut PushWorkitemRequestWrapper,
5924) -> *mut PushWorkitemResponseWrapper {
5925 let options = match safe_wrapper(options) {
5926 Some(options) => options,
5927 None => {
5928 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5929 let response = PushWorkitemResponseWrapper {
5930 success: false,
5931 error: error_msg,
5932 workitem: std::ptr::null(),
5933 request_id: 0
5934 };
5935 return Box::into_raw(Box::new(response));
5936 }
5937 };
5938 let client_wrapper = match safe_wrapper(client) {
5939 Some(client) => client,
5940 None => {
5941 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5942 let response = PushWorkitemResponseWrapper {
5943 success: false,
5944 error: error_msg,
5945 workitem: std::ptr::null(),
5946 request_id: options.request_id
5947 };
5948 return Box::into_raw(Box::new(response));
5949 }
5950 };
5951 let client = client_wrapper.client.clone();
5952 let files_len = options.files_len;
5953 debug!("files_len: {:?}", files_len);
5954 let mut files: Vec<WorkitemFile> = vec![];
5955 if files_len > 0 {
5956 debug!("get files of options");
5957 let _files = unsafe { &*options.files };
5958 debug!("slice files");
5959 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
5960 debug!("loop files");
5961 files = _files.iter().map(|f| {
5962 debug!("process a file");
5963 let file = unsafe { &**f };
5964 debug!("create WorkitemFile instance");
5965 let filename = c_char_to_str(file.filename);
5966 trace!("filename: {:?}", filename);
5967 let id = c_char_to_str(file.id);
5968 trace!("id: {:?}", id);
5969 trace!("compressed: {:?}", file.compressed);
5970 WorkitemFile {
5971 filename,
5972 id,
5973 compressed: file.compressed,
5974 ..Default::default()
5975 }
5977 }).collect();
5978 }
5979 trace!("nextrun: {:?}", options.nextrun);
5980 let mut nextrun = Some(Timestamp::from(
5982 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(options.nextrun as u64)
5983 ));
5984 trace!("nextrun: {:?}", nextrun);
5985 if options.nextrun == 0 {
5986 nextrun = None;
5987 }
5988 let request = PushWorkitemRequest {
5989 wiq: c_char_to_str(options.wiq),
5990 wiqid: c_char_to_str(options.wiqid),
5991 name: c_char_to_str(options.name),
5992 payload: c_char_to_str(options.payload),
5993 nextrun,
5994 success_wiqid: c_char_to_str(options.success_wiqid),
5995 failed_wiqid: c_char_to_str(options.failed_wiqid),
5996 success_wiq: c_char_to_str(options.success_wiq),
5997 failed_wiq: c_char_to_str(options.failed_wiq),
5998 priority: options.priority,
5999 files,
6000 };
6001 if client.is_none() {
6002 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6003 let response = PushWorkitemResponseWrapper {
6004 success: false,
6005 error: error_msg,
6006 workitem: std::ptr::null(),
6007 request_id: options.request_id
6008 };
6009 return Box::into_raw(Box::new(response));
6010 }
6011 let client = client.unwrap();
6012 let result = tokio::task::block_in_place(|| {
6013 let handle = client.get_runtime_handle();
6014 handle.block_on(client
6015 .push_workitem(request)
6016 )
6017 });
6018
6019 match result {
6020 Ok(resp) => {
6021 Box::into_raw(Box::new(match resp.workitem {
6022 Some(workitem) => {
6023 let workitem = wrap_workitem(workitem);
6024 PushWorkitemResponseWrapper {
6025 success: true,
6026 error: std::ptr::null(),
6027 workitem: Box::into_raw(Box::new(workitem)),
6028 request_id: options.request_id
6029 }
6030 }
6031 None => {
6032 let error_msg = CString::new("Push workitem failed: workitem not found").unwrap().into_raw();
6033 PushWorkitemResponseWrapper {
6034 success: false,
6035 error: error_msg,
6036 workitem: std::ptr::null(),
6037 request_id: options.request_id
6038 }
6039 }
6040 }))
6041 }
6042 Err(e) => {
6043 let error_msg = CString::new(format!("Push workitem failed: {:?}", e))
6044 .unwrap()
6045 .into_raw();
6046 Box::into_raw(Box::new(PushWorkitemResponseWrapper {
6047 success: false,
6048 error: error_msg,
6049 workitem: std::ptr::null(),
6050 request_id: options.request_id
6051 }))
6052 }
6053 }
6054}
6055#[no_mangle]
6056#[tracing::instrument(skip_all)]
6057pub extern "C" fn push_workitem_async(
6058 client: *mut ClientWrapper,
6059 options: *mut PushWorkitemRequestWrapper,
6060 callback: extern "C" fn(*mut PushWorkitemResponseWrapper),
6061) {
6062 let options = match safe_wrapper(options) {
6063 Some(options) => options,
6064 None => {
6065 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6066 let response = PushWorkitemResponseWrapper {
6067 success: false,
6068 error: error_msg,
6069 workitem: std::ptr::null(),
6070 request_id: 0
6071 };
6072 return callback(Box::into_raw(Box::new(response)));
6073 }
6074 };
6075 let client_wrapper = match safe_wrapper(client) {
6076 Some(client) => client,
6077 None => {
6078 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6079 let response = PushWorkitemResponseWrapper {
6080 success: false,
6081 error: error_msg,
6082 workitem: std::ptr::null(),
6083 request_id: options.request_id
6084 };
6085 return callback(Box::into_raw(Box::new(response)));
6086 }
6087 };
6088 let client = client_wrapper.client.clone();
6089 let files_len = options.files_len;
6090 debug!("files_len: {:?}", files_len);
6091 let mut files: Vec<WorkitemFile> = vec![];
6092 if files_len > 0 {
6093 debug!("get files of options");
6094 let _files = unsafe { &*options.files };
6095 debug!("slice files");
6096 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
6097 debug!("loop files");
6098 files = _files.iter().map(|f| {
6099 debug!("process a file");
6100 let file = unsafe { &**f };
6101 debug!("create WorkitemFile instance 2");
6102 let filename = c_char_to_str(file.filename);
6103 debug!("filename: {:?}", filename);
6104 let id = c_char_to_str(file.id);
6105 debug!("id: {:?}", id);
6106 let compressed = file.compressed;
6107 debug!("compressed: {:?}", compressed);
6108 WorkitemFile {
6109 filename: c_char_to_str(file.filename),
6110 id: c_char_to_str(file.id),
6111 compressed: file.compressed,
6112 ..Default::default()
6113 }
6115 }).collect();
6116 }
6117 trace!("nextrun: {:?}", options.nextrun);
6118 let mut nextrun = Some(Timestamp::from(
6120 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(options.nextrun as u64)
6121 ));
6122 trace!("nextrun: {:?}", nextrun);
6123 if options.nextrun == 0 {
6124 nextrun = None;
6125 }
6126 let request = PushWorkitemRequest {
6127 wiq: c_char_to_str(options.wiq),
6128 wiqid: c_char_to_str(options.wiqid),
6129 name: c_char_to_str(options.name),
6130 payload: c_char_to_str(options.payload),
6131 nextrun,
6132 success_wiqid: c_char_to_str(options.success_wiqid),
6133 failed_wiqid: c_char_to_str(options.failed_wiqid),
6134 success_wiq: c_char_to_str(options.success_wiq),
6135 failed_wiq: c_char_to_str(options.failed_wiq),
6136 priority: options.priority,
6137 files,
6138 };
6139 if client.is_none() {
6140 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6141 let response = PushWorkitemResponseWrapper {
6142 success: false,
6143 error: error_msg,
6144 workitem: std::ptr::null(),
6145 request_id: options.request_id
6146 };
6147 return callback(Box::into_raw(Box::new(response)));
6148 }
6149 let client = client.unwrap();
6150 let handle = client.get_runtime_handle();
6151 let request_id = options.request_id;
6152 handle.spawn(async move {
6153 let result = client
6154 .push_workitem(request)
6155 .await;
6156 let response = match result {
6157 Ok(resp) => {
6158 match resp.workitem {
6159 Some(workitem) => {
6160 let workitem = wrap_workitem(workitem);
6161 PushWorkitemResponseWrapper {
6162 success: true,
6163 error: std::ptr::null(),
6164 workitem: Box::into_raw(Box::new(workitem)),
6165 request_id,
6166 }
6167 }
6168 None => {
6169 let error_msg = CString::new("Push workitem failed: workitem not found").unwrap().into_raw();
6170 PushWorkitemResponseWrapper {
6171 success: false,
6172 error: error_msg,
6173 workitem: std::ptr::null(),
6174 request_id,
6175 }
6176 }
6177 }
6178 }
6179 Err(e) => {
6180 let error_msg = CString::new(format!("Push workitem failed: {:?}", e))
6181 .unwrap()
6182 .into_raw();
6183 PushWorkitemResponseWrapper {
6184 success: false,
6185 error: error_msg,
6186 workitem: std::ptr::null(),
6187 request_id,
6188 }
6189 }
6190 };
6191 let response = Box::into_raw(Box::new(response));
6192 callback(response);
6193 });
6194
6195
6196}
6197
6198#[no_mangle]
6199#[tracing::instrument(skip_all)]
6200pub extern "C" fn free_push_workitem_response(response: *mut PushWorkitemResponseWrapper) {
6201 if response.is_null() {
6202 return;
6203 }
6204 unsafe {
6205 if !(*response).error.is_null() {
6206 let _ = CString::from_raw((*response).error as *mut c_char);
6207 }
6208 if !(*response).workitem.is_null() {
6209 free_workitem((*response).workitem as *mut WorkitemWrapper);
6210 }
6211 let _ = Box::from_raw(response);
6212 }
6213}
6214
6215#[repr(C)]
6216#[derive(Debug, Clone)]
6217pub struct PopWorkitemRequestWrapper {
6218 wiq: *const c_char,
6219 wiqid: *const c_char,
6220 request_id: i32
6221 }
6224#[repr(C)]
6225#[derive(Debug, Clone)]
6226pub struct PopWorkitemResponseWrapper {
6227 success: bool,
6228 error: *const c_char,
6229 workitem: *const WorkitemWrapper,
6230 request_id: i32
6231}
6232#[no_mangle]
6233#[tracing::instrument(skip_all)]
6234pub extern "C" fn pop_workitem (
6235 client: *mut ClientWrapper,
6236 options: *mut PopWorkitemRequestWrapper,
6237 downloadfolder: *const c_char,
6238) -> *mut PopWorkitemResponseWrapper {
6239 let options = match safe_wrapper(options) {
6240 Some(options) => options,
6241 None => {
6242 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6243 let response = PopWorkitemResponseWrapper {
6244 success: false,
6245 error: error_msg,
6246 workitem: std::ptr::null(),
6247 request_id: 0
6248 };
6249 return Box::into_raw(Box::new(response));
6250 }
6251 };
6252 let client_wrapper = match safe_wrapper(client) {
6253 Some(client) => client,
6254 None => {
6255 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6256 let response = PopWorkitemResponseWrapper {
6257 success: false,
6258 error: error_msg,
6259 workitem: std::ptr::null(),
6260 request_id: options.request_id
6261 };
6262 return Box::into_raw(Box::new(response));
6263 }
6264 };
6265 let client = client_wrapper.client.clone();
6266 let request = PopWorkitemRequest {
6267 wiq: c_char_to_str(options.wiq),
6268 wiqid: c_char_to_str(options.wiqid),
6269 ..Default::default()
6270 };
6271 if client.is_none() {
6272 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6273 let response = PopWorkitemResponseWrapper {
6274 success: false,
6275 error: error_msg,
6276 workitem: std::ptr::null(),
6277 request_id: options.request_id
6278 };
6279 return Box::into_raw(Box::new(response));
6280 }
6281 let downloadfolder = c_char_to_str(downloadfolder);
6282 let mut _downloadfolder = Some(downloadfolder.as_str());
6283 if downloadfolder.is_empty() {
6284 _downloadfolder = None;
6285 }
6286 let client = client.unwrap();
6287 let result = tokio::task::block_in_place(|| {
6288 let handle = client.get_runtime_handle();
6289 handle.block_on(client
6290 .pop_workitem(request, _downloadfolder)
6291 )
6292 });
6293 debug!("pop_workitem completed, parse result");
6294
6295 match result {
6296 Ok(data) => {
6297 let workitem = match data.workitem {
6298 Some(workitem) => {
6299 let workitem = wrap_workitem(workitem);
6300 trace!("wrap workitem");
6301 Box::into_raw(Box::new(workitem))
6302 },
6303 None => {
6304 std::ptr::null()
6305 }
6306 };
6307 Box::into_raw(Box::new(PopWorkitemResponseWrapper {
6308 success: true,
6309 error: std::ptr::null(),
6310 workitem,
6311 request_id: options.request_id
6312 }))
6313 }
6314 Err(e) => {
6315 let error_msg = CString::new(format!("Pop workitem failed: {:?}", e))
6316 .unwrap()
6317 .into_raw();
6318 Box::into_raw(Box::new(PopWorkitemResponseWrapper {
6319 success: false,
6320 error: error_msg,
6321 workitem: std::ptr::null(),
6322 request_id: options.request_id
6323 }))
6324 }
6325 }
6326}
6327#[no_mangle]
6328#[tracing::instrument(skip_all)]
6329pub extern "C" fn pop_workitem_async (
6330 client: *mut ClientWrapper,
6331 options: *mut PopWorkitemRequestWrapper,
6332 downloadfolder: *const c_char,
6333 callback: extern "C" fn(*mut PopWorkitemResponseWrapper),
6334) {
6335 let options = match safe_wrapper(options) {
6336 Some(options) => options,
6337 None => {
6338 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6339 let response = PopWorkitemResponseWrapper {
6340 success: false,
6341 error: error_msg,
6342 workitem: std::ptr::null(),
6343 request_id: 0
6344 };
6345 return callback(Box::into_raw(Box::new(response)));
6346 }
6347 };
6348 let client_wrapper = match safe_wrapper(client) {
6349 Some(client) => client,
6350 None => {
6351 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6352 let response = PopWorkitemResponseWrapper {
6353 success: false,
6354 error: error_msg,
6355 workitem: std::ptr::null(),
6356 request_id: options.request_id
6357 };
6358 return callback(Box::into_raw(Box::new(response)));
6359 }
6360 };
6361 let client = client_wrapper.client.clone();
6362 let request = PopWorkitemRequest {
6363 wiq: c_char_to_str(options.wiq),
6364 wiqid: c_char_to_str(options.wiqid),
6365 ..Default::default()
6366 };
6367 if client.is_none() {
6368 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6369 let response = PopWorkitemResponseWrapper {
6370 success: false,
6371 error: error_msg,
6372 workitem: std::ptr::null(),
6373 request_id: options.request_id
6374 };
6375 return callback(Box::into_raw(Box::new(response)));
6376 }
6377 let downloadfolder = c_char_to_str(downloadfolder);
6378 let client = client.unwrap();
6379 let handle = client.get_runtime_handle();
6380 let request_id = options.request_id;
6381 handle.spawn(async move {
6382 let mut _downloadfolder = Some(downloadfolder.as_str());
6383 if downloadfolder.is_empty() {
6384 _downloadfolder = None;
6385 }
6386
6387 let result = client
6388 .pop_workitem(request, _downloadfolder)
6389 .await;
6390 let response = match result {
6391 Ok(data) => {
6392 let workitem = match data.workitem {
6393 Some(workitem) => {
6394 let workitem = wrap_workitem(workitem);
6395 trace!("wrap workitem");
6396 Box::into_raw(Box::new(workitem))
6397 },
6398 None => {
6399 std::ptr::null()
6400 }
6401 };
6402 let response = PopWorkitemResponseWrapper {
6403 success: true,
6404 error: std::ptr::null(),
6405 workitem,
6406 request_id: request_id
6407 };
6408 Box::into_raw(Box::new(response))
6409 }
6410 Err(e) => {
6411 let error_msg = CString::new(format!("Pop workitem failed: {:?}", e))
6412 .unwrap()
6413 .into_raw();
6414 let response = PopWorkitemResponseWrapper {
6415 success: false,
6416 error: error_msg,
6417 workitem: std::ptr::null(),
6418 request_id: request_id
6419 };
6420 Box::into_raw(Box::new(response))
6421 }
6422 };
6423 trace!("callback with result");
6424 callback(response);
6425 });
6426}
6427#[no_mangle]
6428#[tracing::instrument(skip_all)]
6429pub extern "C" fn free_pop_workitem_response(response: *mut PopWorkitemResponseWrapper) {
6430 if response.is_null() {
6431 return;
6432 }
6433 unsafe {
6434 if !(*response).error.is_null() {
6435 let _ = CString::from_raw((*response).error as *mut c_char);
6436 }
6437 if !(*response).workitem.is_null() {
6438 free_workitem((*response).workitem as *mut WorkitemWrapper);
6439 }
6440 let _ = Box::from_raw(response);
6441 }
6442}
6443#[no_mangle]
6444#[tracing::instrument(skip_all)]
6445pub extern "C" fn free_workitem_file(file: *mut WorkitemFileWrapper) {
6446 if file.is_null() {
6447 return;
6448 }
6449 unsafe {
6450 if !(*file).filename.is_null() {
6451 let _ = CString::from_raw((*file).filename as *mut c_char);
6452 }
6453 if !(*file).id.is_null() {
6454 let _ = CString::from_raw((*file).id as *mut c_char);
6455 }
6456 let _ = Box::from_raw(file);
6457 }
6458}
6459#[no_mangle]
6460#[tracing::instrument(skip_all)]
6461pub extern "C" fn free_workitem(workitem: *mut WorkitemWrapper) {
6462 if workitem.is_null() {
6463 return;
6464 }
6465 unsafe {
6466 if !(*workitem).id.is_null() {
6467 let _ = CString::from_raw((*workitem).id as *mut c_char);
6468 }
6469 if !(*workitem).name.is_null() {
6470 let _ = CString::from_raw((*workitem).name as *mut c_char);
6471 }
6472 if !(*workitem).payload.is_null() {
6473 let _ = CString::from_raw((*workitem).payload as *mut c_char);
6474 }
6475 if !(*workitem).state.is_null() {
6476 let _ = CString::from_raw((*workitem).state as *mut c_char);
6477 }
6478 if !(*workitem).wiq.is_null() {
6479 let _ = CString::from_raw((*workitem).wiq as *mut c_char);
6480 }
6481 if !(*workitem).wiqid.is_null() {
6482 let _ = CString::from_raw((*workitem).wiqid as *mut c_char);
6483 }
6484 if !(*workitem).username.is_null() {
6485 let _ = CString::from_raw((*workitem).username as *mut c_char);
6486 }
6487 if !(*workitem).success_wiqid.is_null() {
6488 let _ = CString::from_raw((*workitem).success_wiqid as *mut c_char);
6489 }
6490 if !(*workitem).failed_wiqid.is_null() {
6491 let _ = CString::from_raw((*workitem).failed_wiqid as *mut c_char);
6492 }
6493 if !(*workitem).success_wiq.is_null() {
6494 let _ = CString::from_raw((*workitem).success_wiq as *mut c_char);
6495 }
6496 if !(*workitem).failed_wiq.is_null() {
6497 let _ = CString::from_raw((*workitem).failed_wiq as *mut c_char);
6498 }
6499 if !(*workitem).errormessage.is_null() {
6500 let _ = CString::from_raw((*workitem).errormessage as *mut c_char);
6501 }
6502 if !(*workitem).errorsource.is_null() {
6503 let _ = CString::from_raw((*workitem).errorsource as *mut c_char);
6504 }
6505 if !(*workitem).errortype.is_null() {
6506 let _ = CString::from_raw((*workitem).errortype as *mut c_char);
6507 }
6508
6509 if !(*workitem).files.is_null() && (*workitem).files_len > 0 {
6511 for i in 0..(*workitem).files_len as isize {
6512 let file_ptr = *(*workitem).files.offset(i);
6513 if !file_ptr.is_null() {
6514 free_workitem_file(file_ptr as *mut WorkitemFileWrapper);
6515 }
6516 }
6517 let _ = Box::from_raw((*workitem).files as *mut *const WorkitemFileWrapper);
6519 }
6520 let _ = Box::from_raw(workitem); }
6522}
6523
6524
6525#[no_mangle]
6526#[tracing::instrument(skip_all)]
6527pub extern "C" fn pop_workitem2_async (
6528 _client: *mut ClientWrapper,
6529 _options: *mut PopWorkitemRequestWrapper,
6530 _downloadfolder: *const c_char,
6531 request_id: i32,
6532 callback: extern "C" fn(*mut PopWorkitemResponseWrapper),
6533) {
6534 callback(Box::into_raw(Box::new(PopWorkitemResponseWrapper {
6535 success: true,
6536 error: std::ptr::null(),
6537 workitem: std::ptr::null(),
6538 request_id: request_id
6539 })));
6540}
6541
6542#[repr(C)]
6543#[derive(Debug, Clone)]
6544pub struct UpdateWorkitemRequestWrapper {
6545 workitem: *const WorkitemWrapper,
6546 ignoremaxretries: bool,
6547 files: *const *const WorkitemFileWrapper,
6548 files_len: i32,
6549 request_id: i32
6550}
6551#[repr(C)]
6552#[derive(Debug, Clone)]
6553pub struct UpdateWorkitemResponseWrapper {
6554 success: bool,
6555 error: *const c_char,
6556 workitem: *const WorkitemWrapper,
6557 request_id: i32
6558}
6559#[no_mangle]
6560#[tracing::instrument(skip_all)]
6561pub extern "C" fn update_workitem (
6562 client: *mut ClientWrapper,
6563 options: *mut UpdateWorkitemRequestWrapper,
6564) -> *mut UpdateWorkitemResponseWrapper {
6565 let options = match safe_wrapper(options) {
6566 Some(options) => options,
6567 None => {
6568 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6569 let response = UpdateWorkitemResponseWrapper {
6570 success: false,
6571 error: error_msg,
6572 workitem: std::ptr::null(),
6573 request_id: 0
6574 };
6575 return Box::into_raw(Box::new(response));
6576 }
6577 };
6578 let client_wrapper = match safe_wrapper(client) {
6579 Some(client) => client,
6580 None => {
6581 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6582 let response = UpdateWorkitemResponseWrapper {
6583 success: false,
6584 error: error_msg,
6585 workitem: std::ptr::null(),
6586 request_id: options.request_id
6587 };
6588 return Box::into_raw(Box::new(response));
6589 }
6590 };
6591 trace!("grab references");
6592 let client = client_wrapper.client.clone();
6593 let files_len = options.files_len;
6594 debug!("files_len: {:?}", files_len);
6595 let mut files: Vec<WorkitemFile> = vec![];
6596 if files_len > 0 {
6597 debug!("get files of options");
6598 let _files = unsafe { &*options.files };
6599 debug!("slice files");
6600 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
6601 debug!("loop files");
6602 files = _files.iter().map(|f| {
6603 debug!("process a file");
6604 let file = unsafe { &**f };
6605 debug!("create WorkitemFile instance 2");
6606 let filename = c_char_to_str(file.filename);
6607 debug!("filename: {:?}", filename);
6608 let id = c_char_to_str(file.id);
6609 debug!("id: {:?}", id);
6610 let compressed = file.compressed;
6611 debug!("compressed: {:?}", compressed);
6612 WorkitemFile {
6613 filename: c_char_to_str(file.filename),
6614 id: c_char_to_str(file.id),
6615 compressed: file.compressed,
6616 ..Default::default()
6617 }
6619 }).collect();
6620 }
6621 debug!("unwrap workitem");
6622 let workitem = unsafe { &*options.workitem };
6623 debug!("convert workitem wrapper to workitem");
6624 let workitem = workitem.as_workitem();
6625 let request = UpdateWorkitemRequest {
6626 workitem: Some(workitem),
6627 ignoremaxretries: options.ignoremaxretries,
6628 files,
6629 };
6630
6631 if client.is_none() {
6632 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6633 let response = UpdateWorkitemResponseWrapper {
6634 success: false,
6635 error: error_msg,
6636 workitem: std::ptr::null(),
6637 request_id: options.request_id
6638 };
6639 return Box::into_raw(Box::new(response));
6640 }
6641 let client = client.unwrap();
6642 let result = tokio::task::block_in_place(|| {
6643 let handle = client.get_runtime_handle();
6644 handle.block_on(client
6645 .update_workitem(request)
6646 )
6647 });
6648
6649 match result {
6650 Ok(resp) => {
6651 Box::into_raw(Box::new(match resp.workitem {
6652 Some(workitem) => {
6653 let workitem = wrap_workitem(workitem);
6654 UpdateWorkitemResponseWrapper {
6655 success: true,
6656 error: std::ptr::null(),
6657 workitem: Box::into_raw(Box::new(workitem)),
6658 request_id: options.request_id
6659 }
6660 }
6661 None => {
6662 let error_msg = CString::new("Update workitem failed: workitem not found").unwrap().into_raw();
6663 UpdateWorkitemResponseWrapper {
6664 success: false,
6665 error: error_msg,
6666 workitem: std::ptr::null(),
6667 request_id: options.request_id
6668 }
6669 }
6670 }))
6671 }
6672 Err(e) => {
6673 let error_msg = CString::new(format!("Update workitem failed: {:?}", e))
6674 .unwrap()
6675 .into_raw();
6676 Box::into_raw(Box::new(UpdateWorkitemResponseWrapper {
6677 success: false,
6678 error: error_msg,
6679 workitem: std::ptr::null(),
6680 request_id: options.request_id
6681 }))
6682 }
6683 }
6684}
6685#[no_mangle]
6686#[tracing::instrument(skip_all)]
6687pub extern "C" fn update_workitem_async (
6688 client: *mut ClientWrapper,
6689 options: *mut UpdateWorkitemRequestWrapper,
6690 callback: extern "C" fn(*mut UpdateWorkitemResponseWrapper),
6691) {
6692 let options = match safe_wrapper(options) {
6693 Some(options) => options,
6694 None => {
6695 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6696 let response = UpdateWorkitemResponseWrapper {
6697 success: false,
6698 error: error_msg,
6699 workitem: std::ptr::null(),
6700 request_id: 0
6701 };
6702 return callback(Box::into_raw(Box::new(response)));
6703 }
6704 };
6705 let client_wrapper = match safe_wrapper(client) {
6706 Some(client) => client,
6707 None => {
6708 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6709 let response = UpdateWorkitemResponseWrapper {
6710 success: false,
6711 error: error_msg,
6712 workitem: std::ptr::null(),
6713 request_id: options.request_id
6714 };
6715 return callback(Box::into_raw(Box::new(response)));
6716 }
6717 };
6718 trace!("grab references");
6719 let client = client_wrapper.client.clone();
6720 let files_len = options.files_len;
6721 debug!("files_len: {:?}", files_len);
6722 let mut files: Vec<WorkitemFile> = vec![];
6723 if files_len > 0 {
6724 debug!("get files of options");
6725 let _files = unsafe { &*options.files };
6726 debug!("slice files");
6727 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
6728 debug!("loop files");
6729 files = _files.iter().map(|f| {
6730 debug!("process a file");
6731 let file = unsafe { &**f };
6732 debug!("create WorkitemFile instance 2");
6733 let filename = c_char_to_str(file.filename);
6734 debug!("filename: {:?}", filename);
6735 let id = c_char_to_str(file.id);
6736 debug!("id: {:?}", id);
6737 let compressed = file.compressed;
6738 debug!("compressed: {:?}", compressed);
6739 WorkitemFile {
6740 filename: c_char_to_str(file.filename),
6741 id: c_char_to_str(file.id),
6742 compressed: file.compressed,
6743 ..Default::default()
6744 }
6746 }).collect();
6747 }
6748 debug!("unwrap workitem");
6749 let workitem = unsafe { &*options
6750 .workitem };
6751
6752 debug!("convert workitem wrapper to workitem");
6753 let workitem = workitem.as_workitem();
6754 let request = UpdateWorkitemRequest {
6755 workitem: Some(workitem),
6756 ignoremaxretries: options.ignoremaxretries,
6757 files,
6758 };
6759
6760 if client.is_none() {
6761 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6762 let response = UpdateWorkitemResponseWrapper {
6763 success: false,
6764 error: error_msg,
6765 workitem: std::ptr::null(),
6766 request_id: options.request_id
6767 };
6768 return callback(Box::into_raw(Box::new(response)));
6769 }
6770 let client = client.unwrap();
6771 let handle = client.get_runtime_handle();
6772 let request_id = options.request_id;
6773 handle.spawn(async move {
6774 let result = client
6775 .update_workitem(request)
6776 .await;
6777 let response = match result {
6778 Ok(resp) => {
6779 let response = match resp.workitem {
6780 Some(workitem) => {
6781 let workitem = wrap_workitem(workitem);
6782 UpdateWorkitemResponseWrapper {
6783 success: true,
6784 error: std::ptr::null(),
6785 workitem: Box::into_raw(Box::new(workitem)),
6786 request_id,
6787 }
6788 }
6789 None => {
6790 let error_msg = CString::new("Update workitem failed: workitem not found").unwrap().into_raw();
6791 UpdateWorkitemResponseWrapper {
6792 success: false,
6793 error: error_msg,
6794 workitem: std::ptr::null(),
6795 request_id,
6796 }
6797 }
6798 };
6799 Box::into_raw(Box::new(response))
6800 }
6801 Err(e) => {
6802 let error_msg = CString::new(format!("Update workitem failed: {:?}", e))
6803 .unwrap()
6804 .into_raw();
6805 Box::into_raw(Box::new(UpdateWorkitemResponseWrapper {
6806 success: false,
6807 error: error_msg,
6808 workitem: std::ptr::null(),
6809 request_id,
6810 }))
6811 }
6812 };
6813 callback(response);
6814 });
6815}
6816#[no_mangle]
6817#[tracing::instrument(skip_all)]
6818pub extern "C" fn free_update_workitem_response(response: *mut UpdateWorkitemResponseWrapper) {
6819 if response.is_null() {
6820 return;
6821 }
6822 unsafe {
6823 if !(*response).error.is_null() {
6824 let _ = CString::from_raw((*response).error as *mut c_char);
6825 }
6826 if !(*response).workitem.is_null() {
6827 free_workitem((*response).workitem as *mut WorkitemWrapper);
6828 }
6829 let _ = Box::from_raw(response);
6830 }
6831}
6832
6833#[repr(C)]
6834#[derive(Debug, Clone)]
6835pub struct DeleteWorkitemRequestWrapper {
6836 id: *const c_char,
6837 request_id: i32
6838}
6839#[repr(C)]
6840#[derive(Debug, Clone)]
6841pub struct DeleteWorkitemResponseWrapper {
6842 success: bool,
6843 error: *const c_char,
6844 request_id: i32
6845}
6846#[no_mangle]
6847#[tracing::instrument(skip_all)]
6848pub extern "C" fn delete_workitem(
6849 client: *mut ClientWrapper,
6850 options: *mut DeleteWorkitemRequestWrapper,
6851) -> *mut DeleteWorkitemResponseWrapper {
6852 let options = match safe_wrapper(options) {
6853 Some(options) => options,
6854 None => {
6855 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6856 let response = DeleteWorkitemResponseWrapper {
6857 success: false,
6858 error: error_msg,
6859 request_id: 0
6860 };
6861 return Box::into_raw(Box::new(response));
6862 }
6863 };
6864 let client_wrapper = match safe_wrapper(client) {
6865 Some(client) => client,
6866 None => {
6867 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6868 let response = DeleteWorkitemResponseWrapper {
6869 success: false,
6870 error: error_msg,
6871 request_id: options.request_id
6872 };
6873 return Box::into_raw(Box::new(response));
6874 }
6875 };
6876 let client = client_wrapper.client.clone();
6877 let request = DeleteWorkitemRequest {
6878 id: c_char_to_str(options.id),
6879 };
6880 if client.is_none() {
6881 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6882 let response = DeleteWorkitemResponseWrapper {
6883 success: false,
6884 error: error_msg,
6885 request_id: options.request_id
6886 };
6887 return Box::into_raw(Box::new(response));
6888 }
6889 let client = client.unwrap();
6890 let result = tokio::task::block_in_place(|| {
6891 let handle = client.get_runtime_handle();
6892 handle.block_on(client
6893 .delete_workitem(request)
6894 )
6895 });
6896
6897 let response = match result {
6898 Ok(_) => {
6899 let response = DeleteWorkitemResponseWrapper {
6900 success: true,
6901 error: std::ptr::null(),
6902 request_id: options.request_id
6903 };
6904 Box::into_raw(Box::new(response))
6905 }
6906 Err(e) => {
6907 let error_msg = CString::new(format!("Delete workitem failed: {:?}", e))
6908 .unwrap()
6909 .into_raw();
6910 let response = DeleteWorkitemResponseWrapper {
6911 success: false,
6912 error: error_msg,
6913 request_id: options.request_id
6914 };
6915 Box::into_raw(Box::new(response))
6916 }
6917 };
6918 debug!("return response {:?}", response);
6919 response
6920}
6921#[no_mangle]
6922#[tracing::instrument(skip_all)]
6923pub extern "C" fn delete_workitem_async(
6924 client: *mut ClientWrapper,
6925 options: *mut DeleteWorkitemRequestWrapper,
6926 callback: extern "C" fn(*mut DeleteWorkitemResponseWrapper),
6927) {
6928 let options = match safe_wrapper(options) {
6929 Some(options) => options,
6930 None => {
6931 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6932 let response = DeleteWorkitemResponseWrapper {
6933 success: false,
6934 error: error_msg,
6935 request_id: 0
6936 };
6937 return callback(Box::into_raw(Box::new(response)));
6938 }
6939 };
6940 let client_wrapper = match safe_wrapper(client) {
6941 Some(client) => client,
6942 None => {
6943 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6944 let response = DeleteWorkitemResponseWrapper {
6945 success: false,
6946 error: error_msg,
6947 request_id: options.request_id
6948 };
6949 return callback(Box::into_raw(Box::new(response)));
6950 }
6951 };
6952 let client = client_wrapper.client.clone();
6953 let request = DeleteWorkitemRequest {
6954 id: c_char_to_str(options.id),
6955 };
6956 if client.is_none() {
6957 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6958 let response = DeleteWorkitemResponseWrapper {
6959 success: false,
6960 error: error_msg,
6961 request_id: options.request_id
6962 };
6963 return callback(Box::into_raw(Box::new(response)));
6964 }
6965 let client = client.unwrap();
6966 let handle = client.get_runtime_handle();
6967 let request_id = options.request_id;
6968 handle.spawn(async move {
6969 let result = client
6970 .delete_workitem(request)
6971 .await;
6972 let response = match result {
6973 Ok(_) => {
6974 debug!("success");
6975 let response = DeleteWorkitemResponseWrapper {
6976 success: true,
6977 error: std::ptr::null(),
6978 request_id,
6979 };
6980 Box::into_raw(Box::new(response))
6981 }
6982 Err(e) => {
6983 let error_msg = CString::new(format!("Delete workitem failed: {:?}", e))
6984 .unwrap()
6985 .into_raw();
6986 debug!("failed: {:?}", error_msg);
6987 let response = DeleteWorkitemResponseWrapper {
6988 success: false,
6989 error: error_msg,
6990 request_id,
6991 };
6992 Box::into_raw(Box::new(response))
6993 }
6994 };
6995 debug!("callback {:?}", response);
6996 callback(response);
6997 });
6998}
6999#[no_mangle]
7000#[tracing::instrument(skip_all)]
7001pub extern "C" fn free_delete_workitem_response(response: *mut DeleteWorkitemResponseWrapper) {
7002 if response.is_null() {
7003 return;
7004 }
7005 unsafe {
7006 if !(*response).error.is_null() {
7007 let _ = CString::from_raw((*response).error as *mut c_char);
7008 }
7009 let _ = Box::from_raw(response);
7010 }
7011}
7012
7013
7014
7015
7016
7017#[repr(C)]
7018#[derive(Debug, Clone)]
7019pub struct ClientEventWrapper {
7020 event: *const c_char,
7021 reason: *const c_char,
7022}
7023impl Default for ClientEventWrapper {
7024 fn default() -> Self {
7025 ClientEventWrapper {
7026 event: std::ptr::null(),
7027 reason: std::ptr::null(),
7028 }
7029 }
7030}
7031#[repr(C)]
7032pub struct ClientEventResponseWrapper {
7033 success: bool,
7034 eventid: *const c_char,
7035 error: *const c_char,
7036}
7037
7038#[no_mangle]
7039#[tracing::instrument(skip_all)]
7040pub extern "C" fn on_client_event(
7041 client: *mut ClientWrapper
7042) -> *mut ClientEventResponseWrapper {
7043 let client_wrapper = match safe_wrapper(client) {
7044 Some(client) => client,
7045 None => {
7046 let error_msg = CString::new("Invalid options, client is None").unwrap().into_raw();
7047 let response = ClientEventResponseWrapper {
7048 success: false,
7049 eventid: std::ptr::null(),
7050 error: error_msg,
7051 };
7052 return Box::into_raw(Box::new(response));
7053 }
7054 };
7055 let mut client = client_wrapper.client.clone();
7056 if client.is_none() {
7057 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7058 let response = ClientEventResponseWrapper {
7059 success: false,
7060 eventid: std::ptr::null(),
7061 error: error_msg,
7062 };
7063 return Box::into_raw(Box::new(response));
7064 }
7065 let client = client.as_mut().unwrap();
7066 let eventid = Client::get_uniqueid();
7067 let _eventid = eventid.clone();
7068 tokio::task::block_in_place(|| {
7069 let handle = client.get_runtime_handle();
7070 handle.block_on(client.on_event(Box::new({
7071 move |event: ClientEvent| {
7072 let clientid = _eventid.clone();
7073 debug!("client event: {:?}", event);
7074
7075 let mut e = CLIENT_EVENTS.lock().unwrap();
7076 let queue = e.get_mut(&clientid);
7077 match queue {
7078 Some(q) => {
7079 q.push_back(event);
7080 }
7081 None => {
7082 let mut q = std::collections::VecDeque::new();
7083 q.push_back(event);
7084 e.insert(clientid, q);
7085 }
7086 }
7087 }
7088 })));
7089 });
7090
7091 let mut events = CLIENT_EVENTS.lock().unwrap();
7092 let _eventid = eventid.clone();
7093 let queue = events.get_mut(&_eventid);
7094 if queue.is_none() {
7095 let q = std::collections::VecDeque::new();
7096 let k = String::from(&eventid);
7097 events.insert(k, q);
7098 };
7099 let response = ClientEventResponseWrapper {
7100 success: true,
7101 eventid: CString::new(eventid).unwrap().into_raw(),
7102 error: std::ptr::null(),
7103 };
7104 return Box::into_raw(Box::new(response));
7105}
7106type ClientEventCallback = extern "C" fn(*mut ClientEventWrapper);
7107#[no_mangle]
7108#[tracing::instrument(skip_all)]
7109pub extern "C" fn on_client_event_async(
7110 client: *mut ClientWrapper,
7111 event_callback: ClientEventCallback,
7112) -> *mut ClientEventResponseWrapper {
7113 debug!("on_client_event_async::begin");
7114 let client_wrapper = match safe_wrapper(client) {
7115 Some(client) => client,
7116 None => {
7117 let error_msg = CString::new("Invalid options, client is None").unwrap().into_raw();
7118 let response = ClientEventResponseWrapper {
7119 success: false,
7120 eventid: std::ptr::null(),
7121 error: error_msg,
7122 };
7123 return Box::into_raw(Box::new(response));
7124 }
7125 };
7126 let mut client = client_wrapper.client.clone();
7127 if client.is_none() {
7128 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7129 let response = ClientEventResponseWrapper {
7130 success: false,
7131 eventid: std::ptr::null(),
7132 error: error_msg,
7133 };
7134 return Box::into_raw(Box::new(response));
7135 }
7136 let client = client.as_mut().unwrap();
7137 let eventid = Client::get_uniqueid();
7138 debug!("on_client_event_async::eventid: {:?}", eventid);
7139 let _eventid = eventid.clone();
7140 tokio::task::block_in_place(|| {
7141 let handle = client.get_runtime_handle();
7142 handle.block_on(client
7143 .on_event(
7144 Box::new(move |event: ClientEvent| {
7145 let clientid = _eventid.clone();
7146 debug!("client event: {:?}", event);
7147 let mut e = CLIENT_EVENTS.lock().unwrap();
7148 let queue = e.get_mut(&clientid);
7149 match queue {
7150 Some(_q) => {
7151 }
7152 None => {
7153 return;
7155 }
7156 };
7157 let event = match event {
7158 ClientEvent::Connecting => ClientEventWrapper { event: CString::new("Connecting").unwrap().into_raw(),reason: std::ptr::null() },
7159 ClientEvent::Connected => ClientEventWrapper { event: CString::new("Connected").unwrap().into_raw(),reason: std::ptr::null() },
7160 ClientEvent::Disconnected(reason) => ClientEventWrapper { event: CString::new("Disconnected").unwrap().into_raw(),reason: CString::new(reason).unwrap().into_raw() },
7161 ClientEvent::SignedIn => ClientEventWrapper { event: CString::new("SignedIn").unwrap().into_raw(),reason: std::ptr::null() },
7162 };
7164 let event = Box::into_raw(Box::new(event));
7165
7166 event_callback(event);
7167 debug!("client event: {:?}", event);
7168 }),
7169 )
7170 )
7171 });
7172
7173 let mut events = CLIENT_EVENTS.lock().unwrap();
7174 let _eventid = eventid.clone();
7175 let queue = events.get_mut(&_eventid);
7176 if queue.is_none() {
7177 debug!("create event queue, for eventid: {:?}", eventid);
7178 let q = std::collections::VecDeque::new();
7179 let k = String::from(&eventid);
7180 events.insert(k, q);
7181 };
7182 debug!("on_client_event_async::end");
7183 let response = ClientEventResponseWrapper {
7184 success: true,
7185 eventid: CString::new(eventid).unwrap().into_raw(),
7186 error: std::ptr::null(),
7187 };
7188 return Box::into_raw(Box::new(response));
7189
7190}
7191
7192#[no_mangle]
7193#[tracing::instrument(skip_all)]
7194pub extern "C" fn next_client_event (
7195 clientid: *const c_char,
7196) -> *mut ClientEventWrapper {
7197 trace!("unwrap clientid");
7198 let clientid = c_char_to_str(clientid);
7199 trace!("clientid {:}", clientid);
7200 let clientid = clientid.to_string();
7201 trace!("unwrap events");
7202 let mut e = CLIENT_EVENTS.lock().unwrap();
7203 trace!("get queue");
7204 let queue = e.get_mut(&clientid);
7205 match queue {
7206 Some(q) => {
7207 match q.pop_front() {
7208 Some(event) => {
7209 debug!("got client event");
7210 let event = match event {
7211 ClientEvent::Connecting => ClientEventWrapper { event: CString::new("Connecting").unwrap().into_raw(),reason: std::ptr::null() },
7212 ClientEvent::Connected => ClientEventWrapper { event: CString::new("Connected").unwrap().into_raw(),reason: std::ptr::null() },
7213 ClientEvent::Disconnected(reason) => ClientEventWrapper { event: CString::new("Disconnected").unwrap().into_raw(),reason: CString::new(reason).unwrap().into_raw() },
7214 ClientEvent::SignedIn => ClientEventWrapper { event: CString::new("SignedIn").unwrap().into_raw(),reason: std::ptr::null() },
7215 };
7217 Box::into_raw(Box::new(event))
7218 }
7219 None => {
7220 trace!("No event");
7221 Box::into_raw(Box::new(ClientEventWrapper::default()))
7222 },
7223 }
7224 },
7225 None => {
7226 debug!("Queue for {:} not found", clientid);
7227 Box::into_raw(Box::new(ClientEventWrapper::default()))
7228 },
7229 }
7230}
7231
7232#[repr(C)]
7233pub struct OffClientEventResponseWrapper {
7234 success: bool,
7235 error: *const c_char,
7236}
7237#[no_mangle]
7238#[tracing::instrument(skip_all)]
7239pub extern "C" fn off_client_event(
7240 eventid: *const c_char,
7241) -> *mut OffClientEventResponseWrapper {
7242 let eventid = c_char_to_str(eventid);
7243 if eventid.is_empty() {
7244 let error_msg = CString::new("eventid is required").unwrap().into_raw();
7245 let response = OffClientEventResponseWrapper {
7246 success: false,
7247 error: error_msg,
7248 };
7249 return Box::into_raw(Box::new(response));
7250 }
7251 trace!("eventid: {:?}", eventid);
7252
7253 let mut e = CLIENT_EVENTS.lock().unwrap();
7254 let queue = e.get_mut(&eventid);
7255 if let Some(q) = queue {
7256 q.clear();
7257 e.remove(&eventid);
7258 };
7259 Box::into_raw(Box::new(OffClientEventResponseWrapper {
7260 success: true,
7261 error: std::ptr::null(),
7262 }))
7263}
7264
7265#[no_mangle]
7266#[tracing::instrument(skip_all)]
7267pub extern "C" fn free_off_event_response(response: *mut OffClientEventResponseWrapper) {
7268 if response.is_null() {
7269 return;
7270 }
7271 unsafe {
7272 if !(*response).error.is_null() {
7273 let _ = CString::from_raw((*response).error as *mut c_char);
7274 }
7275 let _ = Box::from_raw(response);
7276 }
7277}
7278#[no_mangle]
7279#[tracing::instrument(skip_all)]
7280pub extern "C" fn free_event_response(response: *mut ClientEventResponseWrapper) {
7281 if response.is_null() {
7282 return;
7283 }
7284 unsafe {
7285 if !(*response).error.is_null() {
7286 let _ = CString::from_raw((*response).error as *mut c_char);
7287 }
7288 if !(*response).eventid.is_null() {
7289 let _ = CString::from_raw((*response).eventid as *mut c_char);
7290 }
7291 let _ = Box::from_raw(response);
7292 }
7293}
7294#[no_mangle]
7295#[tracing::instrument(skip_all)]
7296pub extern "C" fn free_client_event(response: *mut ClientEventWrapper) {
7297 if response.is_null() {
7298 return;
7299 }
7300 unsafe {
7301 if !(*response).event.is_null() {
7302 let _ = CString::from_raw((*response).event as *mut c_char);
7303 }
7304 if !(*response).reason.is_null() {
7305 let _ = CString::from_raw((*response).reason as *mut c_char);
7306 }
7307 let _ = Box::from_raw(response);
7308 }
7309}
7310#[repr(C)]
7311pub struct RpcResponseWrapper {
7312 success: bool,
7313 result: *const c_char,
7314 error: *const c_char,
7315 request_id: i32
7316}
7317#[no_mangle]
7318#[tracing::instrument(skip_all)]
7319pub extern "C" fn rpc(
7320 client: *mut ClientWrapper,
7321 options: *mut QueueMessageRequestWrapper,
7322 timeout: i32
7323) -> *mut RpcResponseWrapper {
7324 let options = match safe_wrapper(options) {
7325 Some(options) => options,
7326 None => {
7327 let error_msg = CString::new("Invalid options").unwrap().into_raw();
7328 let response = RpcResponseWrapper {
7329 success: false,
7330 result: std::ptr::null(),
7331 error: error_msg,
7332 request_id: 0
7333 };
7334 return Box::into_raw(Box::new(response));
7335 }
7336 };
7337 let client_wrapper = match safe_wrapper(client) {
7338 Some(client) => client,
7339 None => {
7340 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7341 let response = RpcResponseWrapper {
7342 success: false,
7343 result: std::ptr::null(),
7344 error: error_msg,
7345 request_id: options.request_id
7346 };
7347 return Box::into_raw(Box::new(response));
7348 }
7349 };
7350 let client = client_wrapper.client.clone();
7351
7352 if client.is_none() {
7353 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7354 let response = RpcResponseWrapper {
7355 success: false,
7356 result: std::ptr::null(),
7357 error: error_msg,
7358 request_id: options.request_id
7359 };
7360 return Box::into_raw(Box::new(response));
7361 }
7362 let client = client.unwrap();
7363
7364 let mut _timeout = client.get_default_timeout();
7365 if timeout >= 0 {
7366 _timeout = tokio::time::Duration::from_secs(timeout as u64);
7367 }
7368
7369 let result = tokio::task::block_in_place(|| {
7370 let handle = client.get_runtime_handle();
7371 let request = QueueMessageRequest {
7372 queuename: c_char_to_str(options.queuename),
7373 correlation_id: c_char_to_str(options.correlation_id),
7374 replyto: c_char_to_str(options.replyto),
7375 routingkey: c_char_to_str(options.routingkey),
7376 exchangename: c_char_to_str(options.exchangename),
7377 data: c_char_to_str(options.data),
7378 striptoken: options.striptoken,
7379 expiration: options.expiration,
7380 };
7381 handle.block_on(client.rpc(request, _timeout))
7382 });
7383
7384 match result {
7385 Ok(data) => {
7386 let result = CString::new(data).unwrap().into_raw();
7387 let response = RpcResponseWrapper {
7388 success: true,
7389 result,
7390 error: std::ptr::null(),
7391 request_id: options.request_id
7392 };
7393 Box::into_raw(Box::new(response))
7394 }
7395 Err(e) => {
7396 let error_msg = CString::new(format!("RPC failed: {:?}", e))
7397 .unwrap()
7398 .into_raw();
7399 let response = RpcResponseWrapper {
7402 success: false,
7403 result: std::ptr::null(),
7404 error: error_msg,
7405 request_id: options.request_id
7406 };
7407 Box::into_raw(Box::new(response))
7408 }
7409 }
7410}
7411pub type RpcResponseCallback = extern "C" fn(*mut RpcResponseWrapper);
7412#[no_mangle]
7413#[tracing::instrument(skip_all)]
7414pub extern "C" fn rpc_async(
7415 client: *mut ClientWrapper,
7416 options: *mut QueueMessageRequestWrapper,
7417 response_callback: RpcResponseCallback,
7418 timeout: i32,
7419) {
7420 let options = match safe_wrapper(options) {
7422 Some(o) => o,
7423 None => {
7424 let error_msg = CString::new("Invalid options").unwrap().into_raw();
7425 let response = RpcResponseWrapper {
7426 success: false,
7427 result: std::ptr::null(),
7428 error: error_msg,
7429 request_id: 0
7430 };
7431 response_callback(Box::into_raw(Box::new(response)));
7432 return;
7433 }
7434 };
7435
7436 let client_wrapper = match safe_wrapper(client) {
7438 Some(c) => c,
7439 None => {
7440 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7441 let response = RpcResponseWrapper {
7442 success: false,
7443 result: std::ptr::null(),
7444 error: error_msg,
7445 request_id: options.request_id
7446 };
7447 response_callback(Box::into_raw(Box::new(response)));
7448 return;
7449 }
7450 };
7451
7452 let client = match client_wrapper.client.clone() {
7454 Some(c) => c,
7455 None => {
7456 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7457 let response = RpcResponseWrapper {
7458 success: false,
7459 result: std::ptr::null(),
7460 error: error_msg,
7461 request_id: options.request_id
7462 };
7463 response_callback(Box::into_raw(Box::new(response)));
7464 return;
7465 }
7466 };
7467
7468 let request = QueueMessageRequest {
7470 queuename: c_char_to_str(options.queuename),
7471 correlation_id: c_char_to_str(options.correlation_id),
7472 replyto: c_char_to_str(options.replyto),
7473 routingkey: c_char_to_str(options.routingkey),
7474 exchangename: c_char_to_str(options.exchangename),
7475 data: c_char_to_str(options.data),
7476 striptoken: options.striptoken,
7477 expiration: options.expiration
7478 };
7479
7480 let runtime_handle = client.get_runtime_handle();
7482
7483 let request_id = options.request_id;
7484
7485 let mut _timeout = client.get_default_timeout();
7486 if timeout >= 0 {
7487 _timeout = tokio::time::Duration::from_secs(timeout as u64);
7488 }
7489
7490 runtime_handle.spawn(async move {
7492 let result = client.rpc(request, _timeout).await;
7494
7495 let response = match result {
7497 Ok(data) => {
7498 let result_c = CString::new(data).unwrap().into_raw();
7499 RpcResponseWrapper {
7500 success: true,
7501 result: result_c,
7502 error: std::ptr::null(),
7503 request_id: request_id
7504 }
7505 }
7506 Err(e) => {
7507 let error_msg = CString::new(format!("RPC failed: {:?}", e))
7508 .unwrap()
7509 .into_raw();
7510 RpcResponseWrapper {
7511 success: false,
7512 result: std::ptr::null(),
7513 error: error_msg,
7514 request_id: request_id
7515 }
7516 }
7517 };
7518
7519 response_callback(Box::into_raw(Box::new(response)));
7521 });
7522}
7523
7524#[no_mangle]
7628#[tracing::instrument(skip_all)]
7629pub extern "C" fn free_rpc_response(response: *mut RpcResponseWrapper) {
7630 if response.is_null() {
7631 return;
7632 }
7633 unsafe {
7634 if !(*response).error.is_null() {
7635 let _ = CString::from_raw((*response).error as *mut c_char);
7636 }
7637 if !(*response).result.is_null() {
7638 let _ = CString::from_raw((*response).result as *mut c_char);
7639 }
7640 let _ = Box::from_raw(response);
7641 }
7642}