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