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