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 trace!("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 trace!("connect::begin");
437 let res: Result<(), openiap_client::OpenIAPError> = client.connect(&server_address);
438 trace!("connect::complete");
439 if res.is_err() {
440 let e = res.err().unwrap();
441 debug!("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 debug!("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 trace!("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 trace!("unwrap watchid");
4291 let watchid = c_char_to_str(watchid);
4292 trace!("watchid {:}", watchid);
4293 let watchid = watchid.to_string();
4294 trace!("unwrap events");
4295 let mut e = WATCH_EVENTS.lock().unwrap();
4296 trace!("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 trace!("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 |_client, 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 None
4708 }),
4709 )
4710 )
4711 });
4712
4713 let response = match result {
4714 Ok(data) => {
4715 let id = String::from(&data);
4716 let mut events = QUEUE_EVENTS.lock().unwrap();
4717 let queue = events.get_mut(&id);
4718 if queue.is_none() {
4719 let q = std::collections::VecDeque::new();
4720 let k = String::from(&data);
4721 events.insert(k, q);
4722 }
4723 let queuename = CString::new(id).unwrap().into_raw();
4724 RegisterQueueResponseWrapper {
4725 success: true,
4726 queuename,
4727 error: std::ptr::null(),
4728 request_id: options.request_id,
4729 }
4730 }
4731 Err(e) => {
4732 let error_msg = CString::new(format!("queue failed: {:?}", e))
4733 .unwrap()
4734 .into_raw();
4735 RegisterQueueResponseWrapper {
4736 success: false,
4737 queuename: std::ptr::null(),
4738 error: error_msg,
4739 request_id: options.request_id,
4740 }
4741 }
4742 };
4743 Box::into_raw(Box::new(response))
4744}
4745
4746type QueueEventCallback = extern "C" fn(*mut QueueEventWrapper) -> *const c_char;
4747#[no_mangle]
4748#[tracing::instrument(skip_all)]
4749pub extern "C" fn register_queue_async(
4750 client: *mut ClientWrapper,
4751 options: *mut RegisterQueueRequestWrapper,
4752 event_callback: QueueEventCallback,
4753) -> *mut RegisterQueueResponseWrapper {
4754 debug!("register_queue_async");
4755 let options = match safe_wrapper(options) {
4756 Some(options) => options,
4757 None => {
4758 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4759 let response = RegisterQueueResponseWrapper {
4760 success: false,
4761 queuename: std::ptr::null(),
4762 error: error_msg,
4763 request_id: 0,
4764 };
4765 return Box::into_raw(Box::new(response))
4766 }
4767 };
4768 let client_wrapper = match safe_wrapper(client) {
4769 Some(client) => client,
4770 None => {
4771 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4772 let response = RegisterQueueResponseWrapper {
4773 success: false,
4774 queuename: std::ptr::null(),
4775 error: error_msg,
4776 request_id: options.request_id,
4777 };
4778 return Box::into_raw(Box::new(response))
4779 }
4780 };
4781 let client = client_wrapper.client.clone();
4782 let request = RegisterQueueRequest {
4783 queuename: c_char_to_str(options.queuename),
4784 };
4785 if client.is_none() {
4786 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4787 let response = RegisterQueueResponseWrapper {
4788 success: false,
4789 queuename: std::ptr::null(),
4790 error: error_msg,
4791 request_id: options.request_id,
4792 };
4793 return Box::into_raw(Box::new(response))
4794 }
4795 let client = client.unwrap();
4796 debug!("register_queue_async: runtime.spawn");
4797 let request_id = options.request_id;
4798 let result = tokio::task::block_in_place(|| {
4799 let handle = client.get_runtime_handle();
4800 handle.block_on(
4801 client
4802 .register_queue(
4803 request,
4804 Box::new(move |_client, event: QueueEvent| {
4805 debug!("register_queue_async: spawn new task, to call event_callback");
4806 trace!("register_queue_async: call event_callback");
4807 let queuename = CString::new(event.queuename).unwrap().into_raw();
4808 let correlation_id = CString::new(event.correlation_id).unwrap().into_raw();
4809 let replyto = CString::new(event.replyto).unwrap().into_raw();
4810 let routingkey = CString::new(event.routingkey).unwrap().into_raw();
4811 let exchangename = CString::new(event.exchangename).unwrap().into_raw();
4812 let data = CString::new(event.data).unwrap().into_raw();
4813 let event = Box::new(QueueEventWrapper {
4814 queuename,
4815 correlation_id,
4816 replyto,
4817 routingkey,
4818 exchangename,
4819 data,
4820 request_id
4821 });
4822 let result = event_callback(Box::into_raw(event));
4823 let result = c_char_to_str(result);
4824 if result.is_empty() {
4825 return None
4826 }
4827 let result = result.to_string();
4828 Some(result)
4829 }),
4830 )
4831 )
4832 });
4833
4834 debug!("register_queue_async: parse result");
4835 let response = match result {
4836 Ok(data) => {
4837 let queuename = CString::new(data).unwrap().into_raw();
4838 RegisterQueueResponseWrapper {
4839 success: true,
4840 queuename,
4841 error: std::ptr::null(),
4842 request_id: options.request_id,
4843 }
4844 }
4845 Err(e) => {
4846 let error_msg = CString::new(format!("RegisterQueue failed: {:?}", e))
4847 .unwrap()
4848 .into_raw();
4849 RegisterQueueResponseWrapper {
4850 success: false,
4851 queuename: std::ptr::null(),
4852 error: error_msg,
4853 request_id: options.request_id,
4854 }
4855 }
4856 };
4857
4858 Box::into_raw(Box::new(response))
4859}
4860
4861
4862
4863#[no_mangle]
4864#[tracing::instrument(skip_all)]
4865pub extern "C" fn free_register_queue_response(response: *mut RegisterQueueResponseWrapper) {
4866 if response.is_null() {
4867 return;
4868 }
4869 unsafe {
4870 if !(*response).error.is_null() {
4871 let _ = CString::from_raw((*response).error as *mut c_char);
4872 }
4873 if !(*response).queuename.is_null() {
4874 let _ = CString::from_raw((*response).queuename as *mut c_char);
4875 }
4876 let _ = Box::from_raw(response);
4877 }
4878}
4879
4880
4881#[repr(C)]
4882pub struct RegisterExchangeRequestWrapper {
4883 exchangename: *const c_char,
4884 algorithm: *const c_char,
4885 routingkey: *const c_char,
4886 addqueue: bool,
4887 request_id: i32
4888}
4889#[repr(C)]
4890pub struct RegisterExchangeResponseWrapper {
4891 success: bool,
4892 queuename: *const c_char,
4893 error: *const c_char,
4894 request_id: i32
4895}
4896#[no_mangle]
4897#[tracing::instrument(skip_all)]
4898pub extern "C" fn register_exchange (
4899 client: *mut ClientWrapper,
4900 options: *mut RegisterExchangeRequestWrapper,
4901) -> *mut RegisterExchangeResponseWrapper {
4902 let options = match safe_wrapper(options) {
4903 Some(options) => options,
4904 None => {
4905 let error_msg = CString::new("Invalid options").unwrap().into_raw();
4906 let response = RegisterExchangeResponseWrapper {
4907 success: false,
4908 queuename: std::ptr::null(),
4909 error: error_msg,
4910 request_id: 0,
4911 };
4912 return Box::into_raw(Box::new(response));
4913 }
4914 };
4915 let client_wrapper = match safe_wrapper(client) {
4916 Some(client) => client,
4917 None => {
4918 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4919 let response = RegisterExchangeResponseWrapper {
4920 success: false,
4921 queuename: std::ptr::null(),
4922 error: error_msg,
4923 request_id: options.request_id,
4924 };
4925 return Box::into_raw(Box::new(response));
4926 }
4927 };
4928 let client = client_wrapper.client.clone();
4929 let request = RegisterExchangeRequest {
4930 exchangename: c_char_to_str(options.exchangename),
4931 algorithm: c_char_to_str(options.algorithm),
4932 routingkey: c_char_to_str(options.routingkey),
4933 addqueue: options.addqueue,
4934 };
4935 if client.is_none() {
4936 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
4937 let response = RegisterExchangeResponseWrapper {
4938 success: false,
4939 queuename: std::ptr::null(),
4940 error: error_msg,
4941 request_id: options.request_id,
4942 };
4943 return Box::into_raw(Box::new(response));
4944 }
4945 let client = client.unwrap();
4946 let result = tokio::task::block_in_place(|| {
4947 let handle = client.get_runtime_handle();
4948 handle.block_on(
4949 client
4950 .register_exchange(request,
4951 Box::new(move |_client, event: QueueEvent| {
4952 trace!("exchange: event: {:?}", event);
4953 let queuename = CString::new(event.queuename.clone())
4954 .unwrap()
4955 .into_string()
4956 .unwrap();
4957 let mut e = QUEUE_EVENTS.lock().unwrap();
4958 let queue = e.get_mut(&queuename);
4959 match queue {
4960 Some(q) => {
4961 q.push_back(event);
4962 }
4963 None => {
4964 let mut q = std::collections::VecDeque::new();
4965 q.push_back(event);
4966 e.insert(queuename, q);
4967 }
4968 }
4969 None
4970 }),
4971
4972 )
4973 )
4974 });
4975
4976 let response = match result {
4977 Ok(data) => {
4978 let queuename = CString::new(data).unwrap().into_raw();
4979 RegisterExchangeResponseWrapper {
4980 success: true,
4981 queuename,
4982 error: std::ptr::null(),
4983 request_id: options.request_id,
4984 }
4985 }
4986 Err(e) => {
4987 let error_msg = CString::new(format!("RegisterExchange failed: {:?}", e))
4988 .unwrap()
4989 .into_raw();
4990 RegisterExchangeResponseWrapper {
4991 success: false,
4992 queuename: std::ptr::null(),
4993 error: error_msg,
4994 request_id: options.request_id,
4995 }
4996 }
4997 };
4998
4999 Box::into_raw(Box::new(response))
5000}
5001type ExchangeEventCallback = extern "C" fn(*mut QueueEventWrapper);
5002#[no_mangle]
5003#[tracing::instrument(skip_all)]
5004pub extern "C" fn register_exchange_async(
5005 client: *mut ClientWrapper,
5006 options: *mut RegisterExchangeRequestWrapper,
5007 event_callback: ExchangeEventCallback,
5008) -> *mut RegisterExchangeResponseWrapper {
5009 debug!("register_exchange_async");
5010 let options = match safe_wrapper(options) {
5011 Some(options) => options,
5012 None => {
5013 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5014 let response = RegisterExchangeResponseWrapper {
5015 success: false,
5016 queuename: std::ptr::null(),
5017 error: error_msg,
5018 request_id: 0,
5019 };
5020 return Box::into_raw(Box::new(response))
5021 }
5022 };
5023 let client_wrapper = match safe_wrapper(client) {
5024 Some(client) => client,
5025 None => {
5026 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5027 let response = RegisterExchangeResponseWrapper {
5028 success: false,
5029 queuename: std::ptr::null(),
5030 error: error_msg,
5031 request_id: options.request_id,
5032 };
5033 return Box::into_raw(Box::new(response))
5034 }
5035 };
5036 let client = client_wrapper.client.clone();
5037 let request = RegisterExchangeRequest {
5038 exchangename: c_char_to_str(options.exchangename),
5039 algorithm: c_char_to_str(options.algorithm),
5040 routingkey: c_char_to_str(options.routingkey),
5041 addqueue: options.addqueue,
5042 };
5043 if client.is_none() {
5044 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5045 let response = RegisterExchangeResponseWrapper {
5046 success: false,
5047 queuename: std::ptr::null(),
5048 error: error_msg,
5049 request_id: options.request_id,
5050 };
5051 return Box::into_raw(Box::new(response))
5052 }
5053 let client = client.unwrap();
5054 debug!("register_exchange_async: runtime.spawn");
5055 let request_id = options.request_id;
5056 let result = tokio::task::block_in_place(|| {
5057 let handle = client.get_runtime_handle();
5058 handle.block_on(
5059 client
5060 .register_exchange(request,
5061 Box::new(move |_client, event: QueueEvent| {
5062 debug!("register_exchange_async: spawn new task, to call event_callback");
5063 trace!("register_exchange_async: call event_callback");
5064 let queuename = CString::new(event.queuename).unwrap().into_raw();
5065 let correlation_id = CString::new(event.correlation_id).unwrap().into_raw();
5066 let replyto = CString::new(event.replyto).unwrap().into_raw();
5067 let routingkey = CString::new(event.routingkey).unwrap().into_raw();
5068 let exchangename = CString::new(event.exchangename).unwrap().into_raw();
5069 let data = CString::new(event.data).unwrap().into_raw();
5070 let event = Box::new(QueueEventWrapper {
5071 queuename,
5072 correlation_id,
5073 replyto,
5074 routingkey,
5075 exchangename,
5076 data,
5077 request_id
5078 });
5079 event_callback(Box::into_raw(event));
5080 None
5081 }),
5082
5083 )
5084 )
5085 });
5086
5087 debug!("register_exchange_async: parse result");
5088 let response = match result {
5089 Ok(data) => {
5090 let queuename = CString::new(data).unwrap().into_raw();
5091 RegisterExchangeResponseWrapper {
5092 success: true,
5093 queuename,
5094 error: std::ptr::null(),
5095 request_id: options.request_id,
5096 }
5097 }
5098 Err(e) => {
5099 let error_msg = CString::new(format!("RegisterExchange failed: {:?}", e))
5100 .unwrap()
5101 .into_raw();
5102 RegisterExchangeResponseWrapper {
5103 success: false,
5104 queuename: std::ptr::null(),
5105 error: error_msg,
5106 request_id: options.request_id,
5107 }
5108 }
5109 };
5110 Box::into_raw(Box::new(response))
5111}
5112
5113#[no_mangle]
5114#[tracing::instrument(skip_all)]
5115pub extern "C" fn free_register_exchange_response(response: *mut RegisterExchangeResponseWrapper) {
5116 if response.is_null() {
5117 return;
5118 }
5119 unsafe {
5120 if !(*response).error.is_null() {
5121 let _ = CString::from_raw((*response).error as *mut c_char);
5122 }
5123 if !(*response).queuename.is_null() {
5124 let _ = CString::from_raw((*response).queuename as *mut c_char);
5125 }
5126 let _ = Box::from_raw(response);
5127 }
5128}
5129
5130#[repr(C)]
5131#[derive(Debug, Clone)]
5132pub struct QueueEventWrapper {
5133 queuename: *const c_char,
5134 correlation_id: *const c_char,
5135 replyto: *const c_char,
5136 routingkey: *const c_char,
5137 exchangename: *const c_char,
5138 data: *const c_char,
5139 request_id: i32,
5140}
5141impl Default for QueueEventWrapper {
5142 fn default() -> Self {
5143 QueueEventWrapper {
5144 queuename: std::ptr::null(),
5145 correlation_id: std::ptr::null(),
5146 replyto: std::ptr::null(),
5147 routingkey: std::ptr::null(),
5148 exchangename: std::ptr::null(),
5149 data: std::ptr::null(),
5150 request_id: 0,
5151 }
5152 }
5153}
5154
5155#[no_mangle]
5156#[tracing::instrument(skip_all)]
5157pub extern "C" fn next_queue_event (
5158 queuename: *const c_char,
5159) -> *mut QueueEventWrapper {
5160 trace!("unwrap watchid");
5161 let queuename = c_char_to_str(queuename);
5162 trace!("queuename {:}", queuename);
5163 let queuename = queuename.to_string();
5164 trace!("unwrap events");
5165 let mut e = QUEUE_EVENTS.lock().unwrap();
5166 trace!("get queue");
5167 let queue = e.get_mut(&queuename);
5168 match queue {
5169 Some(q) => {
5170 match q.pop_front() {
5171 Some(event) => {
5172 debug!("got event");
5173 let queuename = CString::new(event.queuename).unwrap().into_raw();
5174 let correlation_id = CString::new(event.correlation_id).unwrap().into_raw();
5175 let replyto = CString::new(event.replyto).unwrap().into_raw();
5176 let routingkey = CString::new(event.routingkey).unwrap().into_raw();
5177 let exchangename = CString::new(event.exchangename).unwrap().into_raw();
5178 let data = CString::new(event.data).unwrap().into_raw();
5179 let event = Box::new(QueueEventWrapper {
5180 queuename,
5181 correlation_id,
5182 replyto,
5183 routingkey,
5184 exchangename,
5185 data,
5186 request_id: 0
5187 });
5188 Box::into_raw(event)
5189 }
5190 None => {
5191 trace!("No event");
5192 Box::into_raw(Box::new(QueueEventWrapper::default()))
5193 },
5194 }
5195 },
5196 None => {
5197 debug!("Queue for {:} not found", queuename);
5198 Box::into_raw(Box::new(QueueEventWrapper::default()))
5199 },
5200 }
5201}
5202#[no_mangle]
5203#[tracing::instrument(skip_all)]
5204pub extern "C" fn free_queue_event(response: *mut QueueEventWrapper) {
5205 if response.is_null() {
5206 return;
5207 }
5208 unsafe {
5209 if !(*response).queuename.is_null() {
5210 let _ = CString::from_raw((*response).queuename as *mut c_char);
5211 }
5212 if !(*response).correlation_id.is_null() {
5213 let _ = CString::from_raw((*response).correlation_id as *mut c_char);
5214 }
5215 if !(*response).replyto.is_null() {
5216 let _ = CString::from_raw((*response).replyto as *mut c_char);
5217 }
5218 if !(*response).routingkey.is_null() {
5219 let _ = CString::from_raw((*response).routingkey as *mut c_char);
5220 }
5221 if !(*response).exchangename.is_null() {
5222 let _ = CString::from_raw((*response).exchangename as *mut c_char);
5223 }
5224 if !(*response).data.is_null() {
5225 let _ = CString::from_raw((*response).data as *mut c_char);
5226 }
5227 let _ = Box::from_raw(response);
5228 }
5229}
5230
5231#[repr(C)]
5232pub struct QueueMessageRequestWrapper {
5233 queuename: *const c_char,
5234 correlation_id: *const c_char,
5235 replyto: *const c_char,
5236 routingkey: *const c_char,
5237 exchangename: *const c_char,
5238 data: *const c_char,
5239 striptoken: bool,
5240 expiration: i32,
5241 request_id: i32,
5242}
5243#[repr(C)]
5244pub struct QueueMessageResponseWrapper {
5245 success: bool,
5246 error: *const c_char,
5247}
5248#[no_mangle]
5249#[tracing::instrument(skip_all)]
5250pub extern "C" fn queue_message(
5251 client: *mut ClientWrapper,
5252 options: *mut QueueMessageRequestWrapper,
5253) -> *mut QueueMessageResponseWrapper {
5254 let options = match safe_wrapper(options) {
5255 Some(options) => options,
5256 None => {
5257 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5258 let response = QueueMessageResponseWrapper {
5259 success: false,
5260 error: error_msg,
5261 };
5262 return Box::into_raw(Box::new(response));
5263 }
5264 };
5265 let client_wrapper = match safe_wrapper(client) {
5266 Some(client) => client,
5267 None => {
5268 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5269 let response = QueueMessageResponseWrapper {
5270 success: false,
5271 error: error_msg,
5272 };
5273 return Box::into_raw(Box::new(response));
5274 }
5275 };
5276 let client = client_wrapper.client.clone();
5277 let request = QueueMessageRequest {
5278 queuename: c_char_to_str(options.queuename),
5279 correlation_id: c_char_to_str(options.correlation_id),
5280 replyto: c_char_to_str(options.replyto),
5281 routingkey: c_char_to_str(options.routingkey),
5282 exchangename: c_char_to_str(options.exchangename),
5283 data: c_char_to_str(options.data),
5284 striptoken: options.striptoken,
5285 expiration: options.expiration,
5286 };
5287 if client.is_none() {
5288 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5289 let response = QueueMessageResponseWrapper {
5290 success: false,
5291 error: error_msg,
5292 };
5293 return Box::into_raw(Box::new(response));
5294 }
5295 let client = client.unwrap();
5296 let result = tokio::task::block_in_place(|| {
5297 let handle = client.get_runtime_handle();
5298 handle.block_on(
5299 client
5300 .queue_message(request)
5301 )
5302 });
5303 match result {
5304 Ok(_) => {
5305 let response = QueueMessageResponseWrapper {
5306 success: true,
5307 error: std::ptr::null(),
5308 };
5309 Box::into_raw(Box::new(response))
5310 }
5311 Err(e) => {
5312 let error_msg = CString::new(format!("Queue message failed: {:?}", e))
5313 .unwrap()
5314 .into_raw();
5315 let response = QueueMessageResponseWrapper {
5316 success: false,
5317 error: error_msg,
5318 };
5319 Box::into_raw(Box::new(response))
5320 }
5321 }
5322}
5323#[no_mangle]
5324#[tracing::instrument(skip_all)]
5325pub extern "C" fn free_queue_message_response(response: *mut QueueMessageResponseWrapper) {
5326 if response.is_null() {
5327 return;
5328 }
5329 unsafe {
5330 if !(*response).error.is_null() {
5331 let _ = CString::from_raw((*response).error as *mut c_char);
5332 }
5333 let _ = Box::from_raw(response);
5334 }
5335}
5336
5337#[repr(C)]
5338pub struct UnRegisterQueueResponseWrapper {
5339 success: bool,
5340 error: *const c_char,
5341}
5342#[no_mangle]
5343#[tracing::instrument(skip_all)]
5344pub extern "C" fn unregister_queue(
5345 client: *mut ClientWrapper,
5346 queuename: *const c_char,
5347) -> *mut UnRegisterQueueResponseWrapper {
5348 let client_wrapper = match safe_wrapper(client) {
5349 Some(client) => client,
5350 None => {
5351 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5352 let response = UnRegisterQueueResponseWrapper {
5353 success: false,
5354 error: error_msg,
5355 };
5356 return Box::into_raw(Box::new(response));
5357 }
5358 };
5359 let client = client_wrapper.client.clone();
5360 let queuename = c_char_to_str(queuename);
5361 if client.is_none() {
5362 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5363 let response = UnRegisterQueueResponseWrapper {
5364 success: false,
5365 error: error_msg,
5366 };
5367 return Box::into_raw(Box::new(response));
5368 }
5369 let client = client.unwrap();
5370 let result = tokio::task::block_in_place(|| {
5371 let handle = client.get_runtime_handle();
5372 handle.block_on( client.unregister_queue(&queuename))
5373 });
5374 match result {
5375 Ok(_) => {
5376 let response = UnRegisterQueueResponseWrapper {
5377 success: true,
5378 error: std::ptr::null(),
5379 };
5380 Box::into_raw(Box::new(response))
5381 }
5382 Err(e) => {
5383 let error_msg = CString::new(format!("Unregister queue failed: {:?}", e))
5384 .unwrap()
5385 .into_raw();
5386 let response = UnRegisterQueueResponseWrapper {
5387 success: false,
5388 error: error_msg,
5389 };
5390 Box::into_raw(Box::new(response))
5391 }
5392 }
5393}
5394#[no_mangle]
5395#[tracing::instrument(skip_all)]
5396pub extern "C" fn free_unregister_queue_response(response: *mut UnRegisterQueueResponseWrapper) {
5397 if response.is_null() {
5398 return;
5399 }
5400 unsafe {
5401 if !(*response).error.is_null() {
5402 let _ = CString::from_raw((*response).error as *mut c_char);
5403 }
5404 let _ = Box::from_raw(response);
5405 }
5406}
5407
5408
5409
5410#[repr(C)]
5411#[derive(Debug, Clone)]
5412pub struct WorkitemFileWrapper {
5413 filename: *const c_char,
5414 id: *const c_char,
5415 compressed: bool,
5416 }
5418impl WorkitemFileWrapper {
5419 pub fn new(filename: &str, id: &str, compressed: bool) -> Self {
5420 trace!("filename: {:?}", filename);
5421 let filename = CString::new(filename).unwrap().into_raw();
5422 trace!("filename: {:?}", filename);
5423 trace!("id: {:?}", id);
5424 let id = CString::new(id).unwrap().into_raw();
5425 trace!("id: {:?}", id);
5426 WorkitemFileWrapper {
5428 filename,
5429 id,
5430 compressed,
5432 }
5433 }
5442}
5443
5444#[repr(C)]
5445#[derive(Debug, Clone)]
5446pub struct WorkitemWrapper {
5447 id: *const c_char,
5448 name: *const c_char,
5449 payload: *const c_char,
5450 priority: i32,
5451 nextrun: u64,
5452 lastrun: u64,
5453 files: *const *const WorkitemFileWrapper,
5454 files_len: i32,
5455 state: *const c_char,
5456 wiq: *const c_char,
5457 wiqid: *const c_char,
5458 retries: i32,
5459 username: *const c_char,
5460 success_wiqid: *const c_char,
5461 failed_wiqid: *const c_char,
5462 success_wiq: *const c_char,
5463 failed_wiq: *const c_char,
5464 errormessage: *const c_char,
5465 errorsource: *const c_char,
5466 errortype: *const c_char,
5467}
5468impl WorkitemWrapper {
5469 #[tracing::instrument(skip_all)]
5470 pub fn as_workitem(&self) -> Workitem {
5471 let files_len = self.files_len;
5472 let mut files: Vec<WorkitemFile> = vec![];
5473 if files_len > 0 {
5474 let _files = unsafe { &*self.files };
5475 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
5476 files = _files.iter().map(|f| {
5477 let file = unsafe { &**f };
5478 WorkitemFile {
5479 filename: c_char_to_str(file.filename),
5480 id: c_char_to_str(file.id),
5481 ..Default::default()
5482 }
5485 }).collect();
5486 }
5487 trace!("nextrun: {:?}", self.nextrun);
5488 let mut nextrun = Some(Timestamp::from(
5490 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(self.nextrun)
5491 ));
5492 trace!("nextrun: {:?}", nextrun);
5493 if self.nextrun == 0 {
5494 nextrun = None;
5495 }
5496 trace!("lastrun: {:?}", self.lastrun);
5497 let mut lastrun = Some(Timestamp::from(
5499 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(self.lastrun)
5500 ));
5501 trace!("lastrun: {:?}", lastrun);
5502 if self.lastrun == 0 {
5503 lastrun = None;
5504 }
5505 Workitem {
5506 id: c_char_to_str(self.id),
5507 name: c_char_to_str(self.name),
5508 payload: c_char_to_str(self.payload),
5509 priority: self.priority,
5510 nextrun,
5511 lastrun,
5512 files,
5513 state: c_char_to_str(self.state),
5514 wiq: c_char_to_str(self.wiq),
5515 wiqid: c_char_to_str(self.wiqid),
5516 retries: self.retries,
5517 username: c_char_to_str(self.username),
5518 success_wiqid: c_char_to_str(self.success_wiqid),
5519 failed_wiqid: c_char_to_str(self.failed_wiqid),
5520 success_wiq: c_char_to_str(self.success_wiq),
5521 failed_wiq: c_char_to_str(self.failed_wiq),
5522 errormessage: c_char_to_str(self.errormessage),
5523 errorsource: c_char_to_str(self.errorsource),
5524 errortype: c_char_to_str(self.errortype),
5525 }
5526 }
5527}
5528#[tracing::instrument(skip_all)]
5529pub fn wrap_workitem(workitem: Workitem ) -> WorkitemWrapper {
5530 trace!("parse workitem: {:?}", workitem);
5531 let id = CString::new(workitem.id).unwrap().into_raw();
5532 let name = CString::new(workitem.name).unwrap().into_raw();
5533 let payload = CString::new(workitem.payload).unwrap().into_raw();
5534 let state = CString::new(workitem.state).unwrap().into_raw();
5535 let wiq = CString::new(workitem.wiq).unwrap().into_raw();
5536 let wiqid = CString::new(workitem.wiqid).unwrap().into_raw();
5537 let username = CString::new(workitem.username).unwrap().into_raw();
5538 let success_wiqid = CString::new(workitem.success_wiqid).unwrap().into_raw();
5539 let failed_wiqid = CString::new(workitem.failed_wiqid).unwrap().into_raw();
5540 let success_wiq = CString::new(workitem.success_wiq).unwrap().into_raw();
5541 let failed_wiq = CString::new(workitem.failed_wiq).unwrap().into_raw();
5542 let errormessage = CString::new(workitem.errormessage).unwrap().into_raw();
5543 let errorsource = CString::new(workitem.errorsource).unwrap().into_raw();
5544 let errortype = CString::new(workitem.errortype).unwrap().into_raw();
5545 let mut files: Vec<*const WorkitemFileWrapper> = vec![];
5546 for f in &workitem.files {
5547 let file = Box::into_raw(Box::new(WorkitemFileWrapper::new(&f.filename, &f.id, f.compressed)));
5559 files.push(file);
5560 }
5561 trace!("files: {:?} at {:?}", files.len(), files);
5562 trace!("read nextrun");
5563 let nextrun = workitem.nextrun.map(|t| t.seconds as u64).unwrap_or(0);
5564 trace!("nextrun: {:?}", nextrun);
5565 let lastrun = workitem.lastrun.map(|t| t.seconds as u64).unwrap_or(0);
5566 trace!("lastrun: {:?}", lastrun);
5567 let _files = files.as_ptr();
5568 trace!("files: {:?}", files);
5569 let files_len = workitem.files.len() as i32;
5570 trace!("files_len: {:?}", files_len);
5571 let workitem = WorkitemWrapper {
5572 id,
5573 name,
5574 payload,
5575 priority: workitem.priority,
5576 nextrun,
5577 lastrun,
5578 files: _files,
5579 files_len,
5580 state,
5581 wiq,
5582 wiqid,
5583 retries: workitem.retries,
5584 username,
5585 success_wiqid,
5586 failed_wiqid,
5587 success_wiq,
5588 failed_wiq,
5589 errormessage,
5590 errorsource,
5591 errortype,
5592 };
5593 trace!("forget files");
5594 std::mem::forget(files);
5595 trace!("return workitem");
5596 workitem
5597}
5598#[repr(C)]
5599#[derive(Debug, Clone)]
5600pub struct PushWorkitemRequestWrapper {
5601 wiq: *const c_char,
5602 wiqid: *const c_char,
5603 name: *const c_char,
5604 payload: *const c_char,
5605 nextrun: u64,
5606 success_wiqid: *const c_char,
5607 failed_wiqid: *const c_char,
5608 success_wiq: *const c_char,
5609 failed_wiq: *const c_char,
5610 priority: i32,
5611 files: *const *const WorkitemFileWrapper,
5612 files_len: i32,
5613 request_id: i32
5614}
5615#[repr(C)]
5616#[derive(Debug, Clone)]
5617pub struct PushWorkitemResponseWrapper {
5618 success: bool,
5619 error: *const c_char,
5620 workitem: *const WorkitemWrapper,
5621 request_id: i32
5622}
5623#[no_mangle]
5624#[tracing::instrument(skip_all)]
5625pub extern "C" fn push_workitem(
5626 client: *mut ClientWrapper,
5627 options: *mut PushWorkitemRequestWrapper,
5628) -> *mut PushWorkitemResponseWrapper {
5629 let options = match safe_wrapper(options) {
5630 Some(options) => options,
5631 None => {
5632 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5633 let response = PushWorkitemResponseWrapper {
5634 success: false,
5635 error: error_msg,
5636 workitem: std::ptr::null(),
5637 request_id: 0
5638 };
5639 return Box::into_raw(Box::new(response));
5640 }
5641 };
5642 let client_wrapper = match safe_wrapper(client) {
5643 Some(client) => client,
5644 None => {
5645 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5646 let response = PushWorkitemResponseWrapper {
5647 success: false,
5648 error: error_msg,
5649 workitem: std::ptr::null(),
5650 request_id: options.request_id
5651 };
5652 return Box::into_raw(Box::new(response));
5653 }
5654 };
5655 let client = client_wrapper.client.clone();
5656 let files_len = options.files_len;
5657 debug!("files_len: {:?}", files_len);
5658 let mut files: Vec<WorkitemFile> = vec![];
5659 if files_len > 0 {
5660 debug!("get files of options");
5661 let _files = unsafe { &*options.files };
5662 debug!("slice files");
5663 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
5664 debug!("loop files");
5665 files = _files.iter().map(|f| {
5666 debug!("process a file");
5667 let file = unsafe { &**f };
5668 debug!("create WorkitemFile instance");
5669 let filename = c_char_to_str(file.filename);
5670 trace!("filename: {:?}", filename);
5671 let id = c_char_to_str(file.id);
5672 trace!("id: {:?}", id);
5673 trace!("compressed: {:?}", file.compressed);
5674 WorkitemFile {
5675 filename,
5676 id,
5677 compressed: file.compressed,
5678 ..Default::default()
5679 }
5681 }).collect();
5682 }
5683 trace!("nextrun: {:?}", options.nextrun);
5684 let mut nextrun = Some(Timestamp::from(
5686 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(options.nextrun as u64)
5687 ));
5688 trace!("nextrun: {:?}", nextrun);
5689 if options.nextrun == 0 {
5690 nextrun = None;
5691 }
5692 let request = PushWorkitemRequest {
5693 wiq: c_char_to_str(options.wiq),
5694 wiqid: c_char_to_str(options.wiqid),
5695 name: c_char_to_str(options.name),
5696 payload: c_char_to_str(options.payload),
5697 nextrun,
5698 success_wiqid: c_char_to_str(options.success_wiqid),
5699 failed_wiqid: c_char_to_str(options.failed_wiqid),
5700 success_wiq: c_char_to_str(options.success_wiq),
5701 failed_wiq: c_char_to_str(options.failed_wiq),
5702 priority: options.priority,
5703 files,
5704 };
5705 if client.is_none() {
5706 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5707 let response = PushWorkitemResponseWrapper {
5708 success: false,
5709 error: error_msg,
5710 workitem: std::ptr::null(),
5711 request_id: options.request_id
5712 };
5713 return Box::into_raw(Box::new(response));
5714 }
5715 let client = client.unwrap();
5716 let result = tokio::task::block_in_place(|| {
5717 let handle = client.get_runtime_handle();
5718 handle.block_on(client
5719 .push_workitem(request)
5720 )
5721 });
5722
5723 match result {
5724 Ok(resp) => {
5725 Box::into_raw(Box::new(match resp.workitem {
5726 Some(workitem) => {
5727 let workitem = wrap_workitem(workitem);
5728 PushWorkitemResponseWrapper {
5729 success: true,
5730 error: std::ptr::null(),
5731 workitem: Box::into_raw(Box::new(workitem)),
5732 request_id: options.request_id
5733 }
5734 }
5735 None => {
5736 let error_msg = CString::new("Push workitem failed: workitem not found").unwrap().into_raw();
5737 PushWorkitemResponseWrapper {
5738 success: false,
5739 error: error_msg,
5740 workitem: std::ptr::null(),
5741 request_id: options.request_id
5742 }
5743 }
5744 }))
5745 }
5746 Err(e) => {
5747 let error_msg = CString::new(format!("Push workitem failed: {:?}", e))
5748 .unwrap()
5749 .into_raw();
5750 Box::into_raw(Box::new(PushWorkitemResponseWrapper {
5751 success: false,
5752 error: error_msg,
5753 workitem: std::ptr::null(),
5754 request_id: options.request_id
5755 }))
5756 }
5757 }
5758}
5759#[no_mangle]
5760#[tracing::instrument(skip_all)]
5761pub extern "C" fn push_workitem_async(
5762 client: *mut ClientWrapper,
5763 options: *mut PushWorkitemRequestWrapper,
5764 callback: extern "C" fn(*mut PushWorkitemResponseWrapper),
5765) {
5766 let options = match safe_wrapper(options) {
5767 Some(options) => options,
5768 None => {
5769 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5770 let response = PushWorkitemResponseWrapper {
5771 success: false,
5772 error: error_msg,
5773 workitem: std::ptr::null(),
5774 request_id: 0
5775 };
5776 return callback(Box::into_raw(Box::new(response)));
5777 }
5778 };
5779 let client_wrapper = match safe_wrapper(client) {
5780 Some(client) => client,
5781 None => {
5782 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5783 let response = PushWorkitemResponseWrapper {
5784 success: false,
5785 error: error_msg,
5786 workitem: std::ptr::null(),
5787 request_id: options.request_id
5788 };
5789 return callback(Box::into_raw(Box::new(response)));
5790 }
5791 };
5792 let client = client_wrapper.client.clone();
5793 let files_len = options.files_len;
5794 debug!("files_len: {:?}", files_len);
5795 let mut files: Vec<WorkitemFile> = vec![];
5796 if files_len > 0 {
5797 debug!("get files of options");
5798 let _files = unsafe { &*options.files };
5799 debug!("slice files");
5800 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
5801 debug!("loop files");
5802 files = _files.iter().map(|f| {
5803 debug!("process a file");
5804 let file = unsafe { &**f };
5805 debug!("create WorkitemFile instance 2");
5806 let filename = c_char_to_str(file.filename);
5807 debug!("filename: {:?}", filename);
5808 let id = c_char_to_str(file.id);
5809 debug!("id: {:?}", id);
5810 let compressed = file.compressed;
5811 debug!("compressed: {:?}", compressed);
5812 WorkitemFile {
5813 filename: c_char_to_str(file.filename),
5814 id: c_char_to_str(file.id),
5815 compressed: file.compressed,
5816 ..Default::default()
5817 }
5819 }).collect();
5820 }
5821 trace!("nextrun: {:?}", options.nextrun);
5822 let mut nextrun = Some(Timestamp::from(
5824 std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(options.nextrun as u64)
5825 ));
5826 trace!("nextrun: {:?}", nextrun);
5827 if options.nextrun == 0 {
5828 nextrun = None;
5829 }
5830 let request = PushWorkitemRequest {
5831 wiq: c_char_to_str(options.wiq),
5832 wiqid: c_char_to_str(options.wiqid),
5833 name: c_char_to_str(options.name),
5834 payload: c_char_to_str(options.payload),
5835 nextrun,
5836 success_wiqid: c_char_to_str(options.success_wiqid),
5837 failed_wiqid: c_char_to_str(options.failed_wiqid),
5838 success_wiq: c_char_to_str(options.success_wiq),
5839 failed_wiq: c_char_to_str(options.failed_wiq),
5840 priority: options.priority,
5841 files,
5842 };
5843 if client.is_none() {
5844 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5845 let response = PushWorkitemResponseWrapper {
5846 success: false,
5847 error: error_msg,
5848 workitem: std::ptr::null(),
5849 request_id: options.request_id
5850 };
5851 return callback(Box::into_raw(Box::new(response)));
5852 }
5853 let client = client.unwrap();
5854 let handle = client.get_runtime_handle();
5855 let request_id = options.request_id;
5856 handle.spawn(async move {
5857 let result = client
5858 .push_workitem(request)
5859 .await;
5860 let response = match result {
5861 Ok(resp) => {
5862 match resp.workitem {
5863 Some(workitem) => {
5864 let workitem = wrap_workitem(workitem);
5865 PushWorkitemResponseWrapper {
5866 success: true,
5867 error: std::ptr::null(),
5868 workitem: Box::into_raw(Box::new(workitem)),
5869 request_id,
5870 }
5871 }
5872 None => {
5873 let error_msg = CString::new("Push workitem failed: workitem not found").unwrap().into_raw();
5874 PushWorkitemResponseWrapper {
5875 success: false,
5876 error: error_msg,
5877 workitem: std::ptr::null(),
5878 request_id,
5879 }
5880 }
5881 }
5882 }
5883 Err(e) => {
5884 let error_msg = CString::new(format!("Push workitem failed: {:?}", e))
5885 .unwrap()
5886 .into_raw();
5887 PushWorkitemResponseWrapper {
5888 success: false,
5889 error: error_msg,
5890 workitem: std::ptr::null(),
5891 request_id,
5892 }
5893 }
5894 };
5895 let response = Box::into_raw(Box::new(response));
5896 callback(response);
5897 });
5898
5899
5900}
5901
5902#[no_mangle]
5903#[tracing::instrument(skip_all)]
5904pub extern "C" fn free_push_workitem_response(response: *mut PushWorkitemResponseWrapper) {
5905 if response.is_null() {
5906 return;
5907 }
5908 unsafe {
5909 if !(*response).error.is_null() {
5910 let _ = CString::from_raw((*response).error as *mut c_char);
5911 }
5912 if !(*response).workitem.is_null() {
5913 free_workitem((*response).workitem as *mut WorkitemWrapper);
5914 }
5915 let _ = Box::from_raw(response);
5916 }
5917}
5918
5919#[repr(C)]
5920#[derive(Debug, Clone)]
5921pub struct PopWorkitemRequestWrapper {
5922 wiq: *const c_char,
5923 wiqid: *const c_char,
5924 request_id: i32
5925 }
5928#[repr(C)]
5929#[derive(Debug, Clone)]
5930pub struct PopWorkitemResponseWrapper {
5931 success: bool,
5932 error: *const c_char,
5933 workitem: *const WorkitemWrapper,
5934 request_id: i32
5935}
5936#[no_mangle]
5937#[tracing::instrument(skip_all)]
5938pub extern "C" fn pop_workitem (
5939 client: *mut ClientWrapper,
5940 options: *mut PopWorkitemRequestWrapper,
5941 downloadfolder: *const c_char,
5942) -> *mut PopWorkitemResponseWrapper {
5943 let options = match safe_wrapper(options) {
5944 Some(options) => options,
5945 None => {
5946 let error_msg = CString::new("Invalid options").unwrap().into_raw();
5947 let response = PopWorkitemResponseWrapper {
5948 success: false,
5949 error: error_msg,
5950 workitem: std::ptr::null(),
5951 request_id: 0
5952 };
5953 return Box::into_raw(Box::new(response));
5954 }
5955 };
5956 let client_wrapper = match safe_wrapper(client) {
5957 Some(client) => client,
5958 None => {
5959 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5960 let response = PopWorkitemResponseWrapper {
5961 success: false,
5962 error: error_msg,
5963 workitem: std::ptr::null(),
5964 request_id: options.request_id
5965 };
5966 return Box::into_raw(Box::new(response));
5967 }
5968 };
5969 let client = client_wrapper.client.clone();
5970 let request = PopWorkitemRequest {
5971 wiq: c_char_to_str(options.wiq),
5972 wiqid: c_char_to_str(options.wiqid),
5973 ..Default::default()
5974 };
5975 if client.is_none() {
5976 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
5977 let response = PopWorkitemResponseWrapper {
5978 success: false,
5979 error: error_msg,
5980 workitem: std::ptr::null(),
5981 request_id: options.request_id
5982 };
5983 return Box::into_raw(Box::new(response));
5984 }
5985 let downloadfolder = c_char_to_str(downloadfolder);
5986 let mut _downloadfolder = Some(downloadfolder.as_str());
5987 if downloadfolder.is_empty() {
5988 _downloadfolder = None;
5989 }
5990 let client = client.unwrap();
5991 let result = tokio::task::block_in_place(|| {
5992 let handle = client.get_runtime_handle();
5993 handle.block_on(client
5994 .pop_workitem(request, _downloadfolder)
5995 )
5996 });
5997 debug!("pop_workitem completed, parse result");
5998
5999 match result {
6000 Ok(data) => {
6001 let workitem = match data.workitem {
6002 Some(workitem) => {
6003 let workitem = wrap_workitem(workitem);
6004 trace!("wrap workitem");
6005 Box::into_raw(Box::new(workitem))
6006 },
6007 None => {
6008 std::ptr::null()
6009 }
6010 };
6011 Box::into_raw(Box::new(PopWorkitemResponseWrapper {
6012 success: true,
6013 error: std::ptr::null(),
6014 workitem,
6015 request_id: options.request_id
6016 }))
6017 }
6018 Err(e) => {
6019 let error_msg = CString::new(format!("Pop workitem failed: {:?}", e))
6020 .unwrap()
6021 .into_raw();
6022 Box::into_raw(Box::new(PopWorkitemResponseWrapper {
6023 success: false,
6024 error: error_msg,
6025 workitem: std::ptr::null(),
6026 request_id: options.request_id
6027 }))
6028 }
6029 }
6030}
6031#[no_mangle]
6032#[tracing::instrument(skip_all)]
6033pub extern "C" fn pop_workitem_async (
6034 client: *mut ClientWrapper,
6035 options: *mut PopWorkitemRequestWrapper,
6036 downloadfolder: *const c_char,
6037 callback: extern "C" fn(*mut PopWorkitemResponseWrapper),
6038) {
6039 let options = match safe_wrapper(options) {
6040 Some(options) => options,
6041 None => {
6042 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6043 let response = PopWorkitemResponseWrapper {
6044 success: false,
6045 error: error_msg,
6046 workitem: std::ptr::null(),
6047 request_id: 0
6048 };
6049 return callback(Box::into_raw(Box::new(response)));
6050 }
6051 };
6052 let client_wrapper = match safe_wrapper(client) {
6053 Some(client) => client,
6054 None => {
6055 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6056 let response = PopWorkitemResponseWrapper {
6057 success: false,
6058 error: error_msg,
6059 workitem: std::ptr::null(),
6060 request_id: options.request_id
6061 };
6062 return callback(Box::into_raw(Box::new(response)));
6063 }
6064 };
6065 let client = client_wrapper.client.clone();
6066 let request = PopWorkitemRequest {
6067 wiq: c_char_to_str(options.wiq),
6068 wiqid: c_char_to_str(options.wiqid),
6069 ..Default::default()
6070 };
6071 if client.is_none() {
6072 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6073 let response = PopWorkitemResponseWrapper {
6074 success: false,
6075 error: error_msg,
6076 workitem: std::ptr::null(),
6077 request_id: options.request_id
6078 };
6079 return callback(Box::into_raw(Box::new(response)));
6080 }
6081 let downloadfolder = c_char_to_str(downloadfolder);
6082 let client = client.unwrap();
6083 let handle = client.get_runtime_handle();
6084 let request_id = options.request_id;
6085 handle.spawn(async move {
6086 let mut _downloadfolder = Some(downloadfolder.as_str());
6087 if downloadfolder.is_empty() {
6088 _downloadfolder = None;
6089 }
6090
6091 let result = client
6092 .pop_workitem(request, _downloadfolder)
6093 .await;
6094 let response = match result {
6095 Ok(data) => {
6096 let workitem = match data.workitem {
6097 Some(workitem) => {
6098 let workitem = wrap_workitem(workitem);
6099 trace!("wrap workitem");
6100 Box::into_raw(Box::new(workitem))
6101 },
6102 None => {
6103 std::ptr::null()
6104 }
6105 };
6106 let response = PopWorkitemResponseWrapper {
6107 success: true,
6108 error: std::ptr::null(),
6109 workitem,
6110 request_id: request_id
6111 };
6112 Box::into_raw(Box::new(response))
6113 }
6114 Err(e) => {
6115 let error_msg = CString::new(format!("Pop workitem failed: {:?}", e))
6116 .unwrap()
6117 .into_raw();
6118 let response = PopWorkitemResponseWrapper {
6119 success: false,
6120 error: error_msg,
6121 workitem: std::ptr::null(),
6122 request_id: request_id
6123 };
6124 Box::into_raw(Box::new(response))
6125 }
6126 };
6127 trace!("callback with result");
6128 callback(response);
6129 });
6130}
6131#[no_mangle]
6132#[tracing::instrument(skip_all)]
6133pub extern "C" fn free_pop_workitem_response(response: *mut PopWorkitemResponseWrapper) {
6134 if response.is_null() {
6135 return;
6136 }
6137 unsafe {
6138 if !(*response).error.is_null() {
6139 let _ = CString::from_raw((*response).error as *mut c_char);
6140 }
6141 if !(*response).workitem.is_null() {
6142 free_workitem((*response).workitem as *mut WorkitemWrapper);
6143 }
6144 let _ = Box::from_raw(response);
6145 }
6146}
6147#[no_mangle]
6148#[tracing::instrument(skip_all)]
6149pub extern "C" fn free_workitem_file(file: *mut WorkitemFileWrapper) {
6150 if file.is_null() {
6151 return;
6152 }
6153 unsafe {
6154 if !(*file).filename.is_null() {
6155 let _ = CString::from_raw((*file).filename as *mut c_char);
6156 }
6157 if !(*file).id.is_null() {
6158 let _ = CString::from_raw((*file).id as *mut c_char);
6159 }
6160 let _ = Box::from_raw(file);
6161 }
6162}
6163#[no_mangle]
6164#[tracing::instrument(skip_all)]
6165pub extern "C" fn free_workitem(workitem: *mut WorkitemWrapper) {
6166 if workitem.is_null() {
6167 return;
6168 }
6169 unsafe {
6170 if !(*workitem).id.is_null() {
6171 let _ = CString::from_raw((*workitem).id as *mut c_char);
6172 }
6173 if !(*workitem).name.is_null() {
6174 let _ = CString::from_raw((*workitem).name as *mut c_char);
6175 }
6176 if !(*workitem).payload.is_null() {
6177 let _ = CString::from_raw((*workitem).payload as *mut c_char);
6178 }
6179 if !(*workitem).state.is_null() {
6180 let _ = CString::from_raw((*workitem).state as *mut c_char);
6181 }
6182 if !(*workitem).wiq.is_null() {
6183 let _ = CString::from_raw((*workitem).wiq as *mut c_char);
6184 }
6185 if !(*workitem).wiqid.is_null() {
6186 let _ = CString::from_raw((*workitem).wiqid as *mut c_char);
6187 }
6188 if !(*workitem).username.is_null() {
6189 let _ = CString::from_raw((*workitem).username as *mut c_char);
6190 }
6191 if !(*workitem).success_wiqid.is_null() {
6192 let _ = CString::from_raw((*workitem).success_wiqid as *mut c_char);
6193 }
6194 if !(*workitem).failed_wiqid.is_null() {
6195 let _ = CString::from_raw((*workitem).failed_wiqid as *mut c_char);
6196 }
6197 if !(*workitem).success_wiq.is_null() {
6198 let _ = CString::from_raw((*workitem).success_wiq as *mut c_char);
6199 }
6200 if !(*workitem).failed_wiq.is_null() {
6201 let _ = CString::from_raw((*workitem).failed_wiq as *mut c_char);
6202 }
6203 if !(*workitem).errormessage.is_null() {
6204 let _ = CString::from_raw((*workitem).errormessage as *mut c_char);
6205 }
6206 if !(*workitem).errorsource.is_null() {
6207 let _ = CString::from_raw((*workitem).errorsource as *mut c_char);
6208 }
6209 if !(*workitem).errortype.is_null() {
6210 let _ = CString::from_raw((*workitem).errortype as *mut c_char);
6211 }
6212
6213 if !(*workitem).files.is_null() && (*workitem).files_len > 0 {
6215 for i in 0..(*workitem).files_len as isize {
6216 let file_ptr = *(*workitem).files.offset(i);
6217 if !file_ptr.is_null() {
6218 free_workitem_file(file_ptr as *mut WorkitemFileWrapper);
6219 }
6220 }
6221 let _ = Box::from_raw((*workitem).files as *mut *const WorkitemFileWrapper);
6223 }
6224 let _ = Box::from_raw(workitem); }
6226}
6227
6228
6229#[no_mangle]
6230#[tracing::instrument(skip_all)]
6231pub extern "C" fn pop_workitem2_async (
6232 _client: *mut ClientWrapper,
6233 _options: *mut PopWorkitemRequestWrapper,
6234 _downloadfolder: *const c_char,
6235 request_id: i32,
6236 callback: extern "C" fn(*mut PopWorkitemResponseWrapper),
6237) {
6238 callback(Box::into_raw(Box::new(PopWorkitemResponseWrapper {
6239 success: true,
6240 error: std::ptr::null(),
6241 workitem: std::ptr::null(),
6242 request_id: request_id
6243 })));
6244}
6245
6246#[repr(C)]
6247#[derive(Debug, Clone)]
6248pub struct UpdateWorkitemRequestWrapper {
6249 workitem: *const WorkitemWrapper,
6250 ignoremaxretries: bool,
6251 files: *const *const WorkitemFileWrapper,
6252 files_len: i32,
6253 request_id: i32
6254}
6255#[repr(C)]
6256#[derive(Debug, Clone)]
6257pub struct UpdateWorkitemResponseWrapper {
6258 success: bool,
6259 error: *const c_char,
6260 workitem: *const WorkitemWrapper,
6261 request_id: i32
6262}
6263#[no_mangle]
6264#[tracing::instrument(skip_all)]
6265pub extern "C" fn update_workitem (
6266 client: *mut ClientWrapper,
6267 options: *mut UpdateWorkitemRequestWrapper,
6268) -> *mut UpdateWorkitemResponseWrapper {
6269 let options = match safe_wrapper(options) {
6270 Some(options) => options,
6271 None => {
6272 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6273 let response = UpdateWorkitemResponseWrapper {
6274 success: false,
6275 error: error_msg,
6276 workitem: std::ptr::null(),
6277 request_id: 0
6278 };
6279 return Box::into_raw(Box::new(response));
6280 }
6281 };
6282 let client_wrapper = match safe_wrapper(client) {
6283 Some(client) => client,
6284 None => {
6285 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6286 let response = UpdateWorkitemResponseWrapper {
6287 success: false,
6288 error: error_msg,
6289 workitem: std::ptr::null(),
6290 request_id: options.request_id
6291 };
6292 return Box::into_raw(Box::new(response));
6293 }
6294 };
6295 trace!("grab references");
6296 let client = client_wrapper.client.clone();
6297 let files_len = options.files_len;
6298 debug!("files_len: {:?}", files_len);
6299 let mut files: Vec<WorkitemFile> = vec![];
6300 if files_len > 0 {
6301 debug!("get files of options");
6302 let _files = unsafe { &*options.files };
6303 debug!("slice files");
6304 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
6305 debug!("loop files");
6306 files = _files.iter().map(|f| {
6307 debug!("process a file");
6308 let file = unsafe { &**f };
6309 debug!("create WorkitemFile instance 2");
6310 let filename = c_char_to_str(file.filename);
6311 debug!("filename: {:?}", filename);
6312 let id = c_char_to_str(file.id);
6313 debug!("id: {:?}", id);
6314 let compressed = file.compressed;
6315 debug!("compressed: {:?}", compressed);
6316 WorkitemFile {
6317 filename: c_char_to_str(file.filename),
6318 id: c_char_to_str(file.id),
6319 compressed: file.compressed,
6320 ..Default::default()
6321 }
6323 }).collect();
6324 }
6325 debug!("unwrap workitem");
6326 let workitem = unsafe { &*options.workitem };
6327 debug!("convert workitem wrapper to workitem");
6328 let workitem = workitem.as_workitem();
6329 let request = UpdateWorkitemRequest {
6330 workitem: Some(workitem),
6331 ignoremaxretries: options.ignoremaxretries,
6332 files,
6333 };
6334
6335 if client.is_none() {
6336 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6337 let response = UpdateWorkitemResponseWrapper {
6338 success: false,
6339 error: error_msg,
6340 workitem: std::ptr::null(),
6341 request_id: options.request_id
6342 };
6343 return Box::into_raw(Box::new(response));
6344 }
6345 let client = client.unwrap();
6346 let result = tokio::task::block_in_place(|| {
6347 let handle = client.get_runtime_handle();
6348 handle.block_on(client
6349 .update_workitem(request)
6350 )
6351 });
6352
6353 match result {
6354 Ok(resp) => {
6355 Box::into_raw(Box::new(match resp.workitem {
6356 Some(workitem) => {
6357 let workitem = wrap_workitem(workitem);
6358 UpdateWorkitemResponseWrapper {
6359 success: true,
6360 error: std::ptr::null(),
6361 workitem: Box::into_raw(Box::new(workitem)),
6362 request_id: options.request_id
6363 }
6364 }
6365 None => {
6366 let error_msg = CString::new("Update workitem failed: workitem not found").unwrap().into_raw();
6367 UpdateWorkitemResponseWrapper {
6368 success: false,
6369 error: error_msg,
6370 workitem: std::ptr::null(),
6371 request_id: options.request_id
6372 }
6373 }
6374 }))
6375 }
6376 Err(e) => {
6377 let error_msg = CString::new(format!("Update workitem failed: {:?}", e))
6378 .unwrap()
6379 .into_raw();
6380 Box::into_raw(Box::new(UpdateWorkitemResponseWrapper {
6381 success: false,
6382 error: error_msg,
6383 workitem: std::ptr::null(),
6384 request_id: options.request_id
6385 }))
6386 }
6387 }
6388}
6389#[no_mangle]
6390#[tracing::instrument(skip_all)]
6391pub extern "C" fn update_workitem_async (
6392 client: *mut ClientWrapper,
6393 options: *mut UpdateWorkitemRequestWrapper,
6394 callback: extern "C" fn(*mut UpdateWorkitemResponseWrapper),
6395) {
6396 let options = match safe_wrapper(options) {
6397 Some(options) => options,
6398 None => {
6399 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6400 let response = UpdateWorkitemResponseWrapper {
6401 success: false,
6402 error: error_msg,
6403 workitem: std::ptr::null(),
6404 request_id: 0
6405 };
6406 return callback(Box::into_raw(Box::new(response)));
6407 }
6408 };
6409 let client_wrapper = match safe_wrapper(client) {
6410 Some(client) => client,
6411 None => {
6412 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6413 let response = UpdateWorkitemResponseWrapper {
6414 success: false,
6415 error: error_msg,
6416 workitem: std::ptr::null(),
6417 request_id: options.request_id
6418 };
6419 return callback(Box::into_raw(Box::new(response)));
6420 }
6421 };
6422 trace!("grab references");
6423 let client = client_wrapper.client.clone();
6424 let files_len = options.files_len;
6425 debug!("files_len: {:?}", files_len);
6426 let mut files: Vec<WorkitemFile> = vec![];
6427 if files_len > 0 {
6428 debug!("get files of options");
6429 let _files = unsafe { &*options.files };
6430 debug!("slice files");
6431 let _files = unsafe { std::slice::from_raw_parts(_files, files_len.try_into().unwrap()) };
6432 debug!("loop files");
6433 files = _files.iter().map(|f| {
6434 debug!("process a file");
6435 let file = unsafe { &**f };
6436 debug!("create WorkitemFile instance 2");
6437 let filename = c_char_to_str(file.filename);
6438 debug!("filename: {:?}", filename);
6439 let id = c_char_to_str(file.id);
6440 debug!("id: {:?}", id);
6441 let compressed = file.compressed;
6442 debug!("compressed: {:?}", compressed);
6443 WorkitemFile {
6444 filename: c_char_to_str(file.filename),
6445 id: c_char_to_str(file.id),
6446 compressed: file.compressed,
6447 ..Default::default()
6448 }
6450 }).collect();
6451 }
6452 debug!("unwrap workitem");
6453 let workitem = unsafe { &*options
6454 .workitem };
6455
6456 debug!("convert workitem wrapper to workitem");
6457 let workitem = workitem.as_workitem();
6458 let request = UpdateWorkitemRequest {
6459 workitem: Some(workitem),
6460 ignoremaxretries: options.ignoremaxretries,
6461 files,
6462 };
6463
6464 if client.is_none() {
6465 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6466 let response = UpdateWorkitemResponseWrapper {
6467 success: false,
6468 error: error_msg,
6469 workitem: std::ptr::null(),
6470 request_id: options.request_id
6471 };
6472 return callback(Box::into_raw(Box::new(response)));
6473 }
6474 let client = client.unwrap();
6475 let handle = client.get_runtime_handle();
6476 let request_id = options.request_id;
6477 handle.spawn(async move {
6478 let result = client
6479 .update_workitem(request)
6480 .await;
6481 let response = match result {
6482 Ok(resp) => {
6483 let response = match resp.workitem {
6484 Some(workitem) => {
6485 let workitem = wrap_workitem(workitem);
6486 UpdateWorkitemResponseWrapper {
6487 success: true,
6488 error: std::ptr::null(),
6489 workitem: Box::into_raw(Box::new(workitem)),
6490 request_id,
6491 }
6492 }
6493 None => {
6494 let error_msg = CString::new("Update workitem failed: workitem not found").unwrap().into_raw();
6495 UpdateWorkitemResponseWrapper {
6496 success: false,
6497 error: error_msg,
6498 workitem: std::ptr::null(),
6499 request_id,
6500 }
6501 }
6502 };
6503 Box::into_raw(Box::new(response))
6504 }
6505 Err(e) => {
6506 let error_msg = CString::new(format!("Update workitem failed: {:?}", e))
6507 .unwrap()
6508 .into_raw();
6509 Box::into_raw(Box::new(UpdateWorkitemResponseWrapper {
6510 success: false,
6511 error: error_msg,
6512 workitem: std::ptr::null(),
6513 request_id,
6514 }))
6515 }
6516 };
6517 callback(response);
6518 });
6519}
6520#[no_mangle]
6521#[tracing::instrument(skip_all)]
6522pub extern "C" fn free_update_workitem_response(response: *mut UpdateWorkitemResponseWrapper) {
6523 if response.is_null() {
6524 return;
6525 }
6526 unsafe {
6527 if !(*response).error.is_null() {
6528 let _ = CString::from_raw((*response).error as *mut c_char);
6529 }
6530 if !(*response).workitem.is_null() {
6531 free_workitem((*response).workitem as *mut WorkitemWrapper);
6532 }
6533 let _ = Box::from_raw(response);
6534 }
6535}
6536
6537#[repr(C)]
6538#[derive(Debug, Clone)]
6539pub struct DeleteWorkitemRequestWrapper {
6540 id: *const c_char,
6541 request_id: i32
6542}
6543#[repr(C)]
6544#[derive(Debug, Clone)]
6545pub struct DeleteWorkitemResponseWrapper {
6546 success: bool,
6547 error: *const c_char,
6548 request_id: i32
6549}
6550#[no_mangle]
6551#[tracing::instrument(skip_all)]
6552pub extern "C" fn delete_workitem(
6553 client: *mut ClientWrapper,
6554 options: *mut DeleteWorkitemRequestWrapper,
6555) -> *mut DeleteWorkitemResponseWrapper {
6556 let options = match safe_wrapper(options) {
6557 Some(options) => options,
6558 None => {
6559 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6560 let response = DeleteWorkitemResponseWrapper {
6561 success: false,
6562 error: error_msg,
6563 request_id: 0
6564 };
6565 return Box::into_raw(Box::new(response));
6566 }
6567 };
6568 let client_wrapper = match safe_wrapper(client) {
6569 Some(client) => client,
6570 None => {
6571 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6572 let response = DeleteWorkitemResponseWrapper {
6573 success: false,
6574 error: error_msg,
6575 request_id: options.request_id
6576 };
6577 return Box::into_raw(Box::new(response));
6578 }
6579 };
6580 let client = client_wrapper.client.clone();
6581 let request = DeleteWorkitemRequest {
6582 id: c_char_to_str(options.id),
6583 };
6584 if client.is_none() {
6585 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6586 let response = DeleteWorkitemResponseWrapper {
6587 success: false,
6588 error: error_msg,
6589 request_id: options.request_id
6590 };
6591 return Box::into_raw(Box::new(response));
6592 }
6593 let client = client.unwrap();
6594 let result = tokio::task::block_in_place(|| {
6595 let handle = client.get_runtime_handle();
6596 handle.block_on(client
6597 .delete_workitem(request)
6598 )
6599 });
6600
6601 let response = match result {
6602 Ok(_) => {
6603 let response = DeleteWorkitemResponseWrapper {
6604 success: true,
6605 error: std::ptr::null(),
6606 request_id: options.request_id
6607 };
6608 Box::into_raw(Box::new(response))
6609 }
6610 Err(e) => {
6611 let error_msg = CString::new(format!("Delete workitem failed: {:?}", e))
6612 .unwrap()
6613 .into_raw();
6614 let response = DeleteWorkitemResponseWrapper {
6615 success: false,
6616 error: error_msg,
6617 request_id: options.request_id
6618 };
6619 Box::into_raw(Box::new(response))
6620 }
6621 };
6622 debug!("return response {:?}", response);
6623 response
6624}
6625#[no_mangle]
6626#[tracing::instrument(skip_all)]
6627pub extern "C" fn delete_workitem_async(
6628 client: *mut ClientWrapper,
6629 options: *mut DeleteWorkitemRequestWrapper,
6630 callback: extern "C" fn(*mut DeleteWorkitemResponseWrapper),
6631) {
6632 let options = match safe_wrapper(options) {
6633 Some(options) => options,
6634 None => {
6635 let error_msg = CString::new("Invalid options").unwrap().into_raw();
6636 let response = DeleteWorkitemResponseWrapper {
6637 success: false,
6638 error: error_msg,
6639 request_id: 0
6640 };
6641 return callback(Box::into_raw(Box::new(response)));
6642 }
6643 };
6644 let client_wrapper = match safe_wrapper(client) {
6645 Some(client) => client,
6646 None => {
6647 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6648 let response = DeleteWorkitemResponseWrapper {
6649 success: false,
6650 error: error_msg,
6651 request_id: options.request_id
6652 };
6653 return callback(Box::into_raw(Box::new(response)));
6654 }
6655 };
6656 let client = client_wrapper.client.clone();
6657 let request = DeleteWorkitemRequest {
6658 id: c_char_to_str(options.id),
6659 };
6660 if client.is_none() {
6661 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6662 let response = DeleteWorkitemResponseWrapper {
6663 success: false,
6664 error: error_msg,
6665 request_id: options.request_id
6666 };
6667 return callback(Box::into_raw(Box::new(response)));
6668 }
6669 let client = client.unwrap();
6670 let handle = client.get_runtime_handle();
6671 let request_id = options.request_id;
6672 handle.spawn(async move {
6673 let result = client
6674 .delete_workitem(request)
6675 .await;
6676 let response = match result {
6677 Ok(_) => {
6678 debug!("success");
6679 let response = DeleteWorkitemResponseWrapper {
6680 success: true,
6681 error: std::ptr::null(),
6682 request_id,
6683 };
6684 Box::into_raw(Box::new(response))
6685 }
6686 Err(e) => {
6687 let error_msg = CString::new(format!("Delete workitem failed: {:?}", e))
6688 .unwrap()
6689 .into_raw();
6690 debug!("failed: {:?}", error_msg);
6691 let response = DeleteWorkitemResponseWrapper {
6692 success: false,
6693 error: error_msg,
6694 request_id,
6695 };
6696 Box::into_raw(Box::new(response))
6697 }
6698 };
6699 debug!("callback {:?}", response);
6700 callback(response);
6701 });
6702}
6703#[no_mangle]
6704#[tracing::instrument(skip_all)]
6705pub extern "C" fn free_delete_workitem_response(response: *mut DeleteWorkitemResponseWrapper) {
6706 if response.is_null() {
6707 return;
6708 }
6709 unsafe {
6710 if !(*response).error.is_null() {
6711 let _ = CString::from_raw((*response).error as *mut c_char);
6712 }
6713 let _ = Box::from_raw(response);
6714 }
6715}
6716
6717
6718
6719
6720
6721#[repr(C)]
6722#[derive(Debug, Clone)]
6723pub struct ClientEventWrapper {
6724 event: *const c_char,
6725 reason: *const c_char,
6726}
6727impl Default for ClientEventWrapper {
6728 fn default() -> Self {
6729 ClientEventWrapper {
6730 event: std::ptr::null(),
6731 reason: std::ptr::null(),
6732 }
6733 }
6734}
6735#[repr(C)]
6736pub struct ClientEventResponseWrapper {
6737 success: bool,
6738 eventid: *const c_char,
6739 error: *const c_char,
6740}
6741
6742#[no_mangle]
6743#[tracing::instrument(skip_all)]
6744pub extern "C" fn on_client_event(
6745 client: *mut ClientWrapper
6746) -> *mut ClientEventResponseWrapper {
6747 let client_wrapper = match safe_wrapper(client) {
6748 Some(client) => client,
6749 None => {
6750 let error_msg = CString::new("Invalid options, client is None").unwrap().into_raw();
6751 let response = ClientEventResponseWrapper {
6752 success: false,
6753 eventid: std::ptr::null(),
6754 error: error_msg,
6755 };
6756 return Box::into_raw(Box::new(response));
6757 }
6758 };
6759 let mut client = client_wrapper.client.clone();
6760 if client.is_none() {
6761 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6762 let response = ClientEventResponseWrapper {
6763 success: false,
6764 eventid: std::ptr::null(),
6765 error: error_msg,
6766 };
6767 return Box::into_raw(Box::new(response));
6768 }
6769 let client = client.as_mut().unwrap();
6770 let eventid = Client::get_uniqueid();
6771 let _eventid = eventid.clone();
6772 tokio::task::block_in_place(|| {
6773 let handle = client.get_runtime_handle();
6774 handle.block_on(client.on_event(Box::new({
6775 move |event: ClientEvent| {
6776 let clientid = _eventid.clone();
6777 debug!("client event: {:?}", event);
6778
6779 let mut e = CLIENT_EVENTS.lock().unwrap();
6780 let queue = e.get_mut(&clientid);
6781 match queue {
6782 Some(q) => {
6783 q.push_back(event);
6784 }
6785 None => {
6786 let mut q = std::collections::VecDeque::new();
6787 q.push_back(event);
6788 e.insert(clientid, q);
6789 }
6790 }
6791 }
6792 })));
6793 });
6794
6795 let mut events = CLIENT_EVENTS.lock().unwrap();
6796 let _eventid = eventid.clone();
6797 let queue = events.get_mut(&_eventid);
6798 if queue.is_none() {
6799 let q = std::collections::VecDeque::new();
6800 let k = String::from(&eventid);
6801 events.insert(k, q);
6802 };
6803 let response = ClientEventResponseWrapper {
6804 success: true,
6805 eventid: CString::new(eventid).unwrap().into_raw(),
6806 error: std::ptr::null(),
6807 };
6808 return Box::into_raw(Box::new(response));
6809}
6810type ClientEventCallback = extern "C" fn(*mut ClientEventWrapper);
6811#[no_mangle]
6812#[tracing::instrument(skip_all)]
6813pub extern "C" fn on_client_event_async(
6814 client: *mut ClientWrapper,
6815 event_callback: ClientEventCallback,
6816) -> *mut ClientEventResponseWrapper {
6817 debug!("on_client_event_async::begin");
6818 let client_wrapper = match safe_wrapper(client) {
6819 Some(client) => client,
6820 None => {
6821 let error_msg = CString::new("Invalid options, client is None").unwrap().into_raw();
6822 let response = ClientEventResponseWrapper {
6823 success: false,
6824 eventid: std::ptr::null(),
6825 error: error_msg,
6826 };
6827 return Box::into_raw(Box::new(response));
6828 }
6829 };
6830 let mut client = client_wrapper.client.clone();
6831 if client.is_none() {
6832 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
6833 let response = ClientEventResponseWrapper {
6834 success: false,
6835 eventid: std::ptr::null(),
6836 error: error_msg,
6837 };
6838 return Box::into_raw(Box::new(response));
6839 }
6840 let client = client.as_mut().unwrap();
6841 let eventid = Client::get_uniqueid();
6842 debug!("on_client_event_async::eventid: {:?}", eventid);
6843 let _eventid = eventid.clone();
6844 tokio::task::block_in_place(|| {
6845 let handle = client.get_runtime_handle();
6846 handle.block_on(client
6847 .on_event(
6848 Box::new(move |event: ClientEvent| {
6849 let clientid = _eventid.clone();
6850 debug!("client event: {:?}", event);
6851 let mut e = CLIENT_EVENTS.lock().unwrap();
6852 let queue = e.get_mut(&clientid);
6853 match queue {
6854 Some(_q) => {
6855 }
6856 None => {
6857 return;
6859 }
6860 };
6861 let event = match event {
6862 ClientEvent::Connecting => ClientEventWrapper { event: CString::new("Connecting").unwrap().into_raw(),reason: std::ptr::null() },
6863 ClientEvent::Connected => ClientEventWrapper { event: CString::new("Connected").unwrap().into_raw(),reason: std::ptr::null() },
6864 ClientEvent::Disconnected(reason) => ClientEventWrapper { event: CString::new("Disconnected").unwrap().into_raw(),reason: CString::new(reason).unwrap().into_raw() },
6865 ClientEvent::SignedIn => ClientEventWrapper { event: CString::new("SignedIn").unwrap().into_raw(),reason: std::ptr::null() },
6866 };
6868 let event = Box::into_raw(Box::new(event));
6869
6870 event_callback(event);
6871 debug!("client event: {:?}", event);
6872 }),
6873 )
6874 )
6875 });
6876
6877 let mut events = CLIENT_EVENTS.lock().unwrap();
6878 let _eventid = eventid.clone();
6879 let queue = events.get_mut(&_eventid);
6880 if queue.is_none() {
6881 debug!("create event queue, for eventid: {:?}", eventid);
6882 let q = std::collections::VecDeque::new();
6883 let k = String::from(&eventid);
6884 events.insert(k, q);
6885 };
6886 debug!("on_client_event_async::end");
6887 let response = ClientEventResponseWrapper {
6888 success: true,
6889 eventid: CString::new(eventid).unwrap().into_raw(),
6890 error: std::ptr::null(),
6891 };
6892 return Box::into_raw(Box::new(response));
6893
6894}
6895
6896#[no_mangle]
6897#[tracing::instrument(skip_all)]
6898pub extern "C" fn next_client_event (
6899 clientid: *const c_char,
6900) -> *mut ClientEventWrapper {
6901 trace!("unwrap clientid");
6902 let clientid = c_char_to_str(clientid);
6903 trace!("clientid {:}", clientid);
6904 let clientid = clientid.to_string();
6905 trace!("unwrap events");
6906 let mut e = CLIENT_EVENTS.lock().unwrap();
6907 trace!("get queue");
6908 let queue = e.get_mut(&clientid);
6909 match queue {
6910 Some(q) => {
6911 match q.pop_front() {
6912 Some(event) => {
6913 debug!("got client event");
6914 let event = match event {
6915 ClientEvent::Connecting => ClientEventWrapper { event: CString::new("Connecting").unwrap().into_raw(),reason: std::ptr::null() },
6916 ClientEvent::Connected => ClientEventWrapper { event: CString::new("Connected").unwrap().into_raw(),reason: std::ptr::null() },
6917 ClientEvent::Disconnected(reason) => ClientEventWrapper { event: CString::new("Disconnected").unwrap().into_raw(),reason: CString::new(reason).unwrap().into_raw() },
6918 ClientEvent::SignedIn => ClientEventWrapper { event: CString::new("SignedIn").unwrap().into_raw(),reason: std::ptr::null() },
6919 };
6921 Box::into_raw(Box::new(event))
6922 }
6923 None => {
6924 trace!("No event");
6925 Box::into_raw(Box::new(ClientEventWrapper::default()))
6926 },
6927 }
6928 },
6929 None => {
6930 debug!("Queue for {:} not found", clientid);
6931 Box::into_raw(Box::new(ClientEventWrapper::default()))
6932 },
6933 }
6934}
6935
6936#[repr(C)]
6937pub struct OffClientEventResponseWrapper {
6938 success: bool,
6939 error: *const c_char,
6940}
6941#[no_mangle]
6942#[tracing::instrument(skip_all)]
6943pub extern "C" fn off_client_event(
6944 eventid: *const c_char,
6945) -> *mut OffClientEventResponseWrapper {
6946 let eventid = c_char_to_str(eventid);
6947 if eventid.is_empty() {
6948 let error_msg = CString::new("eventid is required").unwrap().into_raw();
6949 let response = OffClientEventResponseWrapper {
6950 success: false,
6951 error: error_msg,
6952 };
6953 return Box::into_raw(Box::new(response));
6954 }
6955 trace!("eventid: {:?}", eventid);
6956
6957 let mut e = CLIENT_EVENTS.lock().unwrap();
6958 let queue = e.get_mut(&eventid);
6959 if let Some(q) = queue {
6960 q.clear();
6961 e.remove(&eventid);
6962 };
6963 Box::into_raw(Box::new(OffClientEventResponseWrapper {
6964 success: true,
6965 error: std::ptr::null(),
6966 }))
6967}
6968
6969#[no_mangle]
6970#[tracing::instrument(skip_all)]
6971pub extern "C" fn free_off_event_response(response: *mut OffClientEventResponseWrapper) {
6972 if response.is_null() {
6973 return;
6974 }
6975 unsafe {
6976 if !(*response).error.is_null() {
6977 let _ = CString::from_raw((*response).error as *mut c_char);
6978 }
6979 let _ = Box::from_raw(response);
6980 }
6981}
6982#[no_mangle]
6983#[tracing::instrument(skip_all)]
6984pub extern "C" fn free_event_response(response: *mut ClientEventResponseWrapper) {
6985 if response.is_null() {
6986 return;
6987 }
6988 unsafe {
6989 if !(*response).error.is_null() {
6990 let _ = CString::from_raw((*response).error as *mut c_char);
6991 }
6992 if !(*response).eventid.is_null() {
6993 let _ = CString::from_raw((*response).eventid as *mut c_char);
6994 }
6995 let _ = Box::from_raw(response);
6996 }
6997}
6998#[no_mangle]
6999#[tracing::instrument(skip_all)]
7000pub extern "C" fn free_client_event(response: *mut ClientEventWrapper) {
7001 if response.is_null() {
7002 return;
7003 }
7004 unsafe {
7005 if !(*response).event.is_null() {
7006 let _ = CString::from_raw((*response).event as *mut c_char);
7007 }
7008 if !(*response).reason.is_null() {
7009 let _ = CString::from_raw((*response).reason as *mut c_char);
7010 }
7011 let _ = Box::from_raw(response);
7012 }
7013}
7014#[repr(C)]
7015pub struct RpcResponseWrapper {
7016 success: bool,
7017 result: *const c_char,
7018 error: *const c_char,
7019 request_id: i32
7020}
7021#[no_mangle]
7022#[tracing::instrument(skip_all)]
7023pub extern "C" fn rpc(
7024 client: *mut ClientWrapper,
7025 options: *mut QueueMessageRequestWrapper,
7026) -> *mut RpcResponseWrapper {
7027 let options = match safe_wrapper(options) {
7028 Some(options) => options,
7029 None => {
7030 let error_msg = CString::new("Invalid options").unwrap().into_raw();
7031 let response = RpcResponseWrapper {
7032 success: false,
7033 result: std::ptr::null(),
7034 error: error_msg,
7035 request_id: 0
7036 };
7037 return Box::into_raw(Box::new(response));
7038 }
7039 };
7040 let client_wrapper = match safe_wrapper(client) {
7041 Some(client) => client,
7042 None => {
7043 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7044 let response = RpcResponseWrapper {
7045 success: false,
7046 result: std::ptr::null(),
7047 error: error_msg,
7048 request_id: options.request_id
7049 };
7050 return Box::into_raw(Box::new(response));
7051 }
7052 };
7053 let client = client_wrapper.client.clone();
7054
7055 if client.is_none() {
7056 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7057 let response = RpcResponseWrapper {
7058 success: false,
7059 result: std::ptr::null(),
7060 error: error_msg,
7061 request_id: options.request_id
7062 };
7063 return Box::into_raw(Box::new(response));
7064 }
7065 let client = client.unwrap();
7066
7067 let result = tokio::task::block_in_place(|| {
7068 let handle = client.get_runtime_handle();
7069 let request = QueueMessageRequest {
7070 queuename: c_char_to_str(options.queuename),
7071 correlation_id: c_char_to_str(options.correlation_id),
7072 replyto: c_char_to_str(options.replyto),
7073 routingkey: c_char_to_str(options.routingkey),
7074 exchangename: c_char_to_str(options.exchangename),
7075 data: c_char_to_str(options.data),
7076 striptoken: options.striptoken,
7077 expiration: options.expiration,
7078 };
7079
7080 handle.block_on(client.rpc(request))
7081 });
7082
7083 match result {
7084 Ok(data) => {
7085 let result = CString::new(data).unwrap().into_raw();
7086 let response = RpcResponseWrapper {
7087 success: true,
7088 result,
7089 error: std::ptr::null(),
7090 request_id: options.request_id
7091 };
7092 Box::into_raw(Box::new(response))
7093 }
7094 Err(e) => {
7095 let error_msg = CString::new(format!("RPC failed: {:?}", e))
7096 .unwrap()
7097 .into_raw();
7098 let response = RpcResponseWrapper {
7101 success: false,
7102 result: std::ptr::null(),
7103 error: error_msg,
7104 request_id: options.request_id
7105 };
7106 Box::into_raw(Box::new(response))
7107 }
7108 }
7109}
7110pub type RpcResponseCallback = extern "C" fn(*mut RpcResponseWrapper);
7111#[no_mangle]
7112#[tracing::instrument(skip_all)]
7113pub extern "C" fn rpc_async(
7114 client: *mut ClientWrapper,
7115 options: *mut QueueMessageRequestWrapper,
7116 response_callback: RpcResponseCallback,
7117) {
7118 let options = match safe_wrapper(options) {
7120 Some(o) => o,
7121 None => {
7122 let error_msg = CString::new("Invalid options").unwrap().into_raw();
7123 let response = RpcResponseWrapper {
7124 success: false,
7125 result: std::ptr::null(),
7126 error: error_msg,
7127 request_id: 0
7128 };
7129 response_callback(Box::into_raw(Box::new(response)));
7130 return;
7131 }
7132 };
7133
7134 let client_wrapper = match safe_wrapper(client) {
7136 Some(c) => c,
7137 None => {
7138 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7139 let response = RpcResponseWrapper {
7140 success: false,
7141 result: std::ptr::null(),
7142 error: error_msg,
7143 request_id: options.request_id
7144 };
7145 response_callback(Box::into_raw(Box::new(response)));
7146 return;
7147 }
7148 };
7149
7150 let client = match client_wrapper.client.clone() {
7152 Some(c) => c,
7153 None => {
7154 let error_msg = CString::new("Client is not connected").unwrap().into_raw();
7155 let response = RpcResponseWrapper {
7156 success: false,
7157 result: std::ptr::null(),
7158 error: error_msg,
7159 request_id: options.request_id
7160 };
7161 response_callback(Box::into_raw(Box::new(response)));
7162 return;
7163 }
7164 };
7165
7166 let request = QueueMessageRequest {
7168 queuename: c_char_to_str(options.queuename),
7169 correlation_id: c_char_to_str(options.correlation_id),
7170 replyto: c_char_to_str(options.replyto),
7171 routingkey: c_char_to_str(options.routingkey),
7172 exchangename: c_char_to_str(options.exchangename),
7173 data: c_char_to_str(options.data),
7174 striptoken: options.striptoken,
7175 expiration: options.expiration
7176 };
7177
7178 let runtime_handle = client.get_runtime_handle();
7180
7181 let request_id = options.request_id;
7182
7183 runtime_handle.spawn(async move {
7185 let result = client.rpc(request).await;
7187
7188 let response = match result {
7190 Ok(data) => {
7191 let result_c = CString::new(data).unwrap().into_raw();
7192 RpcResponseWrapper {
7193 success: true,
7194 result: result_c,
7195 error: std::ptr::null(),
7196 request_id: request_id
7197 }
7198 }
7199 Err(e) => {
7200 let error_msg = CString::new(format!("RPC failed: {:?}", e))
7201 .unwrap()
7202 .into_raw();
7203 RpcResponseWrapper {
7204 success: false,
7205 result: std::ptr::null(),
7206 error: error_msg,
7207 request_id: request_id
7208 }
7209 }
7210 };
7211
7212 response_callback(Box::into_raw(Box::new(response)));
7214 });
7215}
7216
7217#[no_mangle]
7321#[tracing::instrument(skip_all)]
7322pub extern "C" fn free_rpc_response(response: *mut RpcResponseWrapper) {
7323 if response.is_null() {
7324 return;
7325 }
7326 unsafe {
7327 if !(*response).error.is_null() {
7328 let _ = CString::from_raw((*response).error as *mut c_char);
7329 }
7330 if !(*response).result.is_null() {
7331 let _ = CString::from_raw((*response).result as *mut c_char);
7332 }
7333 let _ = Box::from_raw(response);
7334 }
7335}