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, openiap_client::EnvConfig::new()))
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, openiap_client::EnvConfig::new()).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, openiap_client::EnvConfig::new(), 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, openiap_client::EnvConfig::new(), 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, openiap_client::EnvConfig::new()))
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, openiap_client::EnvConfig::new()).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, openiap_client::EnvConfig::new()))
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, openiap_client::EnvConfig::new()).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, openiap_client::EnvConfig::new()))
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, openiap_client::EnvConfig::new()).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, openiap_client::EnvConfig::new()))
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, openiap_client::EnvConfig::new()).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, openiap_client::EnvConfig::new()))
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, openiap_client::EnvConfig::new()).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, openiap_client::EnvConfig::new()))
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, openiap_client::EnvConfig::new()).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, openiap_client::EnvConfig::new()))
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, openiap_client::EnvConfig::new()).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, openiap_client::EnvConfig::new()))
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,
2526 openiap_client::EnvConfig::new()).await;
2527 let response = match result {
2528 Ok(data) => {
2529 let result = data.result;
2530 CountResponseWrapper {
2531 success: true,
2532 result,
2533 error: std::ptr::null(),
2534 request_id,
2535 }
2536 }
2537 Err(e) => {
2538 let error_msg = CString::new(format!("Count failed: {:?}", e))
2539 .unwrap()
2540 .into_raw();
2541 CountResponseWrapper {
2542 success: false,
2543 result: 0,
2544 error: error_msg,
2545 request_id,
2546 }
2547 }
2548 };
2549
2550 callback(Box::into_raw(Box::new(response)));
2551 });
2552}
2553#[no_mangle]
2554#[tracing::instrument(skip_all)]
2555pub extern "C" fn free_count_response(response: *mut CountResponseWrapper) {
2556 if response.is_null() {
2557 return;
2558 }
2559 unsafe {
2560 if !(*response).error.is_null() {
2561 let _ = CString::from_raw((*response).error as *mut c_char);
2562 }
2563 let _ = Box::from_raw(response);
2564 }
2565}
2566
2567#[repr(C)]
2568pub struct DistinctRequestWrapper {
2569 collectionname: *const c_char,
2570 field: *const c_char,
2571 query: *const c_char,
2572 queryas: *const c_char,
2573 explain: bool,
2574 request_id: i32
2575}
2576#[repr(C)]
2577pub struct DistinctResponseWrapper {
2578 success: bool,
2579 results: *mut *const c_char,
2581 error: *const c_char,
2582 results_len: i32,
2583 request_id: i32
2584}
2585#[no_mangle]
2586#[tracing::instrument(skip_all)]
2587pub extern "C" fn distinct(
2588 client: *mut ClientWrapper,
2589 options: *mut DistinctRequestWrapper,
2590) -> *mut DistinctResponseWrapper {
2591 let options = match safe_wrapper(options) {
2592 Some(options) => options,
2593 None => {
2594 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2595 let response = DistinctResponseWrapper {
2596 success: false,
2597 results: std::ptr::null_mut(),
2598 error: error_msg,
2599 results_len: 0,
2600 request_id: 0,
2601 };
2602 return Box::into_raw(Box::new(response));
2603 }
2604 };
2605 let client_wrapper = match safe_wrapper(client) {
2606 Some(client) => client,
2607 None => {
2608 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2609 let response = DistinctResponseWrapper {
2610 success: false,
2611 results: std::ptr::null_mut(),
2612 error: error_msg,
2613 results_len: 0,
2614 request_id: options.request_id,
2615 };
2616 return Box::into_raw(Box::new(response));
2617 }
2618 };
2619 let client = client_wrapper.client.clone();
2620 let request = DistinctRequest {
2621 collectionname: c_char_to_str(options.collectionname),
2622 field: c_char_to_str(options.field),
2623 query: c_char_to_str(options.query),
2624 queryas: c_char_to_str(options.queryas),
2625 explain: options.explain,
2626 ..Default::default()
2627 };
2628 if client.is_none() {
2629 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2630 let response = DistinctResponseWrapper {
2631 success: false,
2632 results: std::ptr::null_mut(),
2633 error: error_msg,
2634 results_len: 0,
2635 request_id: options.request_id,
2636 };
2637 return Box::into_raw(Box::new(response));
2638 }
2639 let client = client.unwrap();
2640 let result = tokio::task::block_in_place(|| {
2641 let handle = client.get_runtime_handle();
2642 handle.block_on( client.distinct(request, openiap_client::EnvConfig::new()) )
2643 });
2644
2645 let response = match result {
2646 Ok(data) => {
2647 let results_cstrings: Vec<CString> = data
2648 .results
2649 .iter()
2650 .map(|s| CString::new(s.as_str()).unwrap())
2651 .collect();
2652 let results_ptrs: Vec<*const c_char> =
2653 results_cstrings.iter().map(|s| s.as_ptr()).collect();
2654 let results_array =
2655 Box::into_raw(results_ptrs.clone().into_boxed_slice()) as *mut *const c_char;
2656
2657 std::mem::forget(results_cstrings);
2658
2659 DistinctResponseWrapper {
2660 success: true,
2661 results: results_array,
2662 error: std::ptr::null(),
2663 results_len: data.results.len().try_into().unwrap(),
2664 request_id: options.request_id,
2665 }
2666 }
2667 Err(e) => {
2668 let error_msg = CString::new(format!("Distinct failed: {:?}", e))
2669 .unwrap()
2670 .into_raw();
2671 DistinctResponseWrapper {
2672 success: false,
2673 results: std::ptr::null_mut(),
2674 error: error_msg,
2675 results_len: 0,
2676 request_id: options.request_id,
2677 }
2678 }
2679 };
2680
2681 Box::into_raw(Box::new(response))
2682}
2683
2684type DistinctCallback = extern "C" fn(wrapper: *mut DistinctResponseWrapper);
2685#[no_mangle]
2686#[tracing::instrument(skip_all)]
2687pub extern "C" fn distinct_async(
2688 client: *mut ClientWrapper,
2689 options: *mut DistinctRequestWrapper,
2690 callback: DistinctCallback,
2691) {
2692 let options = match safe_wrapper(options) {
2693 Some(options) => options,
2694 None => {
2695 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2696 let response = DistinctResponseWrapper {
2697 success: false,
2698 results: std::ptr::null_mut(),
2699 error: error_msg,
2700 results_len: 0,
2701 request_id: 0,
2702 };
2703 return callback(Box::into_raw(Box::new(response)));
2704 }
2705 };
2706 let client_wrapper = match safe_wrapper(client) {
2707 Some(client) => client,
2708 None => {
2709 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2710 let response = DistinctResponseWrapper {
2711 success: false,
2712 results: std::ptr::null_mut(),
2713 error: error_msg,
2714 results_len: 0,
2715 request_id: options.request_id,
2716 };
2717 return callback(Box::into_raw(Box::new(response)));
2718 }
2719 };
2720 let client = client_wrapper.client.clone();
2721 let request = DistinctRequest {
2722 collectionname: c_char_to_str(options.collectionname),
2723 field: c_char_to_str(options.field),
2724 query: c_char_to_str(options.query),
2725 queryas: c_char_to_str(options.queryas),
2726 explain: options.explain,
2727 ..Default::default()
2728 };
2729 if client.is_none() {
2730 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2731 let response = DistinctResponseWrapper {
2732 success: false,
2733 results: std::ptr::null_mut(),
2734 error: error_msg,
2735 results_len: 0,
2736 request_id: options.request_id,
2737 };
2738 return callback(Box::into_raw(Box::new(response)));
2739 }
2740 let client = client.unwrap();
2741 let handle = client.get_runtime_handle();
2742 let request_id = options.request_id;
2743 handle.spawn(async move {
2744 let result = client.distinct(request, openiap_client::EnvConfig::new()).await;
2745 let response = match result {
2746 Ok(data) => {
2747 let results_cstrings: Vec<CString> = data
2748 .results
2749 .iter()
2750 .map(|s| CString::new(s.as_str()).unwrap())
2751 .collect();
2752 let results_ptrs: Vec<*const c_char> =
2753 results_cstrings.iter().map(|s| s.as_ptr()).collect();
2754 let results_array =
2755 Box::into_raw(results_ptrs.clone().into_boxed_slice()) as *mut *const c_char;
2756
2757 std::mem::forget(results_cstrings);
2758
2759 debug!("Rust: results_array: {:?}", results_array);
2760 for (i, ptr) in results_ptrs.iter().enumerate() {
2761 debug!("Rust: results_ptrs[{}]: {:?}: {:?}", i, ptr, unsafe {
2762 CStr::from_ptr(*ptr).to_str().unwrap()
2763 });
2764 }
2765
2766 DistinctResponseWrapper {
2767 success: true,
2768 results: results_array,
2769 error: std::ptr::null(),
2770 results_len: data.results.len().try_into().unwrap(),
2771 request_id,
2772 }
2773 }
2774 Err(e) => {
2775 let error_msg = CString::new(format!("Distinct failed: {:?}", e))
2776 .unwrap()
2777 .into_raw();
2778 DistinctResponseWrapper {
2779 success: false,
2780 results: std::ptr::null_mut(),
2781 error: error_msg,
2782 results_len: 0,
2783 request_id,
2784 }
2785 }
2786 };
2787
2788 callback(Box::into_raw(Box::new(response)));
2789 });
2790}
2791#[no_mangle]
2792#[tracing::instrument(skip_all)]
2793pub extern "C" fn free_distinct_response(response: *mut DistinctResponseWrapper) {
2794 if response.is_null() {
2795 return;
2796 }
2797 unsafe {
2798 if !(*response).results.is_null() {
2799 for i in 0..(*response).results_len {
2800 let c_str_ptr = *(*response).results.add(i as usize);
2801 if !c_str_ptr.is_null() {
2802 let _ = CString::from_raw(c_str_ptr as *mut c_char); }
2804 }
2805 let _ = Box::from_raw((*response).results);
2806 }
2807
2808 if !(*response).error.is_null() {
2809 let _ = CString::from_raw((*response).error as *mut c_char);
2810 }
2811 let _ = Box::from_raw(response);
2812 }
2813}
2814#[repr(C)]
2815pub struct InsertOneRequestWrapper {
2816 collectionname: *const c_char,
2817 item: *const c_char,
2818 w: i32,
2819 j: bool,
2820 request_id: i32
2821}
2822#[repr(C)]
2823pub struct InsertOneResponseWrapper {
2824 success: bool,
2825 result: *const c_char,
2826 error: *const c_char,
2827 request_id: i32
2828}
2829#[no_mangle]
2830#[tracing::instrument(skip_all)]
2831pub extern "C" fn insert_one(
2832 client: *mut ClientWrapper,
2833 options: *mut InsertOneRequestWrapper,
2834) -> *mut InsertOneResponseWrapper {
2835 let options = match safe_wrapper(options) {
2836 Some(options) => options,
2837 None => {
2838 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2839 let response = InsertOneResponseWrapper {
2840 success: false,
2841 result: std::ptr::null(),
2842 error: error_msg,
2843 request_id: 0,
2844 };
2845 return Box::into_raw(Box::new(response));
2846 }
2847 };
2848 let client_wrapper = match safe_wrapper(client) {
2849 Some(client) => client,
2850 None => {
2851 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2852 let response = InsertOneResponseWrapper {
2853 success: false,
2854 result: std::ptr::null(),
2855 error: error_msg,
2856 request_id: options.request_id,
2857 };
2858 return Box::into_raw(Box::new(response));
2859 }
2860 };
2861 let client = client_wrapper.client.clone();
2862 let request = InsertOneRequest {
2863 collectionname: c_char_to_str(options.collectionname),
2864 item: c_char_to_str(options.item),
2865 w: options.w,
2866 j: options.j,
2867 };
2868 if client.is_none() {
2869 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2870 let response = InsertOneResponseWrapper {
2871 success: false,
2872 result: std::ptr::null(),
2873 error: error_msg,
2874 request_id: options.request_id,
2875 };
2876 return Box::into_raw(Box::new(response));
2877 }
2878 let client = client.unwrap();
2879 let result = tokio::task::block_in_place(|| {
2880 let handle = client.get_runtime_handle();
2881 handle.block_on( client.insert_one(request, openiap_client::EnvConfig::new()))
2882 });
2883
2884 let response = match result {
2885 Ok(data) => {
2886 let result = CString::new(data.result).unwrap().into_raw();
2887 InsertOneResponseWrapper {
2888 success: true,
2889 result,
2890 error: std::ptr::null(),
2891 request_id: options.request_id,
2892 }
2893 }
2894 Err(e) => {
2895 let error_msg = CString::new(format!("InsertOne failed: {:?}", e))
2896 .unwrap()
2897 .into_raw();
2898 InsertOneResponseWrapper {
2899 success: false,
2900 result: std::ptr::null(),
2901 error: error_msg,
2902 request_id: options.request_id,
2903 }
2904 }
2905 };
2906
2907 Box::into_raw(Box::new(response))
2908}
2909
2910type InsertOneCallback = extern "C" fn(wrapper: *mut InsertOneResponseWrapper);
2911#[no_mangle]
2912#[tracing::instrument(skip_all)]
2913pub extern "C" fn insert_one_async(
2914 client: *mut ClientWrapper,
2915 options: *mut InsertOneRequestWrapper,
2916 callback: InsertOneCallback,
2917) {
2918 let options = match safe_wrapper(options) {
2919 Some(options) => options,
2920 None => {
2921 let error_msg = CString::new("Invalid options").unwrap().into_raw();
2922 let response = InsertOneResponseWrapper {
2923 success: false,
2924 result: std::ptr::null(),
2925 error: error_msg,
2926 request_id: 0,
2927 };
2928 return callback(Box::into_raw(Box::new(response)));
2929 }
2930 };
2931 let client_wrapper = match safe_wrapper(client) {
2932 Some(client) => client,
2933 None => {
2934 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2935 let response = InsertOneResponseWrapper {
2936 success: false,
2937 result: std::ptr::null(),
2938 error: error_msg,
2939 request_id: options.request_id,
2940 };
2941 return callback(Box::into_raw(Box::new(response)));
2942 }
2943 };
2944 let client = client_wrapper.client.clone();
2945 let request = InsertOneRequest {
2946 collectionname: c_char_to_str(options.collectionname),
2947 item: c_char_to_str(options.item),
2948 w: options.w,
2949 j: options.j,
2950 };
2951 if client.is_none() {
2952 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
2953 let response = InsertOneResponseWrapper {
2954 success: false,
2955 result: std::ptr::null(),
2956 error: error_msg,
2957 request_id: options.request_id,
2958 };
2959 return callback(Box::into_raw(Box::new(response)));
2960 }
2961
2962 let client = client.unwrap();
2963 let handle = client.get_runtime_handle();
2964 let request_id = options.request_id;
2965 handle.spawn(async move {
2966 let result = client.insert_one(request, openiap_client::EnvConfig::new()).await;
2967 let response = match result {
2968 Ok(data) => {
2969 let result = CString::new(data.result).unwrap().into_raw();
2970 InsertOneResponseWrapper {
2971 success: true,
2972 result,
2973 error: std::ptr::null(),
2974 request_id,
2975 }
2976 }
2977 Err(e) => {
2978 let error_msg = CString::new(format!("InsertOne failed: {:?}", e))
2979 .unwrap()
2980 .into_raw();
2981 InsertOneResponseWrapper {
2982 success: false,
2983 result: std::ptr::null(),
2984 error: error_msg,
2985 request_id,
2986 }
2987 }
2988 };
2989
2990 callback(Box::into_raw(Box::new(response)));
2991 });
2992}
2993#[no_mangle]
2994#[tracing::instrument(skip_all)]
2995pub extern "C" fn free_insert_one_response(response: *mut InsertOneResponseWrapper) {
2996 if response.is_null() {
2997 return;
2998 }
2999 unsafe {
3000 if !(*response).error.is_null() {
3001 let _ = CString::from_raw((*response).error as *mut c_char);
3002 }
3003 if !(*response).result.is_null() {
3004 let _ = CString::from_raw((*response).result as *mut c_char);
3005 }
3006 let _ = Box::from_raw(response);
3007 }
3008}
3009#[repr(C)]
3010pub struct InsertManyRequestWrapper {
3011 collectionname: *const c_char,
3012 items: *const c_char,
3013 w: i32,
3014 j: bool,
3015 skipresults: bool,
3016 request_id: i32
3017}
3018#[repr(C)]
3019pub struct InsertManyResponseWrapper {
3020 success: bool,
3021 results: *const c_char,
3022 error: *const c_char,
3023 request_id: i32,
3024}
3025#[no_mangle]
3026#[tracing::instrument(skip_all)]
3027pub extern "C" fn insert_many(
3028 client: *mut ClientWrapper,
3029 options: *mut InsertManyRequestWrapper,
3030) -> *mut InsertManyResponseWrapper {
3031 let options = match safe_wrapper(options) {
3032 Some(options) => options,
3033 None => {
3034 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3035 let response = InsertManyResponseWrapper {
3036 success: false,
3037 results: std::ptr::null(),
3038 error: error_msg,
3039 request_id: 0,
3040 };
3041 return Box::into_raw(Box::new(response));
3042 }
3043 };
3044 let client_wrapper = match safe_wrapper(client) {
3045 Some(client) => client,
3046 None => {
3047 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3048 let response = InsertManyResponseWrapper {
3049 success: false,
3050 results: std::ptr::null(),
3051 error: error_msg,
3052 request_id: options.request_id,
3053 };
3054 return Box::into_raw(Box::new(response));
3055 }
3056 };
3057 let client = client_wrapper.client.clone();
3058 let request = InsertManyRequest {
3059 collectionname: c_char_to_str(options.collectionname),
3060 items: c_char_to_str(options.items),
3061 w: options.w,
3062 j: options.j,
3063 skipresults: options.skipresults
3064 };
3065 if client.is_none() {
3066 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3067 let response = InsertManyResponseWrapper {
3068 success: false,
3069 results: std::ptr::null(),
3070 error: error_msg,
3071 request_id: options.request_id,
3072 };
3073 return Box::into_raw(Box::new(response));
3074 }
3075 let client = client.unwrap();
3076 let result = tokio::task::block_in_place(|| {
3077 let handle = client.get_runtime_handle();
3078 handle.block_on( client.insert_many(request, openiap_client::EnvConfig::new()))
3079 });
3080
3081 let response = match result {
3082 Ok(data) => {
3083 let results = CString::new(data.results).unwrap().into_raw();
3084 InsertManyResponseWrapper {
3085 success: true,
3086 results,
3087 error: std::ptr::null(),
3088 request_id: options.request_id,
3089 }
3090 }
3091 Err(e) => {
3092 let error_msg = CString::new(format!("InsertMany failed: {:?}", e))
3093 .unwrap()
3094 .into_raw();
3095 InsertManyResponseWrapper {
3096 success: false,
3097 results: std::ptr::null(),
3098 error: error_msg,
3099 request_id: options.request_id,
3100 }
3101 }
3102 };
3103
3104 Box::into_raw(Box::new(response))
3105}
3106
3107type InsertManyCallback = extern "C" fn(wrapper: *mut InsertManyResponseWrapper);
3108#[no_mangle]
3109#[tracing::instrument(skip_all)]
3110pub extern "C" fn insert_many_async(
3111 client: *mut ClientWrapper,
3112 options: *mut InsertManyRequestWrapper,
3113 callback: InsertManyCallback,
3114) {
3115 let options = match safe_wrapper(options) {
3116 Some(options) => options,
3117 None => {
3118 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3119 let response = InsertManyResponseWrapper {
3120 success: false,
3121 results: std::ptr::null(),
3122 error: error_msg,
3123 request_id: 0,
3124 };
3125 return callback(Box::into_raw(Box::new(response)));
3126 }
3127 };
3128 let client_wrapper = match safe_wrapper(client) {
3129 Some(client) => client,
3130 None => {
3131 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3132 let response = InsertManyResponseWrapper {
3133 success: false,
3134 results: std::ptr::null(),
3135 error: error_msg,
3136 request_id: options.request_id,
3137 };
3138 return callback(Box::into_raw(Box::new(response)));
3139 }
3140 };
3141 let client = client_wrapper.client.clone();
3142 let request = InsertManyRequest {
3143 collectionname: c_char_to_str(options.collectionname),
3144 items: c_char_to_str(options.items),
3145 w: options.w,
3146 j: options.j,
3147 skipresults: options.skipresults
3148 };
3149 if client.is_none() {
3150 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3151 let response = InsertManyResponseWrapper {
3152 success: false,
3153 results: std::ptr::null(),
3154 error: error_msg,
3155 request_id: options.request_id,
3156 };
3157 return callback(Box::into_raw(Box::new(response)));
3158 }
3159
3160 let client = client.unwrap();
3161 let handle = client.get_runtime_handle();
3162 let request_id = options.request_id;
3163 handle.spawn(async move {
3164 let result = client.insert_many(request, openiap_client::EnvConfig::new()).await;
3165 let response = match result {
3166 Ok(data) => {
3167 let results = CString::new(data.results.clone()).unwrap().into_raw();
3168 InsertManyResponseWrapper {
3169 success: true,
3170 results,
3171 error: std::ptr::null(),
3172 request_id,
3173 }
3174 }
3175 Err(e) => {
3176 let error_msg = CString::new(format!("InsertMany failed: {:?}", e))
3177 .unwrap()
3178 .into_raw();
3179 InsertManyResponseWrapper {
3180 success: false,
3181 results: std::ptr::null(),
3182 error: error_msg,
3183 request_id,
3184 }
3185 }
3186 };
3187
3188 callback(Box::into_raw(Box::new(response)));
3189 });
3190}
3191
3192#[no_mangle]
3193#[tracing::instrument(skip_all)]
3194pub extern "C" fn free_insert_many_response(response: *mut InsertManyResponseWrapper) {
3195 if response.is_null() {
3196 return;
3197 }
3198 unsafe {
3199 if !(*response).results.is_null() {
3200 let _ = CString::from_raw((*response).results as *mut c_char);
3201 }
3202 let _ = Box::from_raw(response);
3203 }
3204}
3205
3206#[repr(C)]
3207pub struct UpdateOneRequestWrapper {
3208 collectionname: *const c_char,
3209 item: *const c_char,
3210 w: i32,
3211 j: bool,
3212 request_id: i32
3213}
3214#[repr(C)]
3215pub struct UpdateOneResponseWrapper {
3216 success: bool,
3217 result: *const c_char,
3218 error: *const c_char,
3219 request_id: i32
3220}
3221#[no_mangle]
3222#[tracing::instrument(skip_all)]
3223pub extern "C" fn update_one(
3224 client: *mut ClientWrapper,
3225 options: *mut UpdateOneRequestWrapper,
3226) -> *mut UpdateOneResponseWrapper {
3227 let options = match safe_wrapper(options) {
3228 Some(options) => options,
3229 None => {
3230 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3231 let response = UpdateOneResponseWrapper {
3232 success: false,
3233 result: std::ptr::null(),
3234 error: error_msg,
3235 request_id: 0,
3236 };
3237 return Box::into_raw(Box::new(response));
3238 }
3239 };
3240 let client_wrapper = match safe_wrapper(client) {
3241 Some(client) => client,
3242 None => {
3243 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3244 let response = UpdateOneResponseWrapper {
3245 success: false,
3246 result: std::ptr::null(),
3247 error: error_msg,
3248 request_id: options.request_id,
3249 };
3250 return Box::into_raw(Box::new(response));
3251 }
3252 };
3253 let client = client_wrapper.client.clone();
3254 let request = UpdateOneRequest {
3255 collectionname: c_char_to_str(options.collectionname),
3256 item: c_char_to_str(options.item),
3257 w: options.w,
3258 j: options.j
3259 };
3260 if client.is_none() {
3261 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3262 let response = UpdateOneResponseWrapper {
3263 success: false,
3264 result: std::ptr::null(),
3265 error: error_msg,
3266 request_id: options.request_id,
3267 };
3268 return Box::into_raw(Box::new(response));
3269 }
3270 let client = client.unwrap();
3271 let result = tokio::task::block_in_place(|| {
3272 let handle = client.get_runtime_handle();
3273 handle.block_on( client.update_one(request, openiap_client::EnvConfig::new()))
3274 });
3275
3276 let response = match result {
3277 Ok(data) => {
3278 let result = CString::new(data.result).unwrap().into_raw();
3279 UpdateOneResponseWrapper {
3280 success: true,
3281 result,
3282 error: std::ptr::null(),
3283 request_id: options.request_id,
3284 }
3285 }
3286 Err(e) => {
3287 let error_msg = CString::new(format!("UpdateOne failed: {:?}", e))
3288 .unwrap()
3289 .into_raw();
3290 UpdateOneResponseWrapper {
3291 success: false,
3292 result: std::ptr::null(),
3293 error: error_msg,
3294 request_id: options.request_id,
3295 }
3296 }
3297 };
3298
3299 Box::into_raw(Box::new(response))
3300}
3301
3302type UpdateOneCallback = extern "C" fn(wrapper: *mut UpdateOneResponseWrapper);
3303#[no_mangle]
3304#[tracing::instrument(skip_all)]
3305pub extern "C" fn update_one_async(
3306 client: *mut ClientWrapper,
3307 options: *mut UpdateOneRequestWrapper,
3308 callback: UpdateOneCallback,
3309) {
3310 let options = match safe_wrapper(options) {
3311 Some(options) => options,
3312 None => {
3313 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3314 let response = UpdateOneResponseWrapper {
3315 success: false,
3316 result: std::ptr::null(),
3317 error: error_msg,
3318 request_id: 0,
3319 };
3320 return callback(Box::into_raw(Box::new(response)));
3321 }
3322 };
3323 let client_wrapper = match safe_wrapper(client) {
3324 Some(client) => client,
3325 None => {
3326 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3327 let response = UpdateOneResponseWrapper {
3328 success: false,
3329 result: std::ptr::null(),
3330 error: error_msg,
3331 request_id: options.request_id,
3332 };
3333 return callback(Box::into_raw(Box::new(response)));
3334 }
3335 };
3336 let client = client_wrapper.client.clone();
3337 let request = UpdateOneRequest {
3338 collectionname: c_char_to_str(options.collectionname),
3339 item: c_char_to_str(options.item),
3340 w: options.w,
3341 j: options.j
3342 };
3343 if client.is_none() {
3344 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3345 let response = UpdateOneResponseWrapper {
3346 success: false,
3347 result: std::ptr::null(),
3348 error: error_msg,
3349 request_id: options.request_id,
3350 };
3351 return callback(Box::into_raw(Box::new(response)));
3352 }
3353
3354 let client = client.unwrap();
3355 let handle = client.get_runtime_handle();
3356 let request_id = options.request_id;
3357 handle.spawn(async move {
3358 let result = client.update_one(request, openiap_client::EnvConfig::new()).await;
3359 let response = match result {
3360 Ok(data) => {
3361 let result = CString::new(data.result).unwrap().into_raw();
3362 UpdateOneResponseWrapper {
3363 success: true,
3364 result,
3365 error: std::ptr::null(),
3366 request_id,
3367 }
3368 }
3369 Err(e) => {
3370 let error_msg = CString::new(format!("UpdateOne failed: {:?}", e))
3371 .unwrap()
3372 .into_raw();
3373 UpdateOneResponseWrapper {
3374 success: false,
3375 result: std::ptr::null(),
3376 error: error_msg,
3377 request_id,
3378 }
3379 }
3380 };
3381
3382 callback(Box::into_raw(Box::new(response)));
3383 });
3384}
3385
3386#[no_mangle]
3387#[tracing::instrument(skip_all)]
3388pub extern "C" fn free_update_one_response(response: *mut UpdateOneResponseWrapper) {
3389 if response.is_null() {
3390 return;
3391 }
3392 unsafe {
3393 if !(*response).error.is_null() {
3394 let _ = CString::from_raw((*response).error as *mut c_char);
3395 }
3396 if !(*response).result.is_null() {
3397 let _ = CString::from_raw((*response).result as *mut c_char);
3398 }
3399 let _ = Box::from_raw(response);
3400 }
3401}
3402
3403#[repr(C)]
3404pub struct InsertOrUpdateOneRequestWrapper {
3405 collectionname: *const c_char,
3406 uniqeness: *const c_char,
3407 item: *const c_char,
3408 w: i32,
3409 j: bool,
3410 request_id: i32
3411}
3412#[repr(C)]
3413pub struct InsertOrUpdateOneResponseWrapper {
3414 success: bool,
3415 result: *const c_char,
3416 error: *const c_char,
3417 request_id: i32
3418}
3419#[no_mangle]
3420#[tracing::instrument(skip_all)]
3421pub extern "C" fn insert_or_update_one(
3422 client: *mut ClientWrapper,
3423 options: *mut InsertOrUpdateOneRequestWrapper,
3424) -> *mut InsertOrUpdateOneResponseWrapper {
3425 let options = match safe_wrapper(options) {
3426 Some(options) => options,
3427 None => {
3428 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3429 let response = InsertOrUpdateOneResponseWrapper {
3430 success: false,
3431 result: std::ptr::null(),
3432 error: error_msg,
3433 request_id: 0,
3434 };
3435 return Box::into_raw(Box::new(response));
3436 }
3437 };
3438 let client_wrapper = match safe_wrapper(client) {
3439 Some(client) => client,
3440 None => {
3441 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3442 let response = InsertOrUpdateOneResponseWrapper {
3443 success: false,
3444 result: std::ptr::null(),
3445 error: error_msg,
3446 request_id: options.request_id,
3447 };
3448 return Box::into_raw(Box::new(response));
3449 }
3450 };
3451 let client = client_wrapper.client.clone();
3452 debug!("Rust: insert_or_update_one create request");
3453
3454 trace!("Rust: parse collectionname");
3455 let collectionname = c_char_to_str(options.collectionname);
3456 trace!("Rust: parse uniqeness");
3457 let uniqeness = c_char_to_str(options.uniqeness);
3458 trace!("Rust: parse item");
3459 let item = c_char_to_str(options.item);
3460 trace!("Rust: parse w");
3461 let w = options.w;
3462 trace!("Rust: parse j");
3463 let j = options.j;
3464 let request = InsertOrUpdateOneRequest {
3465 collectionname,
3466 uniqeness,
3467 item,
3468 w,
3469 j
3470 };
3471 if client.is_none() {
3472 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3473 let response = InsertOrUpdateOneResponseWrapper {
3474 success: false,
3475 result: std::ptr::null(),
3476 error: error_msg,
3477 request_id: options.request_id,
3478 };
3479 return Box::into_raw(Box::new(response));
3480 }
3481 let client = client.unwrap();
3482 debug!("Rust: run insert_or_update_one in runtime");
3483 let result = tokio::task::block_in_place(|| {
3484 let handle = client.get_runtime_handle();
3485 handle.block_on( client.insert_or_update_one(request, openiap_client::EnvConfig::new()))
3486 });
3487
3488 let response = match result {
3489 Ok(data) => {
3490 let result = CString::new(data).unwrap().into_raw();
3491 InsertOrUpdateOneResponseWrapper {
3492 success: true,
3493 result,
3494 error: std::ptr::null(),
3495 request_id: options.request_id,
3496 }
3497 }
3498 Err(e) => {
3499 let error_msg = CString::new(format!("InsertOrUpdateOne failed: {:?}", e))
3500 .unwrap()
3501 .into_raw();
3502 InsertOrUpdateOneResponseWrapper {
3503 success: false,
3504 result: std::ptr::null(),
3505 error: error_msg,
3506 request_id: options.request_id,
3507 }
3508 }
3509 };
3510
3511 Box::into_raw(Box::new(response))
3512}
3513
3514type InsertOrUpdateOneCallback = extern "C" fn(wrapper: *mut InsertOrUpdateOneResponseWrapper);
3515#[no_mangle]
3516#[tracing::instrument(skip_all)]
3517pub extern "C" fn insert_or_update_one_async(
3518 client: *mut ClientWrapper,
3519 options: *mut InsertOrUpdateOneRequestWrapper,
3520 callback: InsertOrUpdateOneCallback,
3521) {
3522 let options = match safe_wrapper(options) {
3523 Some(options) => options,
3524 None => {
3525 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3526 let response = InsertOrUpdateOneResponseWrapper {
3527 success: false,
3528 result: std::ptr::null(),
3529 error: error_msg,
3530 request_id: 0,
3531 };
3532 return callback(Box::into_raw(Box::new(response)));
3533 }
3534 };
3535 let client_wrapper = match safe_wrapper(client) {
3536 Some(client) => client,
3537 None => {
3538 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3539 let response = InsertOrUpdateOneResponseWrapper {
3540 success: false,
3541 result: std::ptr::null(),
3542 error: error_msg,
3543 request_id: options.request_id,
3544 };
3545 return callback(Box::into_raw(Box::new(response)));
3546 }
3547 };
3548 let client = client_wrapper.client.clone();
3549 debug!("Rust: insert_or_update_one_async create request");
3550 let request = InsertOrUpdateOneRequest {
3551 collectionname: c_char_to_str(options.collectionname),
3552 uniqeness: c_char_to_str(options.uniqeness),
3553 item: c_char_to_str(options.item),
3554 w: options.w,
3555 j: options.j
3556 };
3557 if client.is_none() {
3558 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3559 let response = InsertOrUpdateOneResponseWrapper {
3560 success: false,
3561 result: std::ptr::null(),
3562 error: error_msg,
3563 request_id: options.request_id,
3564 };
3565 return callback(Box::into_raw(Box::new(response)));
3566 }
3567 let client = client.unwrap();
3568 let handle = client.get_runtime_handle();
3569 let request_id = options.request_id;
3570 handle.spawn(async move {
3571 let result = client.insert_or_update_one(request, openiap_client::EnvConfig::new()).await;
3572
3573 let response = match result {
3574 Ok(data) => {
3575 let result = CString::new(data).unwrap().into_raw();
3576 InsertOrUpdateOneResponseWrapper {
3577 success: true,
3578 result,
3579 error: std::ptr::null(),
3580 request_id,
3581 }
3582 }
3583 Err(e) => {
3584 let error_msg = CString::new(format!("InsertOrUpdateOne failed: {:?}", e))
3585 .unwrap()
3586 .into_raw();
3587 InsertOrUpdateOneResponseWrapper {
3588 success: false,
3589 result: std::ptr::null(),
3590 error: error_msg,
3591 request_id,
3592 }
3593 }
3594 };
3595
3596 callback(Box::into_raw(Box::new(response)));
3597 });
3598}
3599#[no_mangle]
3600#[tracing::instrument(skip_all)]
3601pub extern "C" fn free_insert_or_update_one_response(response: *mut InsertOrUpdateOneResponseWrapper) {
3602 if response.is_null() {
3603 return;
3604 }
3605 unsafe {
3606 if !(*response).error.is_null() {
3607 let _ = CString::from_raw((*response).error as *mut c_char);
3608 }
3609 if !(*response).result.is_null() {
3610 let _ = CString::from_raw((*response).result as *mut c_char);
3611 }
3612 let _ = Box::from_raw(response);
3613 }
3614}
3615
3616#[repr(C)]
3617pub struct DeleteOneRequestWrapper {
3618 collectionname: *const c_char,
3619 id: *const c_char,
3620 recursive: bool,
3621 request_id: i32
3622}
3623#[repr(C)]
3624pub struct DeleteOneResponseWrapper {
3625 success: bool,
3626 affectedrows: i32,
3627 error: *const c_char,
3628 request_id: i32
3629}
3630#[no_mangle]
3631#[tracing::instrument(skip_all)]
3632pub extern "C" fn delete_one(
3633 client: *mut ClientWrapper,
3634 options: *mut DeleteOneRequestWrapper,
3635) -> *mut DeleteOneResponseWrapper {
3636 let options = match safe_wrapper(options) {
3637 Some(options) => options,
3638 None => {
3639 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3640 let response = DeleteOneResponseWrapper {
3641 success: false,
3642 affectedrows: 0,
3643 error: error_msg,
3644 request_id: 0,
3645 };
3646 return Box::into_raw(Box::new(response));
3647 }
3648 };
3649 let client_wrapper = match safe_wrapper(client) {
3650 Some(client) => client,
3651 None => {
3652 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3653 let response = DeleteOneResponseWrapper {
3654 success: false,
3655 affectedrows: 0,
3656 error: error_msg,
3657 request_id: options.request_id,
3658 };
3659 return Box::into_raw(Box::new(response));
3660 }
3661 };
3662 let client = client_wrapper.client.clone();
3663 let request = DeleteOneRequest {
3664 collectionname: c_char_to_str(options.collectionname),
3665 id: c_char_to_str(options.id),
3666 recursive: options.recursive
3667 };
3668 if client.is_none() {
3669 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3670 let response = DeleteOneResponseWrapper {
3671 success: false,
3672 affectedrows: 0,
3673 error: error_msg,
3674 request_id: options.request_id,
3675 };
3676 return Box::into_raw(Box::new(response));
3677 }
3678 let client = client.unwrap();
3679 let result = tokio::task::block_in_place(|| {
3680 let handle = client.get_runtime_handle();
3681 handle.block_on( client.delete_one(request, openiap_client::EnvConfig::new()))
3682 });
3683
3684 let response = match result {
3685 Ok(data) => {
3686 let affectedrows = data;
3687 DeleteOneResponseWrapper {
3688 success: true,
3689 affectedrows,
3690 error: std::ptr::null(),
3691 request_id: options.request_id,
3692 }
3693 }
3694 Err(e) => {
3695 let error_msg = CString::new(format!("DeleteOne failed: {:?}", e))
3696 .unwrap()
3697 .into_raw();
3698 DeleteOneResponseWrapper {
3699 success: false,
3700 affectedrows: 0,
3701 error: error_msg,
3702 request_id: options.request_id,
3703 }
3704 }
3705 };
3706
3707 Box::into_raw(Box::new(response))
3708}
3709type DeleteOneCallback = extern "C" fn(wrapper: *mut DeleteOneResponseWrapper);
3710#[no_mangle]
3711#[tracing::instrument(skip_all)]
3712pub extern "C" fn delete_one_async(
3713 client: *mut ClientWrapper,
3714 options: *mut DeleteOneRequestWrapper,
3715 callback: DeleteOneCallback,
3716) {
3717 let options = match safe_wrapper(options) {
3718 Some(options) => options,
3719 None => {
3720 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3721 let response = DeleteOneResponseWrapper {
3722 success: false,
3723 affectedrows: 0,
3724 error: error_msg,
3725 request_id: 0,
3726 };
3727 return callback(Box::into_raw(Box::new(response)));
3728 }
3729 };
3730 let client_wrapper = match safe_wrapper(client) {
3731 Some(client) => client,
3732 None => {
3733 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3734 let response = DeleteOneResponseWrapper {
3735 success: false,
3736 affectedrows: 0,
3737 error: error_msg,
3738 request_id: options.request_id,
3739 };
3740 return callback(Box::into_raw(Box::new(response)));
3741 }
3742 };
3743 let client = client_wrapper.client.clone();
3744 let request = DeleteOneRequest {
3745 collectionname: c_char_to_str(options.collectionname),
3746 id: c_char_to_str(options.id),
3747 recursive: options.recursive
3748 };
3749 if client.is_none() {
3750 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3751 let response = DeleteOneResponseWrapper {
3752 success: false,
3753 affectedrows: 0,
3754 error: error_msg,
3755 request_id: options.request_id,
3756 };
3757 return callback(Box::into_raw(Box::new(response)));
3758 }
3759
3760 let client = client.unwrap();
3761 let handle = client.get_runtime_handle();
3762 let request_id = options.request_id;
3763 handle.spawn(async move {
3764 let result = client.delete_one(request, openiap_client::EnvConfig::new()).await;
3765 let response = match result {
3766 Ok(data) => {
3767 let affectedrows = data;
3768 DeleteOneResponseWrapper {
3769 success: true,
3770 affectedrows,
3771 error: std::ptr::null(),
3772 request_id,
3773 }
3774 }
3775 Err(e) => {
3776 let error_msg = CString::new(format!("DeleteOne failed: {:?}", e))
3777 .unwrap()
3778 .into_raw();
3779 DeleteOneResponseWrapper {
3780 success: false,
3781 affectedrows: 0,
3782 error: error_msg,
3783 request_id,
3784 }
3785 }
3786 };
3787
3788 callback(Box::into_raw(Box::new(response)));
3789 });
3790}
3791#[no_mangle]
3792#[tracing::instrument(skip_all)]
3793pub extern "C" fn free_delete_one_response(response: *mut DeleteOneResponseWrapper) {
3794 if response.is_null() {
3795 return;
3796 }
3797 unsafe {
3798 if !(*response).error.is_null() {
3799 let _ = CString::from_raw((*response).error as *mut c_char);
3800 }
3801 let _ = Box::from_raw(response);
3802 }
3803}
3804
3805#[repr(C)]
3806pub struct DeleteManyRequestWrapper {
3807 collectionname: *const c_char,
3808 query: *const c_char,
3809 recursive: bool,
3810 ids: *const *const c_char,
3811 request_id: i32
3812}
3813#[repr(C)]
3814pub struct DeleteManyResponseWrapper {
3815 success: bool,
3816 affectedrows: i32,
3817 error: *const c_char,
3818 request_id: i32
3819}
3820#[no_mangle]
3821#[tracing::instrument(skip_all)]
3822pub extern "C" fn delete_many(
3823 client: *mut ClientWrapper,
3824 options: *mut DeleteManyRequestWrapper,
3825) -> *mut DeleteManyResponseWrapper {
3826 let options = match safe_wrapper(options) {
3827 Some(options) => options,
3828 None => {
3829 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3830 let response = DeleteManyResponseWrapper {
3831 success: false,
3832 affectedrows: 0,
3833 error: error_msg,
3834 request_id: 0,
3835 };
3836 return Box::into_raw(Box::new(response));
3837 }
3838 };
3839 let client_wrapper = match safe_wrapper(client) {
3840 Some(client) => client,
3841 None => {
3842 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3843 let response = DeleteManyResponseWrapper {
3844 success: false,
3845 affectedrows: 0,
3846 error: error_msg,
3847 request_id: options.request_id,
3848 };
3849 return Box::into_raw(Box::new(response));
3850 }
3851 };
3852 let client = client_wrapper.client.clone();
3853 let request = DeleteManyRequest {
3854 collectionname: c_char_to_str(options.collectionname),
3855 query: c_char_to_str(options.query),
3856 recursive: options.recursive,
3857 ids: {
3858 let mut ids = vec![];
3859 if !options.ids.is_null() {
3860 let mut i = 0;
3861 loop {
3862 let id = unsafe { *options.ids.add(i) };
3863 if id.is_null() {
3864 break;
3865 }
3866 ids.push(c_char_to_str(id));
3867 i += 1;
3868 }
3869 }
3870 ids
3871 }
3872 };
3873 if client.is_none() {
3874 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3875 let response = DeleteManyResponseWrapper {
3876 success: false,
3877 affectedrows: 0,
3878 error: error_msg,
3879 request_id: options.request_id,
3880 };
3881 return Box::into_raw(Box::new(response));
3882 }
3883 let client = client.unwrap();
3884 let result = tokio::task::block_in_place(|| {
3885 let handle = client.get_runtime_handle();
3886 handle.block_on( client.delete_many(request, openiap_client::EnvConfig::new()))
3887 });
3888
3889 let response = match result {
3890 Ok(data) => {
3891 let affectedrows = data;
3892 DeleteManyResponseWrapper {
3893 success: true,
3894 affectedrows,
3895 error: std::ptr::null(),
3896 request_id: options.request_id,
3897 }
3898 }
3899 Err(e) => {
3900 let error_msg = CString::new(format!("DeleteMany failed: {:?}", e))
3901 .unwrap()
3902 .into_raw();
3903 DeleteManyResponseWrapper {
3904 success: false,
3905 affectedrows: 0,
3906 error: error_msg,
3907 request_id: options.request_id,
3908 }
3909 }
3910 };
3911
3912 Box::into_raw(Box::new(response))
3913}
3914type DeleteManyCallback = extern "C" fn(wrapper: *mut DeleteManyResponseWrapper);
3915#[no_mangle]
3916#[tracing::instrument(skip_all)]
3917pub extern "C" fn delete_many_async(
3918 client: *mut ClientWrapper,
3919 options: *mut DeleteManyRequestWrapper,
3920 callback: DeleteManyCallback,
3921) {
3922 let options = match safe_wrapper(options) {
3923 Some(options) => options,
3924 None => {
3925 let error_msg = CString::new("Invalid options").unwrap().into_raw();
3926 let response = DeleteManyResponseWrapper {
3927 success: false,
3928 affectedrows: 0,
3929 error: error_msg,
3930 request_id: 0,
3931 };
3932 return callback(Box::into_raw(Box::new(response)));
3933 }
3934 };
3935 let client_wrapper = match safe_wrapper(client) {
3936 Some(client) => client,
3937 None => {
3938 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3939 let response = DeleteManyResponseWrapper {
3940 success: false,
3941 affectedrows: 0,
3942 error: error_msg,
3943 request_id: options.request_id,
3944 };
3945 return callback(Box::into_raw(Box::new(response)));
3946 }
3947 };
3948 let client = client_wrapper.client.clone();
3949 let request = DeleteManyRequest {
3950 collectionname: c_char_to_str(options.collectionname),
3951 query: c_char_to_str(options.query),
3952 recursive: options.recursive,
3953 ids: {
3954 let mut ids = vec![];
3955 let mut i = 0;
3956 loop {
3957 let id = unsafe { *options.ids.add(i) };
3958 if id.is_null() {
3959 break;
3960 }
3961 let id = c_char_to_str(id);
3962 ids.push(id);
3963 i += 1;
3964 }
3965 ids
3966 }
3967 };
3968 if client.is_none() {
3969 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
3970 let response = DeleteManyResponseWrapper {
3971 success: false,
3972 affectedrows: 0,
3973 error: error_msg,
3974 request_id: options.request_id,
3975 };
3976 return callback(Box::into_raw(Box::new(response)));
3977 }
3978 let client = client.unwrap();
3979 let handle = client.get_runtime_handle();
3980 let request_id = options.request_id;
3981 handle.spawn(async move {
3982 let result = client.delete_many(request, openiap_client::EnvConfig::new()).await;
3983 let response = match result {
3984 Ok(data) => {
3985 let affectedrows = data;
3986 DeleteManyResponseWrapper {
3987 success: true,
3988 affectedrows,
3989 error: std::ptr::null(),
3990 request_id,
3991 }
3992 }
3993 Err(e) => {
3994 let error_msg = CString::new(format!("DeleteMany failed: {:?}", e))
3995 .unwrap()
3996 .into_raw();
3997 DeleteManyResponseWrapper {
3998 success: false,
3999 affectedrows: 0,
4000 error: error_msg,
4001 request_id,
4002 }
4003 }
4004 };
4005
4006 callback(Box::into_raw(Box::new(response)));
4007 });
4008}
4009#[no_mangle]
4010#[tracing::instrument(skip_all)]
4011pub extern "C" fn free_delete_many_response(response: *mut DeleteManyResponseWrapper) {
4012 if response.is_null() {
4013 return;
4014 }
4015 unsafe {
4016 if !(*response).error.is_null() {
4017 let _ = CString::from_raw((*response).error as *mut c_char);
4018 }
4019 let _ = Box::from_raw(response);
4020 }
4021}
4022
4023#[repr(C)]
4024pub struct DownloadRequestWrapper {
4025 collectionname: *const c_char,
4026 id: *const c_char,
4027 folder: *const c_char,
4028 filename: *const c_char,
4029 request_id: i32
4030}
4031#[repr(C)]
4032pub struct DownloadResponseWrapper {
4033 success: bool,
4034 filename: *const c_char,
4035 error: *const c_char,
4036 request_id: i32
4037}
4038#[no_mangle]
4039#[tracing::instrument(skip_all)]
4040pub extern "C" fn download(
4041 client: *mut ClientWrapper,
4042 options: *mut DownloadRequestWrapper,
4043) -> *mut DownloadResponseWrapper {
4044 let options = match safe_wrapper(options) {
4045 Some(options) => options,
4046 None => {
4047 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4048 let response = DownloadResponseWrapper {
4049 success: false,
4050 filename: std::ptr::null(),
4051 error: error_msg,
4052 request_id: 0,
4053 };
4054 return Box::into_raw(Box::new(response));
4055 }
4056 };
4057 let client_wrapper = match safe_wrapper(client) {
4058 Some(client) => client,
4059 None => {
4060 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4061 let response = DownloadResponseWrapper {
4062 success: false,
4063 filename: std::ptr::null(),
4064 error: error_msg,
4065 request_id: options.request_id,
4066 };
4067 return Box::into_raw(Box::new(response));
4068 }
4069 };
4070 let client = client_wrapper.client.clone();
4071 let folder = c_char_to_str(options.folder);
4072 let filename = c_char_to_str(options.filename);
4073 let request = DownloadRequest {
4074 collectionname: c_char_to_str(options.collectionname),
4075 filename: c_char_to_str(options.filename),
4076 id: c_char_to_str(options.id)
4077 };
4078 if client.is_none() {
4079 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4080 let response = DownloadResponseWrapper {
4081 success: false,
4082 filename: std::ptr::null(),
4083 error: error_msg,
4084 request_id: options.request_id,
4085 };
4086 return Box::into_raw(Box::new(response));
4087 }
4088 let client = client.unwrap();
4089 let result = tokio::task::block_in_place(|| {
4090 let handle = client.get_runtime_handle();
4091 handle.block_on( client.download(request, openiap_client::EnvConfig::new(), Some(&folder), Some(&filename)))
4092 });
4093
4094 let response = match result {
4095 Ok(data) => {
4096 let filename = CString::new(data.filename).unwrap().into_raw();
4097 DownloadResponseWrapper {
4098 success: true,
4099 filename,
4100 error: std::ptr::null(),
4101 request_id: options.request_id,
4102 }
4103 }
4104 Err(e) => {
4105 let error_msg = CString::new(format!("Download failed: {:?}", e))
4106 .unwrap()
4107 .into_raw();
4108 DownloadResponseWrapper {
4109 success: false,
4110 filename: std::ptr::null(),
4111 error: error_msg,
4112 request_id: options.request_id,
4113 }
4114 }
4115 };
4116
4117 Box::into_raw(Box::new(response))
4118}
4119
4120type DownloadCallback = extern "C" fn(wrapper: *mut DownloadResponseWrapper);
4121#[no_mangle]
4122#[tracing::instrument(skip_all)]
4123pub extern "C" fn download_async(
4124 client: *mut ClientWrapper,
4125 options: *mut DownloadRequestWrapper,
4126 callback: DownloadCallback,
4127) {
4128 let options = match safe_wrapper(options) {
4129 Some(options) => options,
4130 None => {
4131 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4132 let response = DownloadResponseWrapper {
4133 success: false,
4134 filename: std::ptr::null(),
4135 error: error_msg,
4136 request_id: 0,
4137 };
4138 return callback(Box::into_raw(Box::new(response)));
4139 }
4140 };
4141 let client_wrapper = match safe_wrapper(client) {
4142 Some(client) => client,
4143 None => {
4144 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4145 let response = DownloadResponseWrapper {
4146 success: false,
4147 filename: std::ptr::null(),
4148 error: error_msg,
4149 request_id: options.request_id,
4150 };
4151 return callback(Box::into_raw(Box::new(response)));
4152 }
4153 };
4154 let client = client_wrapper.client.clone();
4155 let folder = c_char_to_str(options.folder);
4156 let filename = c_char_to_str(options.filename);
4157 let request = DownloadRequest {
4158 collectionname: c_char_to_str(options.collectionname),
4159 filename: c_char_to_str(options.filename),
4160 id: c_char_to_str(options.id)
4161 };
4162 if client.is_none() {
4163 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4164 let response = DownloadResponseWrapper {
4165 success: false,
4166 filename: std::ptr::null(),
4167 error: error_msg,
4168 request_id: options.request_id,
4169 };
4170 return callback(Box::into_raw(Box::new(response)));
4171 }
4172 let client = client.unwrap();
4173 let handle = client.get_runtime_handle();
4174 let request_id = options.request_id;
4175 handle.spawn(async move {
4176 let result = client
4177 .download(request, openiap_client::EnvConfig::new(), Some(&folder), Some(&filename))
4178 .await;
4179
4180 let response = match result {
4181 Ok(data) => {
4182 let filename = CString::new(data.filename).unwrap().into_raw();
4183 DownloadResponseWrapper {
4184 success: true,
4185 filename,
4186 error: std::ptr::null(),
4187 request_id,
4188 }
4189 }
4190 Err(e) => {
4191 let error_msg = CString::new(format!("Download failed: {:?}", e))
4192 .unwrap()
4193 .into_raw();
4194 DownloadResponseWrapper {
4195 success: false,
4196 filename: std::ptr::null(),
4197 error: error_msg,
4198 request_id,
4199 }
4200 }
4201 };
4202
4203 callback(Box::into_raw(Box::new(response)));
4204 });
4205}
4206#[no_mangle]
4207#[tracing::instrument(skip_all)]
4208pub extern "C" fn free_download_response(response: *mut DownloadResponseWrapper) {
4209 if response.is_null() {
4210 return;
4211 }
4212 unsafe {
4213 if !(*response).error.is_null() {
4214 let _ = CString::from_raw((*response).error as *mut c_char);
4215 }
4216 if !(*response).filename.is_null() {
4217 let _ = CString::from_raw((*response).filename as *mut c_char);
4218 }
4219 let _ = Box::from_raw(response);
4220 }
4221}
4222
4223#[repr(C)]
4224pub struct UploadRequestWrapper {
4225 filepath: *const c_char,
4226 filename: *const c_char,
4227 mimetype: *const c_char,
4228 metadata: *const c_char,
4229 collectionname: *const c_char,
4230 request_id: i32
4231}
4232#[repr(C)]
4233pub struct UploadResponseWrapper {
4234 success: bool,
4235 id: *const c_char,
4236 error: *const c_char,
4237 request_id: i32
4238}
4239#[no_mangle]
4240#[tracing::instrument(skip_all)]
4241pub extern "C" fn upload(
4242 client: *mut ClientWrapper,
4243 options: *mut UploadRequestWrapper,
4244) -> *mut UploadResponseWrapper {
4245 let options = match safe_wrapper(options) {
4246 Some(options) => options,
4247 None => {
4248 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4249 let response = UploadResponseWrapper {
4250 success: false,
4251 id: std::ptr::null(),
4252 error: error_msg,
4253 request_id: 0,
4254 };
4255 return Box::into_raw(Box::new(response));
4256 }
4257 };
4258 let client_wrapper = match safe_wrapper(client) {
4259 Some(client) => client,
4260 None => {
4261 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4262 let response = UploadResponseWrapper {
4263 success: false,
4264 id: std::ptr::null(),
4265 error: error_msg,
4266 request_id: options.request_id,
4267 };
4268 return Box::into_raw(Box::new(response));
4269 }
4270 };
4271 let client = client_wrapper.client.clone();
4272 let filepath = c_char_to_str(options.filepath);
4273 if filepath.is_empty() {
4274 let error_msg = CString::new("Filepath is required").unwrap().into_raw();
4275 let response = UploadResponseWrapper {
4276 success: false,
4277 id: std::ptr::null(),
4278 error: error_msg,
4279 request_id: options.request_id,
4280 };
4281 return Box::into_raw(Box::new(response));
4282 }
4283 let filepath = filepath.to_string();
4284 debug!("upload: filepath: {}", filepath);
4285 let filename = c_char_to_str(options.filename);
4286 if filename.is_empty() {
4287 let error_msg = CString::new("Filename is required").unwrap().into_raw();
4288 let response = UploadResponseWrapper {
4289 success: false,
4290 id: std::ptr::null(),
4291 error: error_msg,
4292 request_id: options.request_id,
4293 };
4294 return Box::into_raw(Box::new(response));
4295 }
4296
4297 let request = UploadRequest {
4298 filename: filename.to_string(),
4299 mimetype: c_char_to_str(options.mimetype),
4300 metadata: c_char_to_str(options.metadata),
4301 collectionname: c_char_to_str(options.collectionname)
4302 };
4303 if client.is_none() {
4304 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4305 let response = UploadResponseWrapper {
4306 success: false,
4307 id: std::ptr::null(),
4308 error: error_msg,
4309 request_id: options.request_id,
4310 };
4311 return Box::into_raw(Box::new(response));
4312 }
4313 let client = client.unwrap();
4314 debug!("upload: runtime.block_on");
4315 let result = tokio::task::block_in_place(|| {
4316 let handle = client.get_runtime_handle();
4320 handle.block_on( client.upload(request, openiap_client::EnvConfig::new(), &filepath))
4321 });
4322
4323 let response = match result {
4324 Ok(data) => {
4325 let id = CString::new(data.id).unwrap().into_raw();
4326 UploadResponseWrapper {
4327 success: true,
4328 id,
4329 error: std::ptr::null(),
4330 request_id: options.request_id,
4331 }
4332 }
4333 Err(e) => {
4334 let error_msg = CString::new(format!("Upload failed: {:?}", e))
4335 .unwrap()
4336 .into_raw();
4337 UploadResponseWrapper {
4338 success: false,
4339 id: std::ptr::null(),
4340 error: error_msg,
4341 request_id: options.request_id,
4342 }
4343 }
4344 };
4345 Box::into_raw(Box::new(response))
4346}
4347
4348type UploadCallback = extern "C" fn(wrapper: *mut UploadResponseWrapper);
4349#[no_mangle]
4350#[tracing::instrument(skip_all)]
4351pub extern "C" fn upload_async(
4352 client: *mut ClientWrapper,
4353 options: *mut UploadRequestWrapper,
4354 callback: UploadCallback,
4355) {
4356 let options = match safe_wrapper(options) {
4357 Some(options) => options,
4358 None => {
4359 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4360 let response = UploadResponseWrapper {
4361 success: false,
4362 id: std::ptr::null(),
4363 error: error_msg,
4364 request_id: 0,
4365 };
4366 return callback(Box::into_raw(Box::new(response)));
4367 }
4368 };
4369 let client_wrapper = match safe_wrapper(client) {
4370 Some(client) => client,
4371 None => {
4372 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4373 let response = UploadResponseWrapper {
4374 success: false,
4375 id: std::ptr::null(),
4376 error: error_msg,
4377 request_id: options.request_id,
4378 };
4379 return callback(Box::into_raw(Box::new(response)));
4380 }
4381 };
4382 let client = client_wrapper.client.clone();
4383 let filepath = c_char_to_str(options.filepath);
4384 if filepath.is_empty() {
4385 let error_msg = CString::new("Filepath is required").unwrap().into_raw();
4386 let response = UploadResponseWrapper {
4387 success: false,
4388 id: std::ptr::null(),
4389 error: error_msg,
4390 request_id: options.request_id,
4391 };
4392 return callback(Box::into_raw(Box::new(response)));
4393 }
4394 let filepath = filepath.to_string();
4395 debug!("upload_async: filepath: {}", filepath);
4396 let filename = c_char_to_str(options.filename);
4397 if filename.is_empty() {
4398 let error_msg = CString::new("Filename is required").unwrap().into_raw();
4399 let response = UploadResponseWrapper {
4400 success: false,
4401 id: std::ptr::null(),
4402 error: error_msg,
4403 request_id: options.request_id,
4404 };
4405 return callback(Box::into_raw(Box::new(response)));
4406 }
4407
4408 let request = UploadRequest {
4409 filename: filename.to_string(),
4410 mimetype: c_char_to_str(options.mimetype),
4411 metadata: c_char_to_str(options.metadata),
4412 collectionname: c_char_to_str(options.collectionname)
4413 };
4414 if client.is_none() {
4415 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4416 let response = UploadResponseWrapper {
4417 success: false,
4418 id: std::ptr::null(),
4419 error: error_msg,
4420 request_id: options.request_id,
4421 };
4422 return callback(Box::into_raw(Box::new(response)));
4423 }
4424 debug!("upload_async: runtime.spawn");
4425 let client = client.unwrap();
4426 let handle = client.get_runtime_handle();
4427 let request_id = options.request_id;
4428 handle.spawn(async move {
4429 debug!("upload_async: call client.upload");
4430 let result = client.upload(request, openiap_client::EnvConfig::new(), &filepath).await;
4431
4432 debug!("upload_async: call client.upload done");
4433 let response = match result {
4434 Ok(data) => {
4435 let id = CString::new(data.id).unwrap().into_raw();
4436 UploadResponseWrapper {
4437 success: true,
4438 id,
4439 error: std::ptr::null(),
4440 request_id,
4441 }
4442 }
4443 Err(e) => {
4444 let error_msg = CString::new(format!("Upload failed: {:?}", e))
4445 .unwrap()
4446 .into_raw();
4447 UploadResponseWrapper {
4448 success: false,
4449 id: std::ptr::null(),
4450 error: error_msg,
4451 request_id,
4452 }
4453 }
4454 };
4455 debug!("upload_async: call callback with response");
4456 callback(Box::into_raw(Box::new(response)));
4457 });
4458}
4459#[no_mangle]
4460#[tracing::instrument(skip_all)]
4461pub extern "C" fn free_upload_response(response: *mut UploadResponseWrapper) {
4462 if response.is_null() {
4463 return;
4464 }
4465 unsafe {
4466 if !(*response).error.is_null() {
4467 let _ = CString::from_raw((*response).error as *mut c_char);
4468 }
4469 if !(*response).id.is_null() {
4470 let _ = CString::from_raw((*response).id as *mut c_char);
4471 }
4472 let _ = Box::from_raw(response);
4473 }
4474}
4475
4476#[repr(C)]
4477pub struct WatchRequestWrapper {
4478 collectionname: *const c_char,
4479 paths: *const c_char,
4480 request_id: i32
4481}
4482#[repr(C)]
4483pub struct WatchResponseWrapper {
4484 success: bool,
4485 watchid: *const c_char,
4486 error: *const c_char,
4487 request_id: i32
4488}
4489#[no_mangle]
4490#[tracing::instrument(skip_all)]
4491pub extern "C" fn watch(
4492 client: *mut ClientWrapper,
4493 options: *mut WatchRequestWrapper,
4494) -> *mut WatchResponseWrapper {
4495 let options = match safe_wrapper(options) {
4496 Some(options) => options,
4497 None => {
4498 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4499 let response = WatchResponseWrapper {
4500 success: false,
4501 watchid: std::ptr::null(),
4502 error: error_msg,
4503 request_id: 0,
4504 };
4505 return Box::into_raw(Box::new(response));
4506 }
4507 };
4508 let client_wrapper = match safe_wrapper(client) {
4509 Some(client) => client,
4510 None => {
4511 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4512 let response = WatchResponseWrapper {
4513 success: false,
4514 watchid: std::ptr::null(),
4515 error: error_msg,
4516 request_id: options.request_id,
4517 };
4518 return Box::into_raw(Box::new(response));
4519 }
4520 };
4521 let client = client_wrapper.client.clone();
4522 let paths = c_char_to_str(options.paths);
4524 let paths = paths.split(",").map(|s| s.to_string()).collect();
4525 let request = WatchRequest {
4526 collectionname: c_char_to_str(options.collectionname),
4527 paths,
4528 };
4529 if client.is_none() {
4530 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4531 let response = WatchResponseWrapper {
4532 success: false,
4533 watchid: std::ptr::null(),
4534 error: error_msg,
4535 request_id: options.request_id,
4536 };
4537 return Box::into_raw(Box::new(response));
4538 }
4539 let client = client.unwrap();
4540 let request_id = options.request_id;
4541 let result = tokio::task::block_in_place(|| {
4542 let handle = client.get_runtime_handle();
4543 handle.block_on(
4544 client
4545 .watch(
4546 request,
4547 openiap_client::EnvConfig::new(),
4548 Box::new(move |event: WatchEvent| {
4549 debug!("watch: event: {:?}", event);
4553 let watchid = CString::new(event.id.clone())
4554 .unwrap()
4555 .into_string()
4556 .unwrap();
4557 let mut e = WATCH_EVENTS.lock().unwrap();
4558 let queue = e.get_mut(&watchid);
4559 match queue {
4560 Some(q) => {
4561 q.push_back(event);
4562 }
4563 None => {
4564 let mut q = std::collections::VecDeque::new();
4565 q.push_back(event);
4566 e.insert(watchid, q);
4567 }
4568 }
4569 }),
4570 )
4571 )
4572 });
4573
4574 let response = match result {
4575 Ok(data) => {
4576 let id = String::from(&data);
4577 let mut events = WATCH_EVENTS.lock().unwrap();
4578 let queue = events.get_mut(&id);
4579 if queue.is_none() {
4580 let q = std::collections::VecDeque::new();
4581 let k = String::from(&data);
4582 events.insert(k, q);
4583 }
4584 let watchid = CString::new(id).unwrap().into_raw();
4585 WatchResponseWrapper {
4586 success: true,
4587 watchid,
4588 error: std::ptr::null(),
4589 request_id,
4590 }
4591 }
4592 Err(e) => {
4593 let error_msg = CString::new(format!("Watch failed: {:?}", e))
4594 .unwrap()
4595 .into_raw();
4596 WatchResponseWrapper {
4597 success: false,
4598 watchid: std::ptr::null(),
4599 error: error_msg,
4600 request_id,
4601 }
4602 }
4603 };
4604
4605 Box::into_raw(Box::new(response))
4606}
4607#[no_mangle]
4608#[tracing::instrument(skip_all)]
4609pub extern "C" fn next_watch_event (
4610 watchid: *const c_char,
4611) -> *mut WatchEventWrapper {
4612 trace!("unwrap watchid");
4613 let watchid = c_char_to_str(watchid);
4614 trace!("watchid {:}", watchid);
4615 let watchid = watchid.to_string();
4616 trace!("unwrap events");
4617 let mut e = WATCH_EVENTS.lock().unwrap();
4618 trace!("get queue");
4619 let queue = e.get_mut(&watchid);
4620 match queue {
4621 Some(q) => {
4622 match q.pop_front() {
4623 Some(event) => {
4624 debug!("got event");
4625 let id = CString::new(event.id).unwrap().into_raw();
4626 let operation = CString::new(event.operation).unwrap().into_raw();
4627 let document = CString::new(event.document).unwrap().into_raw();
4628 let event = Box::new(WatchEventWrapper {
4629 id,
4630 operation,
4631 document,
4632 request_id: 0
4633 });
4634 Box::into_raw(event)
4635 }
4636 None => {
4637 trace!("No event");
4638 Box::into_raw(Box::new(WatchEventWrapper::default()))
4639 },
4640 }
4641 },
4642 None => {
4643 debug!("Queue for {:} not found", watchid);
4644 Box::into_raw(Box::new(WatchEventWrapper::default()))
4645 },
4646 }
4647}
4648#[no_mangle]
4649#[tracing::instrument(skip_all)]
4650pub extern "C" fn free_watch_event(response: *mut WatchEventWrapper) {
4651 if response.is_null() {
4652 return;
4653 }
4654 unsafe {
4655 if !(*response).id.is_null() {
4656 let _ = CString::from_raw((*response).id as *mut c_char);
4657 }
4658 if !(*response).operation.is_null() {
4659 let _ = CString::from_raw((*response).operation as *mut c_char);
4660 }
4661 if !(*response).document.is_null() {
4662 let _ = CString::from_raw((*response).document as *mut c_char);
4663 }
4664 let _ = Box::from_raw(response);
4665 }
4666}
4667
4668type WatchEventCallback = extern "C" fn(*mut WatchEventWrapper);
4669type WatchCallback = extern "C" fn(wrapper: *mut WatchResponseWrapper);
4670#[no_mangle]
4671#[tracing::instrument(skip_all)]
4672pub extern "C" fn watch_async_async(
4673 client: *mut ClientWrapper,
4674 options: *mut WatchRequestWrapper,
4675 callback: WatchCallback,
4676 event_callback: WatchEventCallback,
4678 ) {
4680 debug!("watch_async_async");
4681 let options = match safe_wrapper(options) {
4682 Some(options) => options,
4683 None => {
4684 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4685 let response = WatchResponseWrapper {
4686 success: false,
4687 watchid: std::ptr::null(),
4688 error: error_msg,
4689 request_id: 0,
4690 };
4691 return callback(Box::into_raw(Box::new(response)));
4692 }
4693 };
4694 let client_wrapper = match safe_wrapper(client) {
4695 Some(client) => client,
4696 None => {
4697 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4698 let response = WatchResponseWrapper {
4699 success: false,
4700 watchid: std::ptr::null(),
4701 error: error_msg,
4702 request_id: options.request_id,
4703 };
4704 return callback(Box::into_raw(Box::new(response)));
4705 }
4706 };
4707 let client = client_wrapper.client.clone();
4708 let paths = c_char_to_str(options.paths);
4709 let paths = paths.split(",").map(|s| s.to_string()).collect();
4710 let request = WatchRequest {
4711 collectionname: c_char_to_str(options.collectionname),
4712 paths,
4713 };
4714 if client.is_none() {
4715 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4716 let response = WatchResponseWrapper {
4717 success: false,
4718 watchid: std::ptr::null(),
4719 error: error_msg,
4720 request_id: options.request_id,
4721 };
4722 return callback(Box::into_raw(Box::new(response)));
4723 }
4724 debug!("watch_async: runtime.spawn");
4725 let client = client.unwrap();
4726 let handle = client.get_runtime_handle();
4727 let request_id = options.request_id;
4728 handle.spawn(async move {
4729 debug!("watch_async: call client.watch");
4730 let result = client
4731 .watch(
4732 request,
4733 openiap_client::EnvConfig::new(),
4734 Box::new(move |_event: WatchEvent| {
4735 debug!("watch_async: spawn new task, to call event_callback");
4736 trace!("watch_async: call event_callback");
4737 let id = CString::new(_event.id).unwrap().into_raw();
4738 let operation = CString::new(_event.operation).unwrap().into_raw();
4739 let document = CString::new(_event.document).unwrap().into_raw();
4740 let event = Box::into_raw(Box::new(WatchEventWrapper {
4741 id,
4742 operation,
4743 document,
4744 request_id
4745 }));
4746
4747 event_callback(event);
4748 }),
4749 )
4750 .await;
4751
4752 let response = match result {
4753 Ok(data) => {
4754 let watchid = CString::new(data).unwrap().into_raw();
4755 WatchResponseWrapper {
4756 success: true,
4757 watchid,
4758 error: std::ptr::null(),
4759 request_id,
4760 }
4761 }
4762 Err(e) => {
4763 let error_msg = CString::new(format!("Watch failed: {:?}", e))
4764 .unwrap()
4765 .into_raw();
4766 WatchResponseWrapper {
4767 success: false,
4768 watchid: std::ptr::null(),
4769 error: error_msg,
4770 request_id,
4771 }
4772 }
4773 };
4774
4775 debug!("watch_async: call callback with response");
4776 callback(Box::into_raw(Box::new(response)));
4777 });
4778}
4779
4780#[no_mangle]
4781#[tracing::instrument(skip_all)]
4782pub extern "C" fn free_watch_response(response: *mut WatchResponseWrapper) {
4783 if response.is_null() {
4784 return;
4785 }
4786 unsafe {
4787 if !(*response).error.is_null() {
4788 let _ = CString::from_raw((*response).error as *mut c_char);
4789 }
4790 if !(*response).watchid.is_null() {
4791 let _ = CString::from_raw((*response).watchid as *mut c_char);
4792 }
4793 let _ = Box::from_raw(response);
4794 }
4795}
4796
4797#[repr(C)]
4798pub struct UnWatchResponseWrapper {
4799 success: bool,
4800 error: *const c_char,
4801 request_id: i32
4802}
4803#[no_mangle]
4804#[tracing::instrument(skip_all)]
4805pub extern "C" fn unwatch(
4806 client: *mut ClientWrapper,
4807 watchid: *const c_char
4808) -> *mut UnWatchResponseWrapper {
4809 let client_wrapper = match safe_wrapper(client) {
4810 Some(client) => client,
4811 None => {
4812 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4813 let response = UnWatchResponseWrapper {
4814 success: false,
4815 error: error_msg,
4816 request_id: 0,
4817 };
4818 return Box::into_raw(Box::new(response));
4819 }
4820 };
4821 let client = client_wrapper.client.clone();
4822 let watchid = c_char_to_str(watchid);
4823 if watchid.is_empty() {
4824 let error_msg = CString::new("Watchid is required").unwrap().into_raw();
4825 let response = UnWatchResponseWrapper {
4826 success: false,
4827 error: error_msg,
4828 request_id: 0,
4829 };
4830 return Box::into_raw(Box::new(response));
4831 }
4832 if client.is_none() {
4833 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4834 let response = UnWatchResponseWrapper {
4835 success: false,
4836 error: error_msg,
4837 request_id: 0
4838 };
4839 return Box::into_raw(Box::new(response));
4840 }
4841 let client = client.unwrap();
4842 trace!("watchid: {:?}", watchid);
4843 let result = tokio::task::block_in_place(|| {
4844 let handle = client.get_runtime_handle();
4845 handle.block_on( client.unwatch(openiap_client::EnvConfig::new(), &watchid))
4846 });
4847 trace!("completed, parsing result");
4848 match result {
4849 Ok(_) => {
4850 let response = UnWatchResponseWrapper {
4851 success: true,
4852 error: std::ptr::null(),
4853 request_id: 0
4854 };
4855 debug!("Unwatch success");
4856 Box::into_raw(Box::new(response))
4857 }
4858 Err(e) => {
4859 let error_msg = CString::new(format!("Unwatch failed: {:?}", e))
4860 .unwrap()
4861 .into_raw();
4862 debug!("Unwatch failed: {:?}", error_msg);
4863 let response = UnWatchResponseWrapper {
4864 success: false,
4865 error: error_msg,
4866 request_id: 0
4867 };
4868 Box::into_raw(Box::new(response))
4869 }
4870 }
4871}
4872#[no_mangle]
4873#[tracing::instrument(skip_all)]
4874pub extern "C" fn unwatch_async(
4875 client: *mut ClientWrapper,
4876 watchid: *const c_char,
4877 request_id: i32,
4878 callback: extern "C" fn(*mut UnWatchResponseWrapper),
4879) {
4880 let client_wrapper = match safe_wrapper(client) {
4881 Some(client) => client,
4882 None => {
4883 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4884 let response = UnWatchResponseWrapper {
4885 success: false,
4886 error: error_msg,
4887 request_id,
4888 };
4889 return callback(Box::into_raw(Box::new(response)));
4890 }
4891 };
4892 let client = client_wrapper.client.clone();
4893 let watchid = c_char_to_str(watchid);
4894 if client.is_none() {
4895 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4896 let response = UnWatchResponseWrapper {
4897 success: false,
4898 error: error_msg,
4899 request_id,
4900 };
4901 return callback(Box::into_raw(Box::new(response)));
4902 }
4903 let client = client.unwrap();
4904 let handle = client.get_runtime_handle();
4905 handle.spawn(async move {
4906 let result = client.unwatch(openiap_client::EnvConfig::new(), &watchid).await;
4907 match result {
4908 Ok(_) => {
4909 let response = UnWatchResponseWrapper {
4910 success: true,
4911 error: std::ptr::null(),
4912 request_id,
4913 };
4914 callback(Box::into_raw(Box::new(response)));
4915 }
4916 Err(e) => {
4917 let error_msg = CString::new(format!("Unwatch failed: {:?}", e))
4918 .unwrap()
4919 .into_raw();
4920 let response = UnWatchResponseWrapper {
4921 success: false,
4922 error: error_msg,
4923 request_id,
4924 };
4925 callback(Box::into_raw(Box::new(response)));
4926 }
4927 }
4928 });
4929}
4930#[no_mangle]
4931#[tracing::instrument(skip_all)]
4932pub extern "C" fn free_unwatch_response(response: *mut UnWatchResponseWrapper) {
4933 if response.is_null() {
4934 return;
4935 }
4936 unsafe {
4937 if !(*response).error.is_null() {
4938 let _ = CString::from_raw((*response).error as *mut c_char);
4939 }
4940 let _ = Box::from_raw(response);
4941 }
4942}
4943
4944
4945#[repr(C)]
4946pub struct RegisterQueueRequestWrapper {
4947 queuename: *const c_char,
4948 request_id: i32
4949}
4950#[repr(C)]
4951pub struct RegisterQueueResponseWrapper {
4952 success: bool,
4953 queuename: *const c_char,
4954 error: *const c_char,
4955 request_id: i32
4956}
4957
4958#[no_mangle]
4959#[tracing::instrument(skip_all)]
4960pub extern "C" fn register_queue(
4961 client: *mut ClientWrapper,
4962 options: *mut RegisterQueueRequestWrapper,
4963) -> *mut RegisterQueueResponseWrapper {
4964 let options = match safe_wrapper(options) {
4965 Some(options) => options,
4966 None => {
4967 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4968 let response = RegisterQueueResponseWrapper {
4969 success: false,
4970 queuename: std::ptr::null(),
4971 error: error_msg,
4972 request_id: 0,
4973 };
4974 return Box::into_raw(Box::new(response));
4975 }
4976 };
4977 let client_wrapper = match safe_wrapper(client) {
4978 Some(client) => client,
4979 None => {
4980 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4981 let response = RegisterQueueResponseWrapper {
4982 success: false,
4983 queuename: std::ptr::null(),
4984 error: error_msg,
4985 request_id: options.request_id,
4986 };
4987 return Box::into_raw(Box::new(response));
4988 }
4989 };
4990 let client = client_wrapper.client.clone();
4991 let request = RegisterQueueRequest {
4993 queuename: c_char_to_str(options.queuename),
4994 };
4995 if client.is_none() {
4996 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4997 let response = RegisterQueueResponseWrapper {
4998 success: false,
4999 queuename: std::ptr::null(),
5000 error: error_msg,
5001 request_id: options.request_id,
5002 };
5003 return Box::into_raw(Box::new(response));
5004 }
5005 let client = client.unwrap();
5006 let result = tokio::task::block_in_place(|| {
5007 let handle = client.get_runtime_handle();
5008 handle.block_on(
5009 client
5010 .register_queue(
5011 request,
5012 openiap_client::EnvConfig::new(),
5013 std::sync::Arc::new(move |_client, event: QueueEvent| {
5014 trace!("queue: event: {:?}", event);
5015 let queuename = CString::new(event.queuename.clone())
5016 .unwrap()
5017 .into_string()
5018 .unwrap();
5019 let mut e = QUEUE_EVENTS.lock().unwrap();
5020 let queue = e.get_mut(&queuename);
5021 match queue {
5022 Some(q) => {
5023 q.push_back(event);
5024 }
5025 None => {
5026 let mut q = std::collections::VecDeque::new();
5027 q.push_back(event);
5028 e.insert(queuename, q);
5029 }
5030 }
5031 Box::pin(async { None })
5032 }),
5033 )
5034 )
5035 });
5036
5037 let response = match result {
5038 Ok(data) => {
5039 let id = String::from(&data);
5040 let mut events = QUEUE_EVENTS.lock().unwrap();
5041 let queue = events.get_mut(&id);
5042 if queue.is_none() {
5043 let q = std::collections::VecDeque::new();
5044 let k = String::from(&data);
5045 events.insert(k, q);
5046 }
5047 let queuename = CString::new(id).unwrap().into_raw();
5048 RegisterQueueResponseWrapper {
5049 success: true,
5050 queuename,
5051 error: std::ptr::null(),
5052 request_id: options.request_id,
5053 }
5054 }
5055 Err(e) => {
5056 let error_msg = CString::new(format!("queue failed: {:?}", e))
5057 .unwrap()
5058 .into_raw();
5059 RegisterQueueResponseWrapper {
5060 success: false,
5061 queuename: std::ptr::null(),
5062 error: error_msg,
5063 request_id: options.request_id,
5064 }
5065 }
5066 };
5067 Box::into_raw(Box::new(response))
5068}
5069
5070type QueueEventCallback = extern "C" fn(*mut QueueEventWrapper) -> *const c_char;
5071#[no_mangle]
5072#[tracing::instrument(skip_all)]
5073pub extern "C" fn register_queue_async(
5074 client: *mut ClientWrapper,
5075 options: *mut RegisterQueueRequestWrapper,
5076 event_callback: QueueEventCallback,
5077) -> *mut RegisterQueueResponseWrapper {
5078 debug!("register_queue_async");
5079 let options = match safe_wrapper(options) {
5080 Some(options) => options,
5081 None => {
5082 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5083 let response = RegisterQueueResponseWrapper {
5084 success: false,
5085 queuename: std::ptr::null(),
5086 error: error_msg,
5087 request_id: 0,
5088 };
5089 return Box::into_raw(Box::new(response))
5090 }
5091 };
5092 let client_wrapper = match safe_wrapper(client) {
5093 Some(client) => client,
5094 None => {
5095 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5096 let response = RegisterQueueResponseWrapper {
5097 success: false,
5098 queuename: std::ptr::null(),
5099 error: error_msg,
5100 request_id: options.request_id,
5101 };
5102 return Box::into_raw(Box::new(response))
5103 }
5104 };
5105 let client = client_wrapper.client.clone();
5106 let request = RegisterQueueRequest {
5107 queuename: c_char_to_str(options.queuename),
5108 };
5109 if client.is_none() {
5110 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5111 let response = RegisterQueueResponseWrapper {
5112 success: false,
5113 queuename: std::ptr::null(),
5114 error: error_msg,
5115 request_id: options.request_id,
5116 };
5117 return Box::into_raw(Box::new(response))
5118 }
5119 let client = client.unwrap();
5120 debug!("register_queue_async: runtime.spawn");
5121 let request_id = options.request_id;
5122 let result = tokio::task::block_in_place(|| {
5123 let handle = client.get_runtime_handle();
5124 handle.block_on(
5125 client
5126 .register_queue(
5127 request,
5128 openiap_client::EnvConfig::new(),
5129 std::sync::Arc::new(move |_client, event: QueueEvent| {
5130 debug!("register_queue_async: spawn new task, to call event_callback");
5131 trace!("register_queue_async: call event_callback");
5132 let queuename = CString::new(event.queuename).unwrap().into_raw();
5133 let correlation_id = CString::new(event.correlation_id).unwrap().into_raw();
5134 let replyto = CString::new(event.replyto).unwrap().into_raw();
5135 let routingkey = CString::new(event.routingkey).unwrap().into_raw();
5136 let exchangename = CString::new(event.exchangename).unwrap().into_raw();
5137 let data = CString::new(event.data).unwrap().into_raw();
5138 let event = Box::new(QueueEventWrapper {
5139 queuename,
5140 correlation_id,
5141 replyto,
5142 routingkey,
5143 exchangename,
5144 data,
5145 request_id
5146 });
5147 let result = event_callback(Box::into_raw(event));
5148 let result = c_char_to_str(result);
5149 if result.is_empty() {
5150 return Box::pin(async { None })
5151 }
5152 let result = result.to_string();
5153 Box::pin(async { Some(result) })
5154 }),
5155 )
5156 )
5157 });
5158
5159 debug!("register_queue_async: parse result");
5160 let response = match result {
5161 Ok(data) => {
5162 let queuename = CString::new(data).unwrap().into_raw();
5163 RegisterQueueResponseWrapper {
5164 success: true,
5165 queuename,
5166 error: std::ptr::null(),
5167 request_id: options.request_id,
5168 }
5169 }
5170 Err(e) => {
5171 let error_msg = CString::new(format!("RegisterQueue failed: {:?}", e))
5172 .unwrap()
5173 .into_raw();
5174 RegisterQueueResponseWrapper {
5175 success: false,
5176 queuename: std::ptr::null(),
5177 error: error_msg,
5178 request_id: options.request_id,
5179 }
5180 }
5181 };
5182
5183 Box::into_raw(Box::new(response))
5184}
5185
5186
5187
5188#[no_mangle]
5189#[tracing::instrument(skip_all)]
5190pub extern "C" fn free_register_queue_response(response: *mut RegisterQueueResponseWrapper) {
5191 if response.is_null() {
5192 return;
5193 }
5194 unsafe {
5195 if !(*response).error.is_null() {
5196 let _ = CString::from_raw((*response).error as *mut c_char);
5197 }
5198 if !(*response).queuename.is_null() {
5199 let _ = CString::from_raw((*response).queuename as *mut c_char);
5200 }
5201 let _ = Box::from_raw(response);
5202 }
5203}
5204
5205
5206#[repr(C)]
5207pub struct RegisterExchangeRequestWrapper {
5208 exchangename: *const c_char,
5209 algorithm: *const c_char,
5210 routingkey: *const c_char,
5211 addqueue: bool,
5212 request_id: i32
5213}
5214#[repr(C)]
5215pub struct RegisterExchangeResponseWrapper {
5216 success: bool,
5217 queuename: *const c_char,
5218 error: *const c_char,
5219 request_id: i32
5220}
5221#[no_mangle]
5222#[tracing::instrument(skip_all)]
5223pub extern "C" fn register_exchange (
5224 client: *mut ClientWrapper,
5225 options: *mut RegisterExchangeRequestWrapper,
5226) -> *mut RegisterExchangeResponseWrapper {
5227 let options = match safe_wrapper(options) {
5228 Some(options) => options,
5229 None => {
5230 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5231 let response = RegisterExchangeResponseWrapper {
5232 success: false,
5233 queuename: std::ptr::null(),
5234 error: error_msg,
5235 request_id: 0,
5236 };
5237 return Box::into_raw(Box::new(response));
5238 }
5239 };
5240 let client_wrapper = match safe_wrapper(client) {
5241 Some(client) => client,
5242 None => {
5243 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5244 let response = RegisterExchangeResponseWrapper {
5245 success: false,
5246 queuename: std::ptr::null(),
5247 error: error_msg,
5248 request_id: options.request_id,
5249 };
5250 return Box::into_raw(Box::new(response));
5251 }
5252 };
5253 let client = client_wrapper.client.clone();
5254 let request = RegisterExchangeRequest {
5255 exchangename: c_char_to_str(options.exchangename),
5256 algorithm: c_char_to_str(options.algorithm),
5257 routingkey: c_char_to_str(options.routingkey),
5258 addqueue: options.addqueue,
5259 };
5260 if client.is_none() {
5261 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5262 let response = RegisterExchangeResponseWrapper {
5263 success: false,
5264 queuename: std::ptr::null(),
5265 error: error_msg,
5266 request_id: options.request_id,
5267 };
5268 return Box::into_raw(Box::new(response));
5269 }
5270 let client = client.unwrap();
5271 let result = tokio::task::block_in_place(|| {
5272 let handle = client.get_runtime_handle();
5273 handle.block_on(
5274 client
5275 .register_exchange(request,
5276 openiap_client::EnvConfig::new(),
5277 std::sync::Arc::new(move |_client, event: QueueEvent| {
5278 trace!("exchange: event: {:?}", event);
5279 let queuename = CString::new(event.queuename.clone())
5280 .unwrap()
5281 .into_string()
5282 .unwrap();
5283 let mut e = QUEUE_EVENTS.lock().unwrap();
5284 let queue = e.get_mut(&queuename);
5285 match queue {
5286 Some(q) => {
5287 q.push_back(event);
5288 }
5289 None => {
5290 let mut q = std::collections::VecDeque::new();
5291 q.push_back(event);
5292 e.insert(queuename, q);
5293 }
5294 }
5295 Box::pin(async { None })
5296 }),
5297
5298 )
5299 )
5300 });
5301
5302 let response = match result {
5303 Ok(data) => {
5304 let queuename = CString::new(data).unwrap().into_raw();
5305 RegisterExchangeResponseWrapper {
5306 success: true,
5307 queuename,
5308 error: std::ptr::null(),
5309 request_id: options.request_id,
5310 }
5311 }
5312 Err(e) => {
5313 let error_msg = CString::new(format!("RegisterExchange failed: {:?}", e))
5314 .unwrap()
5315 .into_raw();
5316 RegisterExchangeResponseWrapper {
5317 success: false,
5318 queuename: std::ptr::null(),
5319 error: error_msg,
5320 request_id: options.request_id,
5321 }
5322 }
5323 };
5324
5325 Box::into_raw(Box::new(response))
5326}
5327type ExchangeEventCallback = extern "C" fn(*mut QueueEventWrapper);
5328#[no_mangle]
5329#[tracing::instrument(skip_all)]
5330pub extern "C" fn register_exchange_async(
5331 client: *mut ClientWrapper,
5332 options: *mut RegisterExchangeRequestWrapper,
5333 event_callback: ExchangeEventCallback,
5334) -> *mut RegisterExchangeResponseWrapper {
5335 debug!("register_exchange_async");
5336 let options = match safe_wrapper(options) {
5337 Some(options) => options,
5338 None => {
5339 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5340 let response = RegisterExchangeResponseWrapper {
5341 success: false,
5342 queuename: std::ptr::null(),
5343 error: error_msg,
5344 request_id: 0,
5345 };
5346 return Box::into_raw(Box::new(response))
5347 }
5348 };
5349 let client_wrapper = match safe_wrapper(client) {
5350 Some(client) => client,
5351 None => {
5352 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5353 let response = RegisterExchangeResponseWrapper {
5354 success: false,
5355 queuename: std::ptr::null(),
5356 error: error_msg,
5357 request_id: options.request_id,
5358 };
5359 return Box::into_raw(Box::new(response))
5360 }
5361 };
5362 let client = client_wrapper.client.clone();
5363 let request = RegisterExchangeRequest {
5364 exchangename: c_char_to_str(options.exchangename),
5365 algorithm: c_char_to_str(options.algorithm),
5366 routingkey: c_char_to_str(options.routingkey),
5367 addqueue: options.addqueue,
5368 };
5369 if client.is_none() {
5370 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5371 let response = RegisterExchangeResponseWrapper {
5372 success: false,
5373 queuename: std::ptr::null(),
5374 error: error_msg,
5375 request_id: options.request_id,
5376 };
5377 return Box::into_raw(Box::new(response))
5378 }
5379 let client = client.unwrap();
5380 debug!("register_exchange_async: runtime.spawn");
5381 let request_id = options.request_id;
5382 let result = tokio::task::block_in_place(|| {
5383 let handle = client.get_runtime_handle();
5384 handle.block_on(
5385 client
5386 .register_exchange(request,
5387 openiap_client::EnvConfig::new(),
5388 std::sync::Arc::new(move |_client, event: QueueEvent| {
5389 debug!("register_exchange_async: spawn new task, to call event_callback");
5390 trace!("register_exchange_async: call event_callback");
5391 let queuename = CString::new(event.queuename).unwrap().into_raw();
5392 let correlation_id = CString::new(event.correlation_id).unwrap().into_raw();
5393 let replyto = CString::new(event.replyto).unwrap().into_raw();
5394 let routingkey = CString::new(event.routingkey).unwrap().into_raw();
5395 let exchangename = CString::new(event.exchangename).unwrap().into_raw();
5396 let data = CString::new(event.data).unwrap().into_raw();
5397 let event = Box::new(QueueEventWrapper {
5398 queuename,
5399 correlation_id,
5400 replyto,
5401 routingkey,
5402 exchangename,
5403 data,
5404 request_id
5405 });
5406 event_callback(Box::into_raw(event));
5407 Box::pin(async { None })
5408 }),
5409
5410 )
5411 )
5412 });
5413
5414 debug!("register_exchange_async: parse result");
5415 let response = match result {
5416 Ok(data) => {
5417 let queuename = CString::new(data).unwrap().into_raw();
5418 RegisterExchangeResponseWrapper {
5419 success: true,
5420 queuename,
5421 error: std::ptr::null(),
5422 request_id: options.request_id,
5423 }
5424 }
5425 Err(e) => {
5426 let error_msg = CString::new(format!("RegisterExchange failed: {:?}", e))
5427 .unwrap()
5428 .into_raw();
5429 RegisterExchangeResponseWrapper {
5430 success: false,
5431 queuename: std::ptr::null(),
5432 error: error_msg,
5433 request_id: options.request_id,
5434 }
5435 }
5436 };
5437 Box::into_raw(Box::new(response))
5438}
5439
5440#[no_mangle]
5441#[tracing::instrument(skip_all)]
5442pub extern "C" fn free_register_exchange_response(response: *mut RegisterExchangeResponseWrapper) {
5443 if response.is_null() {
5444 return;
5445 }
5446 unsafe {
5447 if !(*response).error.is_null() {
5448 let _ = CString::from_raw((*response).error as *mut c_char);
5449 }
5450 if !(*response).queuename.is_null() {
5451 let _ = CString::from_raw((*response).queuename as *mut c_char);
5452 }
5453 let _ = Box::from_raw(response);
5454 }
5455}
5456
5457#[repr(C)]
5458#[derive(Debug, Clone)]
5459pub struct QueueEventWrapper {
5460 queuename: *const c_char,
5461 correlation_id: *const c_char,
5462 replyto: *const c_char,
5463 routingkey: *const c_char,
5464 exchangename: *const c_char,
5465 data: *const c_char,
5466 request_id: i32,
5467}
5468impl Default for QueueEventWrapper {
5469 fn default() -> Self {
5470 QueueEventWrapper {
5471 queuename: std::ptr::null(),
5472 correlation_id: std::ptr::null(),
5473 replyto: std::ptr::null(),
5474 routingkey: std::ptr::null(),
5475 exchangename: std::ptr::null(),
5476 data: std::ptr::null(),
5477 request_id: 0,
5478 }
5479 }
5480}
5481
5482#[no_mangle]
5483#[tracing::instrument(skip_all)]
5484pub extern "C" fn next_queue_event (
5485 queuename: *const c_char,
5486) -> *mut QueueEventWrapper {
5487 trace!("unwrap watchid");
5488 let queuename = c_char_to_str(queuename);
5489 trace!("queuename {:}", queuename);
5490 let queuename = queuename.to_string();
5491 trace!("unwrap events");
5492 let mut e = QUEUE_EVENTS.lock().unwrap();
5493 trace!("get queue");
5494 let queue = e.get_mut(&queuename);
5495 match queue {
5496 Some(q) => {
5497 match q.pop_front() {
5498 Some(event) => {
5499 debug!("got event");
5500 let queuename = CString::new(event.queuename).unwrap().into_raw();
5501 let correlation_id = CString::new(event.correlation_id).unwrap().into_raw();
5502 let replyto = CString::new(event.replyto).unwrap().into_raw();
5503 let routingkey = CString::new(event.routingkey).unwrap().into_raw();
5504 let exchangename = CString::new(event.exchangename).unwrap().into_raw();
5505 let data = CString::new(event.data).unwrap().into_raw();
5506 let event = Box::new(QueueEventWrapper {
5507 queuename,
5508 correlation_id,
5509 replyto,
5510 routingkey,
5511 exchangename,
5512 data,
5513 request_id: 0
5514 });
5515 Box::into_raw(event)
5516 }
5517 None => {
5518 trace!("No event");
5519 Box::into_raw(Box::new(QueueEventWrapper::default()))
5520 },
5521 }
5522 },
5523 None => {
5524 debug!("Queue for {:} not found", queuename);
5525 Box::into_raw(Box::new(QueueEventWrapper::default()))
5526 },
5527 }
5528}
5529#[no_mangle]
5530#[tracing::instrument(skip_all)]
5531pub extern "C" fn free_queue_event(response: *mut QueueEventWrapper) {
5532 if response.is_null() {
5533 return;
5534 }
5535 unsafe {
5536 if !(*response).queuename.is_null() {
5537 let _ = CString::from_raw((*response).queuename as *mut c_char);
5538 }
5539 if !(*response).correlation_id.is_null() {
5540 let _ = CString::from_raw((*response).correlation_id as *mut c_char);
5541 }
5542 if !(*response).replyto.is_null() {
5543 let _ = CString::from_raw((*response).replyto as *mut c_char);
5544 }
5545 if !(*response).routingkey.is_null() {
5546 let _ = CString::from_raw((*response).routingkey as *mut c_char);
5547 }
5548 if !(*response).exchangename.is_null() {
5549 let _ = CString::from_raw((*response).exchangename as *mut c_char);
5550 }
5551 if !(*response).data.is_null() {
5552 let _ = CString::from_raw((*response).data as *mut c_char);
5553 }
5554 let _ = Box::from_raw(response);
5555 }
5556}
5557
5558#[repr(C)]
5559pub struct QueueMessageRequestWrapper {
5560 queuename: *const c_char,
5561 correlation_id: *const c_char,
5562 replyto: *const c_char,
5563 routingkey: *const c_char,
5564 exchangename: *const c_char,
5565 data: *const c_char,
5566 striptoken: bool,
5567 expiration: i32,
5568 request_id: i32,
5569}
5570#[repr(C)]
5571pub struct QueueMessageResponseWrapper {
5572 success: bool,
5573 error: *const c_char,
5574}
5575#[no_mangle]
5576#[tracing::instrument(skip_all)]
5577pub extern "C" fn queue_message(
5578 client: *mut ClientWrapper,
5579 options: *mut QueueMessageRequestWrapper,
5580) -> *mut QueueMessageResponseWrapper {
5581 let options = match safe_wrapper(options) {
5582 Some(options) => options,
5583 None => {
5584 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5585 let response = QueueMessageResponseWrapper {
5586 success: false,
5587 error: error_msg,
5588 };
5589 return Box::into_raw(Box::new(response));
5590 }
5591 };
5592 let client_wrapper = match safe_wrapper(client) {
5593 Some(client) => client,
5594 None => {
5595 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5596 let response = QueueMessageResponseWrapper {
5597 success: false,
5598 error: error_msg,
5599 };
5600 return Box::into_raw(Box::new(response));
5601 }
5602 };
5603 let client = client_wrapper.client.clone();
5604 let request = QueueMessageRequest {
5605 queuename: c_char_to_str(options.queuename),
5606 correlation_id: c_char_to_str(options.correlation_id),
5607 replyto: c_char_to_str(options.replyto),
5608 routingkey: c_char_to_str(options.routingkey),
5609 exchangename: c_char_to_str(options.exchangename),
5610 data: c_char_to_str(options.data),
5611 striptoken: options.striptoken,
5612 expiration: options.expiration,
5613 };
5614 if client.is_none() {
5615 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5616 let response = QueueMessageResponseWrapper {
5617 success: false,
5618 error: error_msg,
5619 };
5620 return Box::into_raw(Box::new(response));
5621 }
5622 let client = client.unwrap();
5623 let result = tokio::task::block_in_place(|| {
5624 let handle = client.get_runtime_handle();
5625 handle.block_on(
5626 client
5627 .queue_message(request, openiap_client::EnvConfig::new())
5628 )
5629 });
5630 match result {
5631 Ok(_) => {
5632 let response = QueueMessageResponseWrapper {
5633 success: true,
5634 error: std::ptr::null(),
5635 };
5636 Box::into_raw(Box::new(response))
5637 }
5638 Err(e) => {
5639 let error_msg = CString::new(format!("Queue message failed: {:?}", e))
5640 .unwrap()
5641 .into_raw();
5642 let response = QueueMessageResponseWrapper {
5643 success: false,
5644 error: error_msg,
5645 };
5646 Box::into_raw(Box::new(response))
5647 }
5648 }
5649}
5650#[no_mangle]
5651#[tracing::instrument(skip_all)]
5652pub extern "C" fn free_queue_message_response(response: *mut QueueMessageResponseWrapper) {
5653 if response.is_null() {
5654 return;
5655 }
5656 unsafe {
5657 if !(*response).error.is_null() {
5658 let _ = CString::from_raw((*response).error as *mut c_char);
5659 }
5660 let _ = Box::from_raw(response);
5661 }
5662}
5663
5664#[repr(C)]
5665pub struct UnRegisterQueueResponseWrapper {
5666 success: bool,
5667 error: *const c_char,
5668}
5669#[no_mangle]
5670#[tracing::instrument(skip_all)]
5671pub extern "C" fn unregister_queue(
5672 client: *mut ClientWrapper,
5673 queuename: *const c_char,
5674) -> *mut UnRegisterQueueResponseWrapper {
5675 let client_wrapper = match safe_wrapper(client) {
5676 Some(client) => client,
5677 None => {
5678 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5679 let response = UnRegisterQueueResponseWrapper {
5680 success: false,
5681 error: error_msg,
5682 };
5683 return Box::into_raw(Box::new(response));
5684 }
5685 };
5686 let client = client_wrapper.client.clone();
5687 let queuename = c_char_to_str(queuename);
5688 if client.is_none() {
5689 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5690 let response = UnRegisterQueueResponseWrapper {
5691 success: false,
5692 error: error_msg,
5693 };
5694 return Box::into_raw(Box::new(response));
5695 }
5696 let client = client.unwrap();
5697 let result = tokio::task::block_in_place(|| {
5698 let handle = client.get_runtime_handle();
5699 handle.block_on( client.unregister_queue(openiap_client::EnvConfig::new(), &queuename))
5700 });
5701 match result {
5702 Ok(_) => {
5703 let response = UnRegisterQueueResponseWrapper {
5704 success: true,
5705 error: std::ptr::null(),
5706 };
5707 Box::into_raw(Box::new(response))
5708 }
5709 Err(e) => {
5710 let error_msg = CString::new(format!("Unregister queue failed: {:?}", e))
5711 .unwrap()
5712 .into_raw();
5713 let response = UnRegisterQueueResponseWrapper {
5714 success: false,
5715 error: error_msg,
5716 };
5717 Box::into_raw(Box::new(response))
5718 }
5719 }
5720}
5721#[no_mangle]
5722#[tracing::instrument(skip_all)]
5723pub extern "C" fn free_unregister_queue_response(response: *mut UnRegisterQueueResponseWrapper) {
5724 if response.is_null() {
5725 return;
5726 }
5727 unsafe {
5728 if !(*response).error.is_null() {
5729 let _ = CString::from_raw((*response).error as *mut c_char);
5730 }
5731 let _ = Box::from_raw(response);
5732 }
5733}
5734
5735
5736
5737#[repr(C)]
5738#[derive(Debug, Clone)]
5739pub struct WorkitemFileWrapper {
5740 filename: *const c_char,
5741 id: *const c_char,
5742 compressed: bool,
5743 }
5745impl WorkitemFileWrapper {
5746 pub fn new(filename: &str, id: &str, compressed: bool) -> Self {
5747 trace!("filename: {:?}", filename);
5748 let filename = CString::new(filename).unwrap().into_raw();
5749 trace!("filename: {:?}", filename);
5750 trace!("id: {:?}", id);
5751 let id = CString::new(id).unwrap().into_raw();
5752 trace!("id: {:?}", id);
5753 WorkitemFileWrapper {
5755 filename,
5756 id,
5757 compressed,
5759 }
5760 }
5769}
5770
5771#[repr(C)]
5772#[derive(Debug, Clone)]
5773pub struct WorkitemWrapper {
5774 id: *const c_char,
5775 name: *const c_char,
5776 payload: *const c_char,
5777 priority: i32,
5778 nextrun: u64,
5779 lastrun: u64,
5780 files: *const *const WorkitemFileWrapper,
5781 files_len: i32,
5782 state: *const c_char,
5783 wiq: *const c_char,
5784 wiqid: *const c_char,
5785 retries: i32,
5786 username: *const c_char,
5787 success_wiqid: *const c_char,
5788 failed_wiqid: *const c_char,
5789 success_wiq: *const c_char,
5790 failed_wiq: *const c_char,
5791 errormessage: *const c_char,
5792 errorsource: *const c_char,
5793 errortype: *const c_char,
5794}
5795impl WorkitemWrapper {
5796 #[tracing::instrument(skip_all)]
5797 pub fn as_workitem(&self) -> Workitem {
5798 let files_len = self.files_len;
5799 let mut files: Vec<WorkitemFile> = vec![];
5800 if files_len > 0 {
5801 let _files = unsafe { &*self.files };
5802 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
5803 files = _files.iter().map(|f| {
5804 let file = unsafe { &**f };
5805 WorkitemFile {
5806 filename: c_char_to_str(file.filename),
5807 id: c_char_to_str(file.id),
5808 ..Default::default()
5809 }
5812 }).collect();
5813 }
5814 trace!("nextrun: {:?}", self.nextrun);
5815 let mut nextrun = Some(Timestamp::from(
5817 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(self.nextrun)
5818 ));
5819 trace!("nextrun: {:?}", nextrun);
5820 if self.nextrun == 0 {
5821 nextrun = None;
5822 }
5823 trace!("lastrun: {:?}", self.lastrun);
5824 let mut lastrun = Some(Timestamp::from(
5826 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(self.lastrun)
5827 ));
5828 trace!("lastrun: {:?}", lastrun);
5829 if self.lastrun == 0 {
5830 lastrun = None;
5831 }
5832 Workitem {
5833 id: c_char_to_str(self.id),
5834 name: c_char_to_str(self.name),
5835 payload: c_char_to_str(self.payload),
5836 priority: self.priority,
5837 nextrun,
5838 lastrun,
5839 files,
5840 state: c_char_to_str(self.state),
5841 wiq: c_char_to_str(self.wiq),
5842 wiqid: c_char_to_str(self.wiqid),
5843 retries: self.retries,
5844 username: c_char_to_str(self.username),
5845 success_wiqid: c_char_to_str(self.success_wiqid),
5846 failed_wiqid: c_char_to_str(self.failed_wiqid),
5847 success_wiq: c_char_to_str(self.success_wiq),
5848 failed_wiq: c_char_to_str(self.failed_wiq),
5849 errormessage: c_char_to_str(self.errormessage),
5850 errorsource: c_char_to_str(self.errorsource),
5851 errortype: c_char_to_str(self.errortype),
5852 }
5853 }
5854}
5855#[tracing::instrument(skip_all)]
5856pub fn wrap_workitem(workitem: Workitem ) -> WorkitemWrapper {
5857 trace!("parse workitem: {:?}", workitem);
5858 let id = CString::new(workitem.id).unwrap().into_raw();
5859 let name = CString::new(workitem.name).unwrap().into_raw();
5860 let payload = CString::new(workitem.payload).unwrap().into_raw();
5861 let state = CString::new(workitem.state).unwrap().into_raw();
5862 let wiq = CString::new(workitem.wiq).unwrap().into_raw();
5863 let wiqid = CString::new(workitem.wiqid).unwrap().into_raw();
5864 let username = CString::new(workitem.username).unwrap().into_raw();
5865 let success_wiqid = CString::new(workitem.success_wiqid).unwrap().into_raw();
5866 let failed_wiqid = CString::new(workitem.failed_wiqid).unwrap().into_raw();
5867 let success_wiq = CString::new(workitem.success_wiq).unwrap().into_raw();
5868 let failed_wiq = CString::new(workitem.failed_wiq).unwrap().into_raw();
5869 let errormessage = CString::new(workitem.errormessage).unwrap().into_raw();
5870 let errorsource = CString::new(workitem.errorsource).unwrap().into_raw();
5871 let errortype = CString::new(workitem.errortype).unwrap().into_raw();
5872 let mut files: Vec<*const WorkitemFileWrapper> = vec![];
5873 for f in &workitem.files {
5874 let file = Box::into_raw(Box::new(WorkitemFileWrapper::new(&f.filename, &f.id, f.compressed)));
5886 files.push(file);
5887 }
5888 trace!("files: {:?} at {:?}", files.len(), files);
5889 trace!("read nextrun");
5890 let nextrun = workitem.nextrun.map(|t| t.seconds as u64).unwrap_or(0);
5891 trace!("nextrun: {:?}", nextrun);
5892 let lastrun = workitem.lastrun.map(|t| t.seconds as u64).unwrap_or(0);
5893 trace!("lastrun: {:?}", lastrun);
5894 let _files = files.as_ptr();
5895 trace!("files: {:?}", files);
5896 let files_len = workitem.files.len() as i32;
5897 trace!("files_len: {:?}", files_len);
5898 let workitem = WorkitemWrapper {
5899 id,
5900 name,
5901 payload,
5902 priority: workitem.priority,
5903 nextrun,
5904 lastrun,
5905 files: _files,
5906 files_len,
5907 state,
5908 wiq,
5909 wiqid,
5910 retries: workitem.retries,
5911 username,
5912 success_wiqid,
5913 failed_wiqid,
5914 success_wiq,
5915 failed_wiq,
5916 errormessage,
5917 errorsource,
5918 errortype,
5919 };
5920 trace!("forget files");
5921 std::mem::forget(files);
5922 trace!("return workitem");
5923 workitem
5924}
5925#[repr(C)]
5926#[derive(Debug, Clone)]
5927pub struct PushWorkitemRequestWrapper {
5928 wiq: *const c_char,
5929 wiqid: *const c_char,
5930 name: *const c_char,
5931 payload: *const c_char,
5932 nextrun: u64,
5933 success_wiqid: *const c_char,
5934 failed_wiqid: *const c_char,
5935 success_wiq: *const c_char,
5936 failed_wiq: *const c_char,
5937 priority: i32,
5938 files: *const *const WorkitemFileWrapper,
5939 files_len: i32,
5940 request_id: i32
5941}
5942#[repr(C)]
5943#[derive(Debug, Clone)]
5944pub struct PushWorkitemResponseWrapper {
5945 success: bool,
5946 error: *const c_char,
5947 workitem: *const WorkitemWrapper,
5948 request_id: i32
5949}
5950#[no_mangle]
5951#[tracing::instrument(skip_all)]
5952pub extern "C" fn push_workitem(
5953 client: *mut ClientWrapper,
5954 options: *mut PushWorkitemRequestWrapper,
5955) -> *mut PushWorkitemResponseWrapper {
5956 let options = match safe_wrapper(options) {
5957 Some(options) => options,
5958 None => {
5959 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5960 let response = PushWorkitemResponseWrapper {
5961 success: false,
5962 error: error_msg,
5963 workitem: std::ptr::null(),
5964 request_id: 0
5965 };
5966 return Box::into_raw(Box::new(response));
5967 }
5968 };
5969 let client_wrapper = match safe_wrapper(client) {
5970 Some(client) => client,
5971 None => {
5972 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5973 let response = PushWorkitemResponseWrapper {
5974 success: false,
5975 error: error_msg,
5976 workitem: std::ptr::null(),
5977 request_id: options.request_id
5978 };
5979 return Box::into_raw(Box::new(response));
5980 }
5981 };
5982 let client = client_wrapper.client.clone();
5983 let files_len = options.files_len;
5984 debug!("files_len: {:?}", files_len);
5985 let mut files: Vec<WorkitemFile> = vec![];
5986 if files_len > 0 {
5987 debug!("get files of options");
5988 let _files = unsafe { &*options.files };
5989 debug!("slice files");
5990 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
5991 debug!("loop files");
5992 files = _files.iter().map(|f| {
5993 debug!("process a file");
5994 let file = unsafe { &**f };
5995 debug!("create WorkitemFile instance");
5996 let filename = c_char_to_str(file.filename);
5997 trace!("filename: {:?}", filename);
5998 let id = c_char_to_str(file.id);
5999 trace!("id: {:?}", id);
6000 trace!("compressed: {:?}", file.compressed);
6001 WorkitemFile {
6002 filename,
6003 id,
6004 compressed: file.compressed,
6005 ..Default::default()
6006 }
6008 }).collect();
6009 }
6010 trace!("nextrun: {:?}", options.nextrun);
6011 let mut nextrun = Some(Timestamp::from(
6013 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(options.nextrun as u64)
6014 ));
6015 trace!("nextrun: {:?}", nextrun);
6016 if options.nextrun == 0 {
6017 nextrun = None;
6018 }
6019 let request = PushWorkitemRequest {
6020 wiq: c_char_to_str(options.wiq),
6021 wiqid: c_char_to_str(options.wiqid),
6022 name: c_char_to_str(options.name),
6023 payload: c_char_to_str(options.payload),
6024 nextrun,
6025 success_wiqid: c_char_to_str(options.success_wiqid),
6026 failed_wiqid: c_char_to_str(options.failed_wiqid),
6027 success_wiq: c_char_to_str(options.success_wiq),
6028 failed_wiq: c_char_to_str(options.failed_wiq),
6029 priority: options.priority,
6030 files,
6031 };
6032 if client.is_none() {
6033 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6034 let response = PushWorkitemResponseWrapper {
6035 success: false,
6036 error: error_msg,
6037 workitem: std::ptr::null(),
6038 request_id: options.request_id
6039 };
6040 return Box::into_raw(Box::new(response));
6041 }
6042 let client = client.unwrap();
6043 let result = tokio::task::block_in_place(|| {
6044 let handle = client.get_runtime_handle();
6045 handle.block_on(client
6046 .push_workitem(request, openiap_client::EnvConfig::new())
6047 )
6048 });
6049
6050 match result {
6051 Ok(resp) => {
6052 Box::into_raw(Box::new(match resp.workitem {
6053 Some(workitem) => {
6054 let workitem = wrap_workitem(workitem);
6055 PushWorkitemResponseWrapper {
6056 success: true,
6057 error: std::ptr::null(),
6058 workitem: Box::into_raw(Box::new(workitem)),
6059 request_id: options.request_id
6060 }
6061 }
6062 None => {
6063 let error_msg = CString::new("Push workitem failed: workitem not found").unwrap().into_raw();
6064 PushWorkitemResponseWrapper {
6065 success: false,
6066 error: error_msg,
6067 workitem: std::ptr::null(),
6068 request_id: options.request_id
6069 }
6070 }
6071 }))
6072 }
6073 Err(e) => {
6074 let error_msg = CString::new(format!("Push workitem failed: {:?}", e))
6075 .unwrap()
6076 .into_raw();
6077 Box::into_raw(Box::new(PushWorkitemResponseWrapper {
6078 success: false,
6079 error: error_msg,
6080 workitem: std::ptr::null(),
6081 request_id: options.request_id
6082 }))
6083 }
6084 }
6085}
6086#[no_mangle]
6087#[tracing::instrument(skip_all)]
6088pub extern "C" fn push_workitem_async(
6089 client: *mut ClientWrapper,
6090 options: *mut PushWorkitemRequestWrapper,
6091 callback: extern "C" fn(*mut PushWorkitemResponseWrapper),
6092) {
6093 let options = match safe_wrapper(options) {
6094 Some(options) => options,
6095 None => {
6096 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6097 let response = PushWorkitemResponseWrapper {
6098 success: false,
6099 error: error_msg,
6100 workitem: std::ptr::null(),
6101 request_id: 0
6102 };
6103 return callback(Box::into_raw(Box::new(response)));
6104 }
6105 };
6106 let client_wrapper = match safe_wrapper(client) {
6107 Some(client) => client,
6108 None => {
6109 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6110 let response = PushWorkitemResponseWrapper {
6111 success: false,
6112 error: error_msg,
6113 workitem: std::ptr::null(),
6114 request_id: options.request_id
6115 };
6116 return callback(Box::into_raw(Box::new(response)));
6117 }
6118 };
6119 let client = client_wrapper.client.clone();
6120 let files_len = options.files_len;
6121 debug!("files_len: {:?}", files_len);
6122 let mut files: Vec<WorkitemFile> = vec![];
6123 if files_len > 0 {
6124 debug!("get files of options");
6125 let _files = unsafe { &*options.files };
6126 debug!("slice files");
6127 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
6128 debug!("loop files");
6129 files = _files.iter().map(|f| {
6130 debug!("process a file");
6131 let file = unsafe { &**f };
6132 debug!("create WorkitemFile instance 2");
6133 let filename = c_char_to_str(file.filename);
6134 debug!("filename: {:?}", filename);
6135 let id = c_char_to_str(file.id);
6136 debug!("id: {:?}", id);
6137 let compressed = file.compressed;
6138 debug!("compressed: {:?}", compressed);
6139 WorkitemFile {
6140 filename: c_char_to_str(file.filename),
6141 id: c_char_to_str(file.id),
6142 compressed: file.compressed,
6143 ..Default::default()
6144 }
6146 }).collect();
6147 }
6148 trace!("nextrun: {:?}", options.nextrun);
6149 let mut nextrun = Some(Timestamp::from(
6151 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(options.nextrun as u64)
6152 ));
6153 trace!("nextrun: {:?}", nextrun);
6154 if options.nextrun == 0 {
6155 nextrun = None;
6156 }
6157 let request = PushWorkitemRequest {
6158 wiq: c_char_to_str(options.wiq),
6159 wiqid: c_char_to_str(options.wiqid),
6160 name: c_char_to_str(options.name),
6161 payload: c_char_to_str(options.payload),
6162 nextrun,
6163 success_wiqid: c_char_to_str(options.success_wiqid),
6164 failed_wiqid: c_char_to_str(options.failed_wiqid),
6165 success_wiq: c_char_to_str(options.success_wiq),
6166 failed_wiq: c_char_to_str(options.failed_wiq),
6167 priority: options.priority,
6168 files,
6169 };
6170 if client.is_none() {
6171 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6172 let response = PushWorkitemResponseWrapper {
6173 success: false,
6174 error: error_msg,
6175 workitem: std::ptr::null(),
6176 request_id: options.request_id
6177 };
6178 return callback(Box::into_raw(Box::new(response)));
6179 }
6180 let client = client.unwrap();
6181 let handle = client.get_runtime_handle();
6182 let request_id = options.request_id;
6183 handle.spawn(async move {
6184 let result = client
6185 .push_workitem(request, openiap_client::EnvConfig::new())
6186 .await;
6187 let response = match result {
6188 Ok(resp) => {
6189 match resp.workitem {
6190 Some(workitem) => {
6191 let workitem = wrap_workitem(workitem);
6192 PushWorkitemResponseWrapper {
6193 success: true,
6194 error: std::ptr::null(),
6195 workitem: Box::into_raw(Box::new(workitem)),
6196 request_id,
6197 }
6198 }
6199 None => {
6200 let error_msg = CString::new("Push workitem failed: workitem not found").unwrap().into_raw();
6201 PushWorkitemResponseWrapper {
6202 success: false,
6203 error: error_msg,
6204 workitem: std::ptr::null(),
6205 request_id,
6206 }
6207 }
6208 }
6209 }
6210 Err(e) => {
6211 let error_msg = CString::new(format!("Push workitem failed: {:?}", e))
6212 .unwrap()
6213 .into_raw();
6214 PushWorkitemResponseWrapper {
6215 success: false,
6216 error: error_msg,
6217 workitem: std::ptr::null(),
6218 request_id,
6219 }
6220 }
6221 };
6222 let response = Box::into_raw(Box::new(response));
6223 callback(response);
6224 });
6225
6226
6227}
6228
6229#[no_mangle]
6230#[tracing::instrument(skip_all)]
6231pub extern "C" fn free_push_workitem_response(response: *mut PushWorkitemResponseWrapper) {
6232 if response.is_null() {
6233 return;
6234 }
6235 unsafe {
6236 if !(*response).error.is_null() {
6237 let _ = CString::from_raw((*response).error as *mut c_char);
6238 }
6239 if !(*response).workitem.is_null() {
6240 free_workitem((*response).workitem as *mut WorkitemWrapper);
6241 }
6242 let _ = Box::from_raw(response);
6243 }
6244}
6245
6246#[repr(C)]
6247#[derive(Debug, Clone)]
6248pub struct PopWorkitemRequestWrapper {
6249 wiq: *const c_char,
6250 wiqid: *const c_char,
6251 request_id: i32
6252 }
6255#[repr(C)]
6256#[derive(Debug, Clone)]
6257pub struct PopWorkitemResponseWrapper {
6258 success: bool,
6259 error: *const c_char,
6260 workitem: *const WorkitemWrapper,
6261 request_id: i32
6262}
6263#[no_mangle]
6264#[tracing::instrument(skip_all)]
6265pub extern "C" fn pop_workitem (
6266 client: *mut ClientWrapper,
6267 options: *mut PopWorkitemRequestWrapper,
6268 downloadfolder: *const c_char,
6269) -> *mut PopWorkitemResponseWrapper {
6270 let options = match safe_wrapper(options) {
6271 Some(options) => options,
6272 None => {
6273 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6274 let response = PopWorkitemResponseWrapper {
6275 success: false,
6276 error: error_msg,
6277 workitem: std::ptr::null(),
6278 request_id: 0
6279 };
6280 return Box::into_raw(Box::new(response));
6281 }
6282 };
6283 let client_wrapper = match safe_wrapper(client) {
6284 Some(client) => client,
6285 None => {
6286 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6287 let response = PopWorkitemResponseWrapper {
6288 success: false,
6289 error: error_msg,
6290 workitem: std::ptr::null(),
6291 request_id: options.request_id
6292 };
6293 return Box::into_raw(Box::new(response));
6294 }
6295 };
6296 let client = client_wrapper.client.clone();
6297 let request = PopWorkitemRequest {
6298 wiq: c_char_to_str(options.wiq),
6299 wiqid: c_char_to_str(options.wiqid),
6300 ..Default::default()
6301 };
6302 if client.is_none() {
6303 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6304 let response = PopWorkitemResponseWrapper {
6305 success: false,
6306 error: error_msg,
6307 workitem: std::ptr::null(),
6308 request_id: options.request_id
6309 };
6310 return Box::into_raw(Box::new(response));
6311 }
6312 let downloadfolder = c_char_to_str(downloadfolder);
6313 let mut _downloadfolder = Some(downloadfolder.as_str());
6314 if downloadfolder.is_empty() {
6315 _downloadfolder = None;
6316 }
6317 let client = client.unwrap();
6318 let result = tokio::task::block_in_place(|| {
6319 let handle = client.get_runtime_handle();
6320 handle.block_on(client
6321 .pop_workitem(request, openiap_client::EnvConfig::new(), _downloadfolder)
6322 )
6323 });
6324 debug!("pop_workitem completed, parse result");
6325
6326 match result {
6327 Ok(data) => {
6328 let workitem = match data.workitem {
6329 Some(workitem) => {
6330 let workitem = wrap_workitem(workitem);
6331 trace!("wrap workitem");
6332 Box::into_raw(Box::new(workitem))
6333 },
6334 None => {
6335 std::ptr::null()
6336 }
6337 };
6338 Box::into_raw(Box::new(PopWorkitemResponseWrapper {
6339 success: true,
6340 error: std::ptr::null(),
6341 workitem,
6342 request_id: options.request_id
6343 }))
6344 }
6345 Err(e) => {
6346 let error_msg = CString::new(format!("Pop workitem failed: {:?}", e))
6347 .unwrap()
6348 .into_raw();
6349 Box::into_raw(Box::new(PopWorkitemResponseWrapper {
6350 success: false,
6351 error: error_msg,
6352 workitem: std::ptr::null(),
6353 request_id: options.request_id
6354 }))
6355 }
6356 }
6357}
6358#[no_mangle]
6359#[tracing::instrument(skip_all)]
6360pub extern "C" fn pop_workitem_async (
6361 client: *mut ClientWrapper,
6362 options: *mut PopWorkitemRequestWrapper,
6363 downloadfolder: *const c_char,
6364 callback: extern "C" fn(*mut PopWorkitemResponseWrapper),
6365) {
6366 let options = match safe_wrapper(options) {
6367 Some(options) => options,
6368 None => {
6369 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6370 let response = PopWorkitemResponseWrapper {
6371 success: false,
6372 error: error_msg,
6373 workitem: std::ptr::null(),
6374 request_id: 0
6375 };
6376 return callback(Box::into_raw(Box::new(response)));
6377 }
6378 };
6379 let client_wrapper = match safe_wrapper(client) {
6380 Some(client) => client,
6381 None => {
6382 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6383 let response = PopWorkitemResponseWrapper {
6384 success: false,
6385 error: error_msg,
6386 workitem: std::ptr::null(),
6387 request_id: options.request_id
6388 };
6389 return callback(Box::into_raw(Box::new(response)));
6390 }
6391 };
6392 let client = client_wrapper.client.clone();
6393 let request = PopWorkitemRequest {
6394 wiq: c_char_to_str(options.wiq),
6395 wiqid: c_char_to_str(options.wiqid),
6396 ..Default::default()
6397 };
6398 if client.is_none() {
6399 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6400 let response = PopWorkitemResponseWrapper {
6401 success: false,
6402 error: error_msg,
6403 workitem: std::ptr::null(),
6404 request_id: options.request_id
6405 };
6406 return callback(Box::into_raw(Box::new(response)));
6407 }
6408 let downloadfolder = c_char_to_str(downloadfolder);
6409 let client = client.unwrap();
6410 let handle = client.get_runtime_handle();
6411 let request_id = options.request_id;
6412 handle.spawn(async move {
6413 let mut _downloadfolder = Some(downloadfolder.as_str());
6414 if downloadfolder.is_empty() {
6415 _downloadfolder = None;
6416 }
6417
6418 let result = client
6419 .pop_workitem(request, openiap_client::EnvConfig::new(), _downloadfolder)
6420 .await;
6421 let response = match result {
6422 Ok(data) => {
6423 let workitem = match data.workitem {
6424 Some(workitem) => {
6425 let workitem = wrap_workitem(workitem);
6426 trace!("wrap workitem");
6427 Box::into_raw(Box::new(workitem))
6428 },
6429 None => {
6430 std::ptr::null()
6431 }
6432 };
6433 let response = PopWorkitemResponseWrapper {
6434 success: true,
6435 error: std::ptr::null(),
6436 workitem,
6437 request_id: request_id
6438 };
6439 Box::into_raw(Box::new(response))
6440 }
6441 Err(e) => {
6442 let error_msg = CString::new(format!("Pop workitem failed: {:?}", e))
6443 .unwrap()
6444 .into_raw();
6445 let response = PopWorkitemResponseWrapper {
6446 success: false,
6447 error: error_msg,
6448 workitem: std::ptr::null(),
6449 request_id: request_id
6450 };
6451 Box::into_raw(Box::new(response))
6452 }
6453 };
6454 trace!("callback with result");
6455 callback(response);
6456 });
6457}
6458#[no_mangle]
6459#[tracing::instrument(skip_all)]
6460pub extern "C" fn free_pop_workitem_response(response: *mut PopWorkitemResponseWrapper) {
6461 if response.is_null() {
6462 return;
6463 }
6464 unsafe {
6465 if !(*response).error.is_null() {
6466 let _ = CString::from_raw((*response).error as *mut c_char);
6467 }
6468 if !(*response).workitem.is_null() {
6469 free_workitem((*response).workitem as *mut WorkitemWrapper);
6470 }
6471 let _ = Box::from_raw(response);
6472 }
6473}
6474#[no_mangle]
6475#[tracing::instrument(skip_all)]
6476pub extern "C" fn free_workitem_file(file: *mut WorkitemFileWrapper) {
6477 if file.is_null() {
6478 return;
6479 }
6480 unsafe {
6481 if !(*file).filename.is_null() {
6482 let _ = CString::from_raw((*file).filename as *mut c_char);
6483 }
6484 if !(*file).id.is_null() {
6485 let _ = CString::from_raw((*file).id as *mut c_char);
6486 }
6487 let _ = Box::from_raw(file);
6488 }
6489}
6490#[no_mangle]
6491#[tracing::instrument(skip_all)]
6492pub extern "C" fn free_workitem(workitem: *mut WorkitemWrapper) {
6493 if workitem.is_null() {
6494 return;
6495 }
6496 unsafe {
6497 if !(*workitem).id.is_null() {
6498 let _ = CString::from_raw((*workitem).id as *mut c_char);
6499 }
6500 if !(*workitem).name.is_null() {
6501 let _ = CString::from_raw((*workitem).name as *mut c_char);
6502 }
6503 if !(*workitem).payload.is_null() {
6504 let _ = CString::from_raw((*workitem).payload as *mut c_char);
6505 }
6506 if !(*workitem).state.is_null() {
6507 let _ = CString::from_raw((*workitem).state as *mut c_char);
6508 }
6509 if !(*workitem).wiq.is_null() {
6510 let _ = CString::from_raw((*workitem).wiq as *mut c_char);
6511 }
6512 if !(*workitem).wiqid.is_null() {
6513 let _ = CString::from_raw((*workitem).wiqid as *mut c_char);
6514 }
6515 if !(*workitem).username.is_null() {
6516 let _ = CString::from_raw((*workitem).username as *mut c_char);
6517 }
6518 if !(*workitem).success_wiqid.is_null() {
6519 let _ = CString::from_raw((*workitem).success_wiqid as *mut c_char);
6520 }
6521 if !(*workitem).failed_wiqid.is_null() {
6522 let _ = CString::from_raw((*workitem).failed_wiqid as *mut c_char);
6523 }
6524 if !(*workitem).success_wiq.is_null() {
6525 let _ = CString::from_raw((*workitem).success_wiq as *mut c_char);
6526 }
6527 if !(*workitem).failed_wiq.is_null() {
6528 let _ = CString::from_raw((*workitem).failed_wiq as *mut c_char);
6529 }
6530 if !(*workitem).errormessage.is_null() {
6531 let _ = CString::from_raw((*workitem).errormessage as *mut c_char);
6532 }
6533 if !(*workitem).errorsource.is_null() {
6534 let _ = CString::from_raw((*workitem).errorsource as *mut c_char);
6535 }
6536 if !(*workitem).errortype.is_null() {
6537 let _ = CString::from_raw((*workitem).errortype as *mut c_char);
6538 }
6539
6540 if !(*workitem).files.is_null() && (*workitem).files_len > 0 {
6542 for i in 0..(*workitem).files_len as isize {
6543 let file_ptr = *(*workitem).files.offset(i);
6544 if !file_ptr.is_null() {
6545 free_workitem_file(file_ptr as *mut WorkitemFileWrapper);
6546 }
6547 }
6548 let _ = Box::from_raw((*workitem).files as *mut *const WorkitemFileWrapper);
6550 }
6551 let _ = Box::from_raw(workitem); }
6553}
6554
6555
6556#[no_mangle]
6557#[tracing::instrument(skip_all)]
6558pub extern "C" fn pop_workitem2_async (
6559 _client: *mut ClientWrapper,
6560 _options: *mut PopWorkitemRequestWrapper,
6561 _downloadfolder: *const c_char,
6562 request_id: i32,
6563 callback: extern "C" fn(*mut PopWorkitemResponseWrapper),
6564) {
6565 callback(Box::into_raw(Box::new(PopWorkitemResponseWrapper {
6566 success: true,
6567 error: std::ptr::null(),
6568 workitem: std::ptr::null(),
6569 request_id: request_id
6570 })));
6571}
6572
6573#[repr(C)]
6574#[derive(Debug, Clone)]
6575pub struct UpdateWorkitemRequestWrapper {
6576 workitem: *const WorkitemWrapper,
6577 ignoremaxretries: bool,
6578 files: *const *const WorkitemFileWrapper,
6579 files_len: i32,
6580 request_id: i32
6581}
6582#[repr(C)]
6583#[derive(Debug, Clone)]
6584pub struct UpdateWorkitemResponseWrapper {
6585 success: bool,
6586 error: *const c_char,
6587 workitem: *const WorkitemWrapper,
6588 request_id: i32
6589}
6590#[no_mangle]
6591#[tracing::instrument(skip_all)]
6592pub extern "C" fn update_workitem (
6593 client: *mut ClientWrapper,
6594 options: *mut UpdateWorkitemRequestWrapper,
6595) -> *mut UpdateWorkitemResponseWrapper {
6596 let options = match safe_wrapper(options) {
6597 Some(options) => options,
6598 None => {
6599 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6600 let response = UpdateWorkitemResponseWrapper {
6601 success: false,
6602 error: error_msg,
6603 workitem: std::ptr::null(),
6604 request_id: 0
6605 };
6606 return Box::into_raw(Box::new(response));
6607 }
6608 };
6609 let client_wrapper = match safe_wrapper(client) {
6610 Some(client) => client,
6611 None => {
6612 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6613 let response = UpdateWorkitemResponseWrapper {
6614 success: false,
6615 error: error_msg,
6616 workitem: std::ptr::null(),
6617 request_id: options.request_id
6618 };
6619 return Box::into_raw(Box::new(response));
6620 }
6621 };
6622 trace!("grab references");
6623 let client = client_wrapper.client.clone();
6624 let files_len = options.files_len;
6625 debug!("files_len: {:?}", files_len);
6626 let mut files: Vec<WorkitemFile> = vec![];
6627 if files_len > 0 {
6628 debug!("get files of options");
6629 let _files = unsafe { &*options.files };
6630 debug!("slice files");
6631 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
6632 debug!("loop files");
6633 files = _files.iter().map(|f| {
6634 debug!("process a file");
6635 let file = unsafe { &**f };
6636 debug!("create WorkitemFile instance 2");
6637 let filename = c_char_to_str(file.filename);
6638 debug!("filename: {:?}", filename);
6639 let id = c_char_to_str(file.id);
6640 debug!("id: {:?}", id);
6641 let compressed = file.compressed;
6642 debug!("compressed: {:?}", compressed);
6643 WorkitemFile {
6644 filename: c_char_to_str(file.filename),
6645 id: c_char_to_str(file.id),
6646 compressed: file.compressed,
6647 ..Default::default()
6648 }
6650 }).collect();
6651 }
6652 debug!("unwrap workitem");
6653 let workitem = unsafe { &*options.workitem };
6654 debug!("convert workitem wrapper to workitem");
6655 let workitem = workitem.as_workitem();
6656 let request = UpdateWorkitemRequest {
6657 workitem: Some(workitem),
6658 ignoremaxretries: options.ignoremaxretries,
6659 files,
6660 };
6661
6662 if client.is_none() {
6663 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6664 let response = UpdateWorkitemResponseWrapper {
6665 success: false,
6666 error: error_msg,
6667 workitem: std::ptr::null(),
6668 request_id: options.request_id
6669 };
6670 return Box::into_raw(Box::new(response));
6671 }
6672 let client = client.unwrap();
6673 let result = tokio::task::block_in_place(|| {
6674 let handle = client.get_runtime_handle();
6675 handle.block_on(client
6676 .update_workitem(request, openiap_client::EnvConfig::new())
6677 )
6678 });
6679
6680 match result {
6681 Ok(resp) => {
6682 Box::into_raw(Box::new(match resp.workitem {
6683 Some(workitem) => {
6684 let workitem = wrap_workitem(workitem);
6685 UpdateWorkitemResponseWrapper {
6686 success: true,
6687 error: std::ptr::null(),
6688 workitem: Box::into_raw(Box::new(workitem)),
6689 request_id: options.request_id
6690 }
6691 }
6692 None => {
6693 let error_msg = CString::new("Update workitem failed: workitem not found").unwrap().into_raw();
6694 UpdateWorkitemResponseWrapper {
6695 success: false,
6696 error: error_msg,
6697 workitem: std::ptr::null(),
6698 request_id: options.request_id
6699 }
6700 }
6701 }))
6702 }
6703 Err(e) => {
6704 let error_msg = CString::new(format!("Update workitem failed: {:?}", e))
6705 .unwrap()
6706 .into_raw();
6707 Box::into_raw(Box::new(UpdateWorkitemResponseWrapper {
6708 success: false,
6709 error: error_msg,
6710 workitem: std::ptr::null(),
6711 request_id: options.request_id
6712 }))
6713 }
6714 }
6715}
6716#[no_mangle]
6717#[tracing::instrument(skip_all)]
6718pub extern "C" fn update_workitem_async (
6719 client: *mut ClientWrapper,
6720 options: *mut UpdateWorkitemRequestWrapper,
6721 callback: extern "C" fn(*mut UpdateWorkitemResponseWrapper),
6722) {
6723 let options = match safe_wrapper(options) {
6724 Some(options) => options,
6725 None => {
6726 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6727 let response = UpdateWorkitemResponseWrapper {
6728 success: false,
6729 error: error_msg,
6730 workitem: std::ptr::null(),
6731 request_id: 0
6732 };
6733 return callback(Box::into_raw(Box::new(response)));
6734 }
6735 };
6736 let client_wrapper = match safe_wrapper(client) {
6737 Some(client) => client,
6738 None => {
6739 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6740 let response = UpdateWorkitemResponseWrapper {
6741 success: false,
6742 error: error_msg,
6743 workitem: std::ptr::null(),
6744 request_id: options.request_id
6745 };
6746 return callback(Box::into_raw(Box::new(response)));
6747 }
6748 };
6749 trace!("grab references");
6750 let client = client_wrapper.client.clone();
6751 let files_len = options.files_len;
6752 debug!("files_len: {:?}", files_len);
6753 let mut files: Vec<WorkitemFile> = vec![];
6754 if files_len > 0 {
6755 debug!("get files of options");
6756 let _files = unsafe { &*options.files };
6757 debug!("slice files");
6758 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
6759 debug!("loop files");
6760 files = _files.iter().map(|f| {
6761 debug!("process a file");
6762 let file = unsafe { &**f };
6763 debug!("create WorkitemFile instance 2");
6764 let filename = c_char_to_str(file.filename);
6765 debug!("filename: {:?}", filename);
6766 let id = c_char_to_str(file.id);
6767 debug!("id: {:?}", id);
6768 let compressed = file.compressed;
6769 debug!("compressed: {:?}", compressed);
6770 WorkitemFile {
6771 filename: c_char_to_str(file.filename),
6772 id: c_char_to_str(file.id),
6773 compressed: file.compressed,
6774 ..Default::default()
6775 }
6777 }).collect();
6778 }
6779 debug!("unwrap workitem");
6780 let workitem = unsafe { &*options
6781 .workitem };
6782
6783 debug!("convert workitem wrapper to workitem");
6784 let workitem = workitem.as_workitem();
6785 let request = UpdateWorkitemRequest {
6786 workitem: Some(workitem),
6787 ignoremaxretries: options.ignoremaxretries,
6788 files,
6789 };
6790
6791 if client.is_none() {
6792 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6793 let response = UpdateWorkitemResponseWrapper {
6794 success: false,
6795 error: error_msg,
6796 workitem: std::ptr::null(),
6797 request_id: options.request_id
6798 };
6799 return callback(Box::into_raw(Box::new(response)));
6800 }
6801 let client = client.unwrap();
6802 let handle = client.get_runtime_handle();
6803 let request_id = options.request_id;
6804 handle.spawn(async move {
6805 let result = client
6806 .update_workitem(request, openiap_client::EnvConfig::new())
6807 .await;
6808 let response = match result {
6809 Ok(resp) => {
6810 let response = match resp.workitem {
6811 Some(workitem) => {
6812 let workitem = wrap_workitem(workitem);
6813 UpdateWorkitemResponseWrapper {
6814 success: true,
6815 error: std::ptr::null(),
6816 workitem: Box::into_raw(Box::new(workitem)),
6817 request_id,
6818 }
6819 }
6820 None => {
6821 let error_msg = CString::new("Update workitem failed: workitem not found").unwrap().into_raw();
6822 UpdateWorkitemResponseWrapper {
6823 success: false,
6824 error: error_msg,
6825 workitem: std::ptr::null(),
6826 request_id,
6827 }
6828 }
6829 };
6830 Box::into_raw(Box::new(response))
6831 }
6832 Err(e) => {
6833 let error_msg = CString::new(format!("Update workitem failed: {:?}", e))
6834 .unwrap()
6835 .into_raw();
6836 Box::into_raw(Box::new(UpdateWorkitemResponseWrapper {
6837 success: false,
6838 error: error_msg,
6839 workitem: std::ptr::null(),
6840 request_id,
6841 }))
6842 }
6843 };
6844 callback(response);
6845 });
6846}
6847#[no_mangle]
6848#[tracing::instrument(skip_all)]
6849pub extern "C" fn free_update_workitem_response(response: *mut UpdateWorkitemResponseWrapper) {
6850 if response.is_null() {
6851 return;
6852 }
6853 unsafe {
6854 if !(*response).error.is_null() {
6855 let _ = CString::from_raw((*response).error as *mut c_char);
6856 }
6857 if !(*response).workitem.is_null() {
6858 free_workitem((*response).workitem as *mut WorkitemWrapper);
6859 }
6860 let _ = Box::from_raw(response);
6861 }
6862}
6863
6864#[repr(C)]
6865#[derive(Debug, Clone)]
6866pub struct DeleteWorkitemRequestWrapper {
6867 id: *const c_char,
6868 request_id: i32
6869}
6870#[repr(C)]
6871#[derive(Debug, Clone)]
6872pub struct DeleteWorkitemResponseWrapper {
6873 success: bool,
6874 error: *const c_char,
6875 request_id: i32
6876}
6877#[no_mangle]
6878#[tracing::instrument(skip_all)]
6879pub extern "C" fn delete_workitem(
6880 client: *mut ClientWrapper,
6881 options: *mut DeleteWorkitemRequestWrapper,
6882) -> *mut DeleteWorkitemResponseWrapper {
6883 let options = match safe_wrapper(options) {
6884 Some(options) => options,
6885 None => {
6886 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6887 let response = DeleteWorkitemResponseWrapper {
6888 success: false,
6889 error: error_msg,
6890 request_id: 0
6891 };
6892 return Box::into_raw(Box::new(response));
6893 }
6894 };
6895 let client_wrapper = match safe_wrapper(client) {
6896 Some(client) => client,
6897 None => {
6898 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6899 let response = DeleteWorkitemResponseWrapper {
6900 success: false,
6901 error: error_msg,
6902 request_id: options.request_id
6903 };
6904 return Box::into_raw(Box::new(response));
6905 }
6906 };
6907 let client = client_wrapper.client.clone();
6908 let request = DeleteWorkitemRequest {
6909 id: c_char_to_str(options.id),
6910 };
6911 if client.is_none() {
6912 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6913 let response = DeleteWorkitemResponseWrapper {
6914 success: false,
6915 error: error_msg,
6916 request_id: options.request_id
6917 };
6918 return Box::into_raw(Box::new(response));
6919 }
6920 let client = client.unwrap();
6921 let result = tokio::task::block_in_place(|| {
6922 let handle = client.get_runtime_handle();
6923 handle.block_on(client
6924 .delete_workitem(request, openiap_client::EnvConfig::new())
6925 )
6926 });
6927
6928 let response = match result {
6929 Ok(_) => {
6930 let response = DeleteWorkitemResponseWrapper {
6931 success: true,
6932 error: std::ptr::null(),
6933 request_id: options.request_id
6934 };
6935 Box::into_raw(Box::new(response))
6936 }
6937 Err(e) => {
6938 let error_msg = CString::new(format!("Delete workitem failed: {:?}", e))
6939 .unwrap()
6940 .into_raw();
6941 let response = DeleteWorkitemResponseWrapper {
6942 success: false,
6943 error: error_msg,
6944 request_id: options.request_id
6945 };
6946 Box::into_raw(Box::new(response))
6947 }
6948 };
6949 debug!("return response {:?}", response);
6950 response
6951}
6952#[no_mangle]
6953#[tracing::instrument(skip_all)]
6954pub extern "C" fn delete_workitem_async(
6955 client: *mut ClientWrapper,
6956 options: *mut DeleteWorkitemRequestWrapper,
6957 callback: extern "C" fn(*mut DeleteWorkitemResponseWrapper),
6958) {
6959 let options = match safe_wrapper(options) {
6960 Some(options) => options,
6961 None => {
6962 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6963 let response = DeleteWorkitemResponseWrapper {
6964 success: false,
6965 error: error_msg,
6966 request_id: 0
6967 };
6968 return callback(Box::into_raw(Box::new(response)));
6969 }
6970 };
6971 let client_wrapper = match safe_wrapper(client) {
6972 Some(client) => client,
6973 None => {
6974 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6975 let response = DeleteWorkitemResponseWrapper {
6976 success: false,
6977 error: error_msg,
6978 request_id: options.request_id
6979 };
6980 return callback(Box::into_raw(Box::new(response)));
6981 }
6982 };
6983 let client = client_wrapper.client.clone();
6984 let request = DeleteWorkitemRequest {
6985 id: c_char_to_str(options.id),
6986 };
6987 if client.is_none() {
6988 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6989 let response = DeleteWorkitemResponseWrapper {
6990 success: false,
6991 error: error_msg,
6992 request_id: options.request_id
6993 };
6994 return callback(Box::into_raw(Box::new(response)));
6995 }
6996 let client = client.unwrap();
6997 let handle = client.get_runtime_handle();
6998 let request_id = options.request_id;
6999 handle.spawn(async move {
7000 let result = client
7001 .delete_workitem(request, openiap_client::EnvConfig::new())
7002 .await;
7003 let response = match result {
7004 Ok(_) => {
7005 debug!("success");
7006 let response = DeleteWorkitemResponseWrapper {
7007 success: true,
7008 error: std::ptr::null(),
7009 request_id,
7010 };
7011 Box::into_raw(Box::new(response))
7012 }
7013 Err(e) => {
7014 let error_msg = CString::new(format!("Delete workitem failed: {:?}", e))
7015 .unwrap()
7016 .into_raw();
7017 debug!("failed: {:?}", error_msg);
7018 let response = DeleteWorkitemResponseWrapper {
7019 success: false,
7020 error: error_msg,
7021 request_id,
7022 };
7023 Box::into_raw(Box::new(response))
7024 }
7025 };
7026 debug!("callback {:?}", response);
7027 callback(response);
7028 });
7029}
7030#[no_mangle]
7031#[tracing::instrument(skip_all)]
7032pub extern "C" fn free_delete_workitem_response(response: *mut DeleteWorkitemResponseWrapper) {
7033 if response.is_null() {
7034 return;
7035 }
7036 unsafe {
7037 if !(*response).error.is_null() {
7038 let _ = CString::from_raw((*response).error as *mut c_char);
7039 }
7040 let _ = Box::from_raw(response);
7041 }
7042}
7043
7044
7045
7046
7047
7048#[repr(C)]
7049#[derive(Debug, Clone)]
7050pub struct ClientEventWrapper {
7051 event: *const c_char,
7052 reason: *const c_char,
7053}
7054impl Default for ClientEventWrapper {
7055 fn default() -> Self {
7056 ClientEventWrapper {
7057 event: std::ptr::null(),
7058 reason: std::ptr::null(),
7059 }
7060 }
7061}
7062#[repr(C)]
7063pub struct ClientEventResponseWrapper {
7064 success: bool,
7065 eventid: *const c_char,
7066 error: *const c_char,
7067}
7068
7069#[no_mangle]
7070#[tracing::instrument(skip_all)]
7071pub extern "C" fn on_client_event(
7072 client: *mut ClientWrapper
7073) -> *mut ClientEventResponseWrapper {
7074 let client_wrapper = match safe_wrapper(client) {
7075 Some(client) => client,
7076 None => {
7077 let error_msg = CString::new("Invalid options, client is None").unwrap().into_raw();
7078 let response = ClientEventResponseWrapper {
7079 success: false,
7080 eventid: std::ptr::null(),
7081 error: error_msg,
7082 };
7083 return Box::into_raw(Box::new(response));
7084 }
7085 };
7086 let mut client = client_wrapper.client.clone();
7087 if client.is_none() {
7088 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7089 let response = ClientEventResponseWrapper {
7090 success: false,
7091 eventid: std::ptr::null(),
7092 error: error_msg,
7093 };
7094 return Box::into_raw(Box::new(response));
7095 }
7096 let client = client.as_mut().unwrap();
7097 let eventid = Client::get_uniqueid();
7098 let _eventid = eventid.clone();
7099 tokio::task::block_in_place(|| {
7100 let handle = client.get_runtime_handle();
7101 handle.block_on(client.on_event(Box::new({
7102 move |event: ClientEvent| {
7103 let clientid = _eventid.clone();
7104 debug!("client event: {:?}", event);
7105
7106 let mut e = CLIENT_EVENTS.lock().unwrap();
7107 let queue = e.get_mut(&clientid);
7108 match queue {
7109 Some(q) => {
7110 q.push_back(event);
7111 }
7112 None => {
7113 let mut q = std::collections::VecDeque::new();
7114 q.push_back(event);
7115 e.insert(clientid, q);
7116 }
7117 }
7118 }
7119 })));
7120 });
7121
7122 let mut events = CLIENT_EVENTS.lock().unwrap();
7123 let _eventid = eventid.clone();
7124 let queue = events.get_mut(&_eventid);
7125 if queue.is_none() {
7126 let q = std::collections::VecDeque::new();
7127 let k = String::from(&eventid);
7128 events.insert(k, q);
7129 };
7130 let response = ClientEventResponseWrapper {
7131 success: true,
7132 eventid: CString::new(eventid).unwrap().into_raw(),
7133 error: std::ptr::null(),
7134 };
7135 return Box::into_raw(Box::new(response));
7136}
7137type ClientEventCallback = extern "C" fn(*mut ClientEventWrapper);
7138#[no_mangle]
7139#[tracing::instrument(skip_all)]
7140pub extern "C" fn on_client_event_async(
7141 client: *mut ClientWrapper,
7142 event_callback: ClientEventCallback,
7143) -> *mut ClientEventResponseWrapper {
7144 debug!("on_client_event_async::begin");
7145 let client_wrapper = match safe_wrapper(client) {
7146 Some(client) => client,
7147 None => {
7148 let error_msg = CString::new("Invalid options, client is None").unwrap().into_raw();
7149 let response = ClientEventResponseWrapper {
7150 success: false,
7151 eventid: std::ptr::null(),
7152 error: error_msg,
7153 };
7154 return Box::into_raw(Box::new(response));
7155 }
7156 };
7157 let mut client = client_wrapper.client.clone();
7158 if client.is_none() {
7159 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7160 let response = ClientEventResponseWrapper {
7161 success: false,
7162 eventid: std::ptr::null(),
7163 error: error_msg,
7164 };
7165 return Box::into_raw(Box::new(response));
7166 }
7167 let client = client.as_mut().unwrap();
7168 let eventid = Client::get_uniqueid();
7169 debug!("on_client_event_async::eventid: {:?}", eventid);
7170 let _eventid = eventid.clone();
7171 tokio::task::block_in_place(|| {
7172 let handle = client.get_runtime_handle();
7173 handle.block_on(client
7174 .on_event(
7175 Box::new(move |event: ClientEvent| {
7176 let clientid = _eventid.clone();
7177 debug!("client event: {:?}", event);
7178 let mut e = CLIENT_EVENTS.lock().unwrap();
7179 let queue = e.get_mut(&clientid);
7180 match queue {
7181 Some(_q) => {
7182 }
7183 None => {
7184 return;
7186 }
7187 };
7188 let event = match event {
7189 ClientEvent::Connecting => ClientEventWrapper { event: CString::new("Connecting").unwrap().into_raw(),reason: std::ptr::null() },
7190 ClientEvent::Connected => ClientEventWrapper { event: CString::new("Connected").unwrap().into_raw(),reason: std::ptr::null() },
7191 ClientEvent::Disconnected(reason) => ClientEventWrapper { event: CString::new("Disconnected").unwrap().into_raw(),reason: CString::new(reason).unwrap().into_raw() },
7192 ClientEvent::SignedIn => ClientEventWrapper { event: CString::new("SignedIn").unwrap().into_raw(),reason: std::ptr::null() },
7193 };
7195 let event = Box::into_raw(Box::new(event));
7196
7197 event_callback(event);
7198 debug!("client event: {:?}", event);
7199 }),
7200 )
7201 )
7202 });
7203
7204 let mut events = CLIENT_EVENTS.lock().unwrap();
7205 let _eventid = eventid.clone();
7206 let queue = events.get_mut(&_eventid);
7207 if queue.is_none() {
7208 debug!("create event queue, for eventid: {:?}", eventid);
7209 let q = std::collections::VecDeque::new();
7210 let k = String::from(&eventid);
7211 events.insert(k, q);
7212 };
7213 debug!("on_client_event_async::end");
7214 let response = ClientEventResponseWrapper {
7215 success: true,
7216 eventid: CString::new(eventid).unwrap().into_raw(),
7217 error: std::ptr::null(),
7218 };
7219 return Box::into_raw(Box::new(response));
7220
7221}
7222
7223#[no_mangle]
7224#[tracing::instrument(skip_all)]
7225pub extern "C" fn next_client_event (
7226 clientid: *const c_char,
7227) -> *mut ClientEventWrapper {
7228 trace!("unwrap clientid");
7229 let clientid = c_char_to_str(clientid);
7230 trace!("clientid {:}", clientid);
7231 let clientid = clientid.to_string();
7232 trace!("unwrap events");
7233 let mut e = CLIENT_EVENTS.lock().unwrap();
7234 trace!("get queue");
7235 let queue = e.get_mut(&clientid);
7236 match queue {
7237 Some(q) => {
7238 match q.pop_front() {
7239 Some(event) => {
7240 debug!("got client event");
7241 let event = match event {
7242 ClientEvent::Connecting => ClientEventWrapper { event: CString::new("Connecting").unwrap().into_raw(),reason: std::ptr::null() },
7243 ClientEvent::Connected => ClientEventWrapper { event: CString::new("Connected").unwrap().into_raw(),reason: std::ptr::null() },
7244 ClientEvent::Disconnected(reason) => ClientEventWrapper { event: CString::new("Disconnected").unwrap().into_raw(),reason: CString::new(reason).unwrap().into_raw() },
7245 ClientEvent::SignedIn => ClientEventWrapper { event: CString::new("SignedIn").unwrap().into_raw(),reason: std::ptr::null() },
7246 };
7248 Box::into_raw(Box::new(event))
7249 }
7250 None => {
7251 trace!("No event");
7252 Box::into_raw(Box::new(ClientEventWrapper::default()))
7253 },
7254 }
7255 },
7256 None => {
7257 debug!("Queue for {:} not found", clientid);
7258 Box::into_raw(Box::new(ClientEventWrapper::default()))
7259 },
7260 }
7261}
7262
7263#[repr(C)]
7264pub struct OffClientEventResponseWrapper {
7265 success: bool,
7266 error: *const c_char,
7267}
7268#[no_mangle]
7269#[tracing::instrument(skip_all)]
7270pub extern "C" fn off_client_event(
7271 eventid: *const c_char,
7272) -> *mut OffClientEventResponseWrapper {
7273 let eventid = c_char_to_str(eventid);
7274 if eventid.is_empty() {
7275 let error_msg = CString::new("eventid is required").unwrap().into_raw();
7276 let response = OffClientEventResponseWrapper {
7277 success: false,
7278 error: error_msg,
7279 };
7280 return Box::into_raw(Box::new(response));
7281 }
7282 trace!("eventid: {:?}", eventid);
7283
7284 let mut e = CLIENT_EVENTS.lock().unwrap();
7285 let queue = e.get_mut(&eventid);
7286 if let Some(q) = queue {
7287 q.clear();
7288 e.remove(&eventid);
7289 };
7290 Box::into_raw(Box::new(OffClientEventResponseWrapper {
7291 success: true,
7292 error: std::ptr::null(),
7293 }))
7294}
7295
7296#[no_mangle]
7297#[tracing::instrument(skip_all)]
7298pub extern "C" fn free_off_event_response(response: *mut OffClientEventResponseWrapper) {
7299 if response.is_null() {
7300 return;
7301 }
7302 unsafe {
7303 if !(*response).error.is_null() {
7304 let _ = CString::from_raw((*response).error as *mut c_char);
7305 }
7306 let _ = Box::from_raw(response);
7307 }
7308}
7309#[no_mangle]
7310#[tracing::instrument(skip_all)]
7311pub extern "C" fn free_event_response(response: *mut ClientEventResponseWrapper) {
7312 if response.is_null() {
7313 return;
7314 }
7315 unsafe {
7316 if !(*response).error.is_null() {
7317 let _ = CString::from_raw((*response).error as *mut c_char);
7318 }
7319 if !(*response).eventid.is_null() {
7320 let _ = CString::from_raw((*response).eventid as *mut c_char);
7321 }
7322 let _ = Box::from_raw(response);
7323 }
7324}
7325#[no_mangle]
7326#[tracing::instrument(skip_all)]
7327pub extern "C" fn free_client_event(response: *mut ClientEventWrapper) {
7328 if response.is_null() {
7329 return;
7330 }
7331 unsafe {
7332 if !(*response).event.is_null() {
7333 let _ = CString::from_raw((*response).event as *mut c_char);
7334 }
7335 if !(*response).reason.is_null() {
7336 let _ = CString::from_raw((*response).reason as *mut c_char);
7337 }
7338 let _ = Box::from_raw(response);
7339 }
7340}
7341#[repr(C)]
7342pub struct RpcResponseWrapper {
7343 success: bool,
7344 result: *const c_char,
7345 error: *const c_char,
7346 request_id: i32
7347}
7348#[no_mangle]
7349#[tracing::instrument(skip_all)]
7350pub extern "C" fn rpc(
7351 client: *mut ClientWrapper,
7352 options: *mut QueueMessageRequestWrapper,
7353 timeout: i32
7354) -> *mut RpcResponseWrapper {
7355 let options = match safe_wrapper(options) {
7356 Some(options) => options,
7357 None => {
7358 let error_msg = CString::new("Invalid options").unwrap().into_raw();
7359 let response = RpcResponseWrapper {
7360 success: false,
7361 result: std::ptr::null(),
7362 error: error_msg,
7363 request_id: 0
7364 };
7365 return Box::into_raw(Box::new(response));
7366 }
7367 };
7368 let client_wrapper = match safe_wrapper(client) {
7369 Some(client) => client,
7370 None => {
7371 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7372 let response = RpcResponseWrapper {
7373 success: false,
7374 result: std::ptr::null(),
7375 error: error_msg,
7376 request_id: options.request_id
7377 };
7378 return Box::into_raw(Box::new(response));
7379 }
7380 };
7381 let client = client_wrapper.client.clone();
7382
7383 if client.is_none() {
7384 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7385 let response = RpcResponseWrapper {
7386 success: false,
7387 result: std::ptr::null(),
7388 error: error_msg,
7389 request_id: options.request_id
7390 };
7391 return Box::into_raw(Box::new(response));
7392 }
7393 let client = client.unwrap();
7394
7395 let mut _timeout = client.get_default_timeout();
7396 if timeout >= 0 {
7397 _timeout = tokio::time::Duration::from_secs(timeout as u64);
7398 }
7399
7400 let result = tokio::task::block_in_place(|| {
7401 let handle = client.get_runtime_handle();
7402 let request = QueueMessageRequest {
7403 queuename: c_char_to_str(options.queuename),
7404 correlation_id: c_char_to_str(options.correlation_id),
7405 replyto: c_char_to_str(options.replyto),
7406 routingkey: c_char_to_str(options.routingkey),
7407 exchangename: c_char_to_str(options.exchangename),
7408 data: c_char_to_str(options.data),
7409 striptoken: options.striptoken,
7410 expiration: options.expiration,
7411 };
7412 handle.block_on(client.rpc(request, openiap_client::EnvConfig::new(), _timeout))
7413 });
7414
7415 match result {
7416 Ok(data) => {
7417 let result = CString::new(data).unwrap().into_raw();
7418 let response = RpcResponseWrapper {
7419 success: true,
7420 result,
7421 error: std::ptr::null(),
7422 request_id: options.request_id
7423 };
7424 Box::into_raw(Box::new(response))
7425 }
7426 Err(e) => {
7427 let error_msg = CString::new(format!("RPC failed: {:?}", e))
7428 .unwrap()
7429 .into_raw();
7430 let response = RpcResponseWrapper {
7433 success: false,
7434 result: std::ptr::null(),
7435 error: error_msg,
7436 request_id: options.request_id
7437 };
7438 Box::into_raw(Box::new(response))
7439 }
7440 }
7441}
7442pub type RpcResponseCallback = extern "C" fn(*mut RpcResponseWrapper);
7443#[no_mangle]
7444#[tracing::instrument(skip_all)]
7445pub extern "C" fn rpc_async(
7446 client: *mut ClientWrapper,
7447 options: *mut QueueMessageRequestWrapper,
7448 response_callback: RpcResponseCallback,
7449 timeout: i32,
7450) {
7451 let options = match safe_wrapper(options) {
7453 Some(o) => o,
7454 None => {
7455 let error_msg = CString::new("Invalid options").unwrap().into_raw();
7456 let response = RpcResponseWrapper {
7457 success: false,
7458 result: std::ptr::null(),
7459 error: error_msg,
7460 request_id: 0
7461 };
7462 response_callback(Box::into_raw(Box::new(response)));
7463 return;
7464 }
7465 };
7466
7467 let client_wrapper = match safe_wrapper(client) {
7469 Some(c) => c,
7470 None => {
7471 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7472 let response = RpcResponseWrapper {
7473 success: false,
7474 result: std::ptr::null(),
7475 error: error_msg,
7476 request_id: options.request_id
7477 };
7478 response_callback(Box::into_raw(Box::new(response)));
7479 return;
7480 }
7481 };
7482
7483 let client = match client_wrapper.client.clone() {
7485 Some(c) => c,
7486 None => {
7487 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7488 let response = RpcResponseWrapper {
7489 success: false,
7490 result: std::ptr::null(),
7491 error: error_msg,
7492 request_id: options.request_id
7493 };
7494 response_callback(Box::into_raw(Box::new(response)));
7495 return;
7496 }
7497 };
7498
7499 let request = QueueMessageRequest {
7501 queuename: c_char_to_str(options.queuename),
7502 correlation_id: c_char_to_str(options.correlation_id),
7503 replyto: c_char_to_str(options.replyto),
7504 routingkey: c_char_to_str(options.routingkey),
7505 exchangename: c_char_to_str(options.exchangename),
7506 data: c_char_to_str(options.data),
7507 striptoken: options.striptoken,
7508 expiration: options.expiration
7509 };
7510
7511 let runtime_handle = client.get_runtime_handle();
7513
7514 let request_id = options.request_id;
7515
7516 let mut _timeout = client.get_default_timeout();
7517 if timeout >= 0 {
7518 _timeout = tokio::time::Duration::from_secs(timeout as u64);
7519 }
7520
7521 runtime_handle.spawn(async move {
7523 let result = client.rpc(request, openiap_client::EnvConfig::new(), _timeout).await;
7525
7526 let response = match result {
7528 Ok(data) => {
7529 let result_c = CString::new(data).unwrap().into_raw();
7530 RpcResponseWrapper {
7531 success: true,
7532 result: result_c,
7533 error: std::ptr::null(),
7534 request_id: request_id
7535 }
7536 }
7537 Err(e) => {
7538 let error_msg = CString::new(format!("RPC failed: {:?}", e))
7539 .unwrap()
7540 .into_raw();
7541 RpcResponseWrapper {
7542 success: false,
7543 result: std::ptr::null(),
7544 error: error_msg,
7545 request_id: request_id
7546 }
7547 }
7548 };
7549
7550 response_callback(Box::into_raw(Box::new(response)));
7552 });
7553}
7554
7555#[no_mangle]
7659#[tracing::instrument(skip_all)]
7660pub extern "C" fn free_rpc_response(response: *mut RpcResponseWrapper) {
7661 if response.is_null() {
7662 return;
7663 }
7664 unsafe {
7665 if !(*response).error.is_null() {
7666 let _ = CString::from_raw((*response).error as *mut c_char);
7667 }
7668 if !(*response).result.is_null() {
7669 let _ = CString::from_raw((*response).result as *mut c_char);
7670 }
7671 let _ = Box::from_raw(response);
7672 }
7673}
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692#[repr(C)]
7694pub struct InvokeOpenRPARequestWrapper {
7695 robotid: *const c_char,
7696 workflowid: *const c_char,
7697 payload: *const c_char,
7698 rpc: bool,
7699 request_id: i32,
7700}
7701#[repr(C)]
7703pub struct InvokeOpenRPAResponseWrapper {
7704 success: bool,
7705 result: *const c_char,
7706 error: *const c_char,
7707 request_id: i32,
7708}
7709#[no_mangle]
7711#[tracing::instrument(skip_all)]
7712pub extern "C" fn invoke_openrpa(
7713 client: *mut ClientWrapper,
7714 options: *mut InvokeOpenRPARequestWrapper,
7715 timeout: i32,
7716) -> *mut InvokeOpenRPAResponseWrapper {
7717 let options = match safe_wrapper(options) {
7718 Some(options) => options,
7719 None => {
7720 let error_msg = CString::new("Invalid options").unwrap().into_raw();
7721 let response = InvokeOpenRPAResponseWrapper {
7722 success: false,
7723 result: std::ptr::null(),
7724 error: error_msg,
7725 request_id: 0,
7726 };
7727 return Box::into_raw(Box::new(response));
7728 }
7729 };
7730 let client_wrapper = match safe_wrapper(client) {
7731 Some(client) => client,
7732 None => {
7733 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7734 let response = InvokeOpenRPAResponseWrapper {
7735 success: false,
7736 result: std::ptr::null(),
7737 error: error_msg,
7738 request_id: options.request_id,
7739 };
7740 return Box::into_raw(Box::new(response));
7741 }
7742 };
7743 let request = InvokeOpenRpaRequest {
7744 payload: c_char_to_str(options.payload),
7745 robotid: c_char_to_str(options.robotid),
7746 workflowid: c_char_to_str(options.workflowid),
7747 rpc: options.rpc
7748 };
7749 if client_wrapper.client.is_none() {
7750 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7751 let response = InvokeOpenRPAResponseWrapper {
7752 success: false,
7753 result: std::ptr::null(),
7754 error: error_msg,
7755 request_id: options.request_id,
7756 };
7757 return Box::into_raw(Box::new(response));
7758 }
7759 let client = client_wrapper.client.clone().unwrap();
7760 let mut _timeout = client.get_default_timeout();
7761 if timeout >= 0 {
7762 _timeout = tokio::time::Duration::from_secs(timeout as u64);
7763 }
7764
7765 let result = tokio::task::block_in_place(|| {
7766 let handle = client.get_runtime_handle();
7767 handle.block_on(client.invoke_openrpa(request, openiap_client::EnvConfig::new(), Some(_timeout)))
7768 });
7769 Box::into_raw(Box::new(match result {
7770 Ok(data) => {
7771 let result: *const c_char = CString::new(data).unwrap().into_raw();
7772 InvokeOpenRPAResponseWrapper {
7773 success: true,
7774 result,
7775 error: std::ptr::null(),
7776 request_id: options.request_id,
7777 }
7778 }
7779 Err(e) => {
7780 let error_msg = CString::new(format!("Query failed: {:?}", e))
7781 .unwrap()
7782 .into_raw();
7783 InvokeOpenRPAResponseWrapper {
7784 success: false,
7785 result: std::ptr::null(),
7786 error: error_msg,
7787 request_id: options.request_id,
7788 }
7789 }
7790 }))
7791}
7792#[no_mangle]
7793#[tracing::instrument(skip_all)]
7794pub extern "C" fn free_invoke_openrpa_response(response: *mut InvokeOpenRPAResponseWrapper) {
7795 if response.is_null() {
7796 return;
7797 }
7798 unsafe {
7799 if !(*response).error.is_null() {
7800 let _ = CString::from_raw((*response).error as *mut c_char);
7801 }
7802 if !(*response).result.is_null() {
7803 let _ = CString::from_raw((*response).result as *mut c_char);
7804 }
7805 let _ = Box::from_raw(response);
7806 }
7807}