1use std::ffi::{CStr, CString};
2use std::os::raw::{c_char, c_int};
3use std::ptr;
4use std::sync::Mutex;
5use std::collections::HashMap;
6use lazy_static::lazy_static;
7use crate::EipClient;
8use crate::PlcValue;
9use crate::RUNTIME;
10
11lazy_static! {
13 static ref FFI_CLIENTS: Mutex<HashMap<i32, EipClient>> = Mutex::new(HashMap::new());
14 static ref FFI_NEXT_ID: Mutex<i32> = Mutex::new(1);
15}
16
17#[no_mangle]
19pub extern "C" fn eip_connect(ip_address: *const c_char) -> c_int {
20 if ip_address.is_null() {
21 return -1;
22 }
23
24 let ip_str = match unsafe { CStr::from_ptr(ip_address) }.to_str() {
25 Ok(s) => s,
26 Err(_) => return -1,
27 };
28
29 let client = match RUNTIME.block_on(EipClient::new(ip_str)) {
30 Ok(client) => client,
31 Err(_) => return -1,
32 };
33
34 let client_id = {
35 let mut next_id = FFI_NEXT_ID.lock().unwrap();
36 let id = *next_id;
37 *next_id += 1;
38 id
39 };
40
41 {
42 let mut clients = FFI_CLIENTS.lock().unwrap();
43 clients.insert(client_id, client);
44 }
45
46 client_id
47}
48
49#[no_mangle]
51pub extern "C" fn eip_disconnect(client_id: c_int) -> c_int {
52 let mut clients = FFI_CLIENTS.lock().unwrap();
53 match clients.remove(&client_id) {
54 Some(_) => 0,
55 None => -1,
56 }
57}
58
59#[no_mangle]
61pub extern "C" fn eip_read_bool(client_id: c_int, tag_name: *const c_char, result: *mut c_int) -> c_int {
62 if tag_name.is_null() || result.is_null() {
63 return -1;
64 }
65
66 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
67 Ok(s) => s,
68 Err(_) => return -1,
69 };
70
71 let mut clients = FFI_CLIENTS.lock().unwrap();
72 match clients.get_mut(&client_id) {
73 Some(client) => {
74 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
75 Ok(PlcValue::Bool(value)) => {
76 unsafe { *result = if value { 1 } else { 0 }; }
77 0
78 }
79 _ => -1,
80 }
81 }
82 None => -1,
83 }
84}
85
86#[no_mangle]
88pub extern "C" fn eip_write_bool(client_id: c_int, tag_name: *const c_char, value: c_int) -> c_int {
89 if tag_name.is_null() {
90 return -1;
91 }
92
93 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
94 Ok(s) => s,
95 Err(_) => return -1,
96 };
97
98 let mut clients = FFI_CLIENTS.lock().unwrap();
99 match clients.get_mut(&client_id) {
100 Some(client) => {
101 let bool_value = value != 0;
102 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Bool(bool_value))) {
103 Ok(_) => 0,
104 Err(_) => -1,
105 }
106 }
107 None => -1,
108 }
109}
110
111#[no_mangle]
113pub extern "C" fn eip_read_sint(client_id: c_int, tag_name: *const c_char, result: *mut i8) -> c_int {
114 if tag_name.is_null() || result.is_null() {
115 return -1;
116 }
117
118 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
119 Ok(s) => s,
120 Err(_) => return -1,
121 };
122
123 let mut clients = FFI_CLIENTS.lock().unwrap();
124 match clients.get_mut(&client_id) {
125 Some(client) => {
126 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
127 Ok(PlcValue::Sint(value)) => {
128 unsafe { *result = value; }
129 0
130 }
131 _ => -1,
132 }
133 }
134 None => -1,
135 }
136}
137
138#[no_mangle]
139pub extern "C" fn eip_write_sint(client_id: c_int, tag_name: *const c_char, value: i8) -> c_int {
140 if tag_name.is_null() {
141 return -1;
142 }
143
144 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
145 Ok(s) => s,
146 Err(_) => return -1,
147 };
148
149 let mut clients = FFI_CLIENTS.lock().unwrap();
150 match clients.get_mut(&client_id) {
151 Some(client) => {
152 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Sint(value))) {
153 Ok(_) => 0,
154 Err(_) => -1,
155 }
156 }
157 None => -1,
158 }
159}
160
161#[no_mangle]
163pub extern "C" fn eip_read_int(client_id: c_int, tag_name: *const c_char, result: *mut i16) -> c_int {
164 if tag_name.is_null() || result.is_null() {
165 return -1;
166 }
167
168 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
169 Ok(s) => s,
170 Err(_) => return -1,
171 };
172
173 let mut clients = FFI_CLIENTS.lock().unwrap();
174 match clients.get_mut(&client_id) {
175 Some(client) => {
176 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
177 Ok(PlcValue::Int(value)) => {
178 unsafe { *result = value; }
179 0
180 }
181 _ => -1,
182 }
183 }
184 None => -1,
185 }
186}
187
188#[no_mangle]
189pub extern "C" fn eip_write_int(client_id: c_int, tag_name: *const c_char, value: i16) -> c_int {
190 if tag_name.is_null() {
191 return -1;
192 }
193
194 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
195 Ok(s) => s,
196 Err(_) => return -1,
197 };
198
199 let mut clients = FFI_CLIENTS.lock().unwrap();
200 match clients.get_mut(&client_id) {
201 Some(client) => {
202 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Int(value))) {
203 Ok(_) => 0,
204 Err(_) => -1,
205 }
206 }
207 None => -1,
208 }
209}
210
211#[no_mangle]
213pub extern "C" fn eip_read_dint(client_id: c_int, tag_name: *const c_char, result: *mut c_int) -> c_int {
214 if tag_name.is_null() || result.is_null() {
215 return -1;
216 }
217
218 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
219 Ok(s) => s,
220 Err(_) => return -1,
221 };
222
223 let mut clients = FFI_CLIENTS.lock().unwrap();
224 match clients.get_mut(&client_id) {
225 Some(client) => {
226 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
227 Ok(PlcValue::Dint(value)) => {
228 unsafe { *result = value; }
229 0
230 }
231 _ => -1,
232 }
233 }
234 None => -1,
235 }
236}
237
238#[no_mangle]
240pub extern "C" fn eip_write_dint(client_id: c_int, tag_name: *const c_char, value: c_int) -> c_int {
241 if tag_name.is_null() {
242 return -1;
243 }
244
245 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
246 Ok(s) => s,
247 Err(_) => return -1,
248 };
249
250 let mut clients = FFI_CLIENTS.lock().unwrap();
251 match clients.get_mut(&client_id) {
252 Some(client) => {
253 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Dint(value))) {
254 Ok(_) => 0,
255 Err(_) => -1,
256 }
257 }
258 None => -1,
259 }
260}
261
262#[no_mangle]
264pub extern "C" fn eip_read_lint(client_id: c_int, tag_name: *const c_char, result: *mut i64) -> c_int {
265 if tag_name.is_null() || result.is_null() {
266 return -1;
267 }
268
269 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
270 Ok(s) => s,
271 Err(_) => return -1,
272 };
273
274 let mut clients = FFI_CLIENTS.lock().unwrap();
275 match clients.get_mut(&client_id) {
276 Some(client) => {
277 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
278 Ok(PlcValue::Lint(value)) => {
279 unsafe { *result = value; }
280 0
281 }
282 _ => -1,
283 }
284 }
285 None => -1,
286 }
287}
288
289#[no_mangle]
290pub extern "C" fn eip_write_lint(client_id: c_int, tag_name: *const c_char, value: i64) -> c_int {
291 if tag_name.is_null() {
292 return -1;
293 }
294
295 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
296 Ok(s) => s,
297 Err(_) => return -1,
298 };
299
300 let mut clients = FFI_CLIENTS.lock().unwrap();
301 match clients.get_mut(&client_id) {
302 Some(client) => {
303 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Lint(value))) {
304 Ok(_) => 0,
305 Err(_) => -1,
306 }
307 }
308 None => -1,
309 }
310}
311
312#[no_mangle]
314pub extern "C" fn eip_read_usint(client_id: c_int, tag_name: *const c_char, result: *mut u8) -> c_int {
315 if tag_name.is_null() || result.is_null() {
316 return -1;
317 }
318
319 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
320 Ok(s) => s,
321 Err(_) => return -1,
322 };
323
324 let mut clients = FFI_CLIENTS.lock().unwrap();
325 match clients.get_mut(&client_id) {
326 Some(client) => {
327 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
328 Ok(PlcValue::Usint(value)) => {
329 unsafe { *result = value; }
330 0
331 }
332 _ => -1,
333 }
334 }
335 None => -1,
336 }
337}
338
339#[no_mangle]
340pub extern "C" fn eip_write_usint(client_id: c_int, tag_name: *const c_char, value: u8) -> c_int {
341 if tag_name.is_null() {
342 return -1;
343 }
344
345 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
346 Ok(s) => s,
347 Err(_) => return -1,
348 };
349
350 let mut clients = FFI_CLIENTS.lock().unwrap();
351 match clients.get_mut(&client_id) {
352 Some(client) => {
353 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Usint(value))) {
354 Ok(_) => 0,
355 Err(_) => -1,
356 }
357 }
358 None => -1,
359 }
360}
361
362#[no_mangle]
364pub extern "C" fn eip_read_uint(client_id: c_int, tag_name: *const c_char, result: *mut u16) -> c_int {
365 if tag_name.is_null() || result.is_null() {
366 return -1;
367 }
368
369 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
370 Ok(s) => s,
371 Err(_) => return -1,
372 };
373
374 let mut clients = FFI_CLIENTS.lock().unwrap();
375 match clients.get_mut(&client_id) {
376 Some(client) => {
377 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
378 Ok(PlcValue::Uint(value)) => {
379 unsafe { *result = value; }
380 0
381 }
382 _ => -1,
383 }
384 }
385 None => -1,
386 }
387}
388
389#[no_mangle]
390pub extern "C" fn eip_write_uint(client_id: c_int, tag_name: *const c_char, value: u16) -> c_int {
391 if tag_name.is_null() {
392 return -1;
393 }
394
395 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
396 Ok(s) => s,
397 Err(_) => return -1,
398 };
399
400 let mut clients = FFI_CLIENTS.lock().unwrap();
401 match clients.get_mut(&client_id) {
402 Some(client) => {
403 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Uint(value))) {
404 Ok(_) => 0,
405 Err(_) => -1,
406 }
407 }
408 None => -1,
409 }
410}
411
412#[no_mangle]
414pub extern "C" fn eip_read_udint(client_id: c_int, tag_name: *const c_char, result: *mut u32) -> c_int {
415 if tag_name.is_null() || result.is_null() {
416 return -1;
417 }
418
419 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
420 Ok(s) => s,
421 Err(_) => return -1,
422 };
423
424 let mut clients = FFI_CLIENTS.lock().unwrap();
425 match clients.get_mut(&client_id) {
426 Some(client) => {
427 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
428 Ok(PlcValue::Udint(value)) => {
429 unsafe { *result = value; }
430 0
431 }
432 _ => -1,
433 }
434 }
435 None => -1,
436 }
437}
438
439#[no_mangle]
440pub extern "C" fn eip_write_udint(client_id: c_int, tag_name: *const c_char, value: u32) -> c_int {
441 if tag_name.is_null() {
442 return -1;
443 }
444
445 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
446 Ok(s) => s,
447 Err(_) => return -1,
448 };
449
450 let mut clients = FFI_CLIENTS.lock().unwrap();
451 match clients.get_mut(&client_id) {
452 Some(client) => {
453 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Udint(value))) {
454 Ok(_) => 0,
455 Err(_) => -1,
456 }
457 }
458 None => -1,
459 }
460}
461
462#[no_mangle]
464pub extern "C" fn eip_read_ulint(client_id: c_int, tag_name: *const c_char, result: *mut u64) -> c_int {
465 if tag_name.is_null() || result.is_null() {
466 return -1;
467 }
468
469 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
470 Ok(s) => s,
471 Err(_) => return -1,
472 };
473
474 let mut clients = FFI_CLIENTS.lock().unwrap();
475 match clients.get_mut(&client_id) {
476 Some(client) => {
477 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
478 Ok(PlcValue::Ulint(value)) => {
479 unsafe { *result = value; }
480 0
481 }
482 _ => -1,
483 }
484 }
485 None => -1,
486 }
487}
488
489#[no_mangle]
490pub extern "C" fn eip_write_ulint(client_id: c_int, tag_name: *const c_char, value: u64) -> c_int {
491 if tag_name.is_null() {
492 return -1;
493 }
494
495 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
496 Ok(s) => s,
497 Err(_) => return -1,
498 };
499
500 let mut clients = FFI_CLIENTS.lock().unwrap();
501 match clients.get_mut(&client_id) {
502 Some(client) => {
503 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Ulint(value))) {
504 Ok(_) => 0,
505 Err(_) => -1,
506 }
507 }
508 None => -1,
509 }
510}
511
512#[no_mangle]
514pub extern "C" fn eip_read_real(client_id: c_int, tag_name: *const c_char, result: *mut f64) -> c_int {
515 if tag_name.is_null() || result.is_null() {
516 return -1;
517 }
518
519 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
520 Ok(s) => s,
521 Err(_) => return -1,
522 };
523
524 let mut clients = FFI_CLIENTS.lock().unwrap();
525 match clients.get_mut(&client_id) {
526 Some(client) => {
527 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
528 Ok(PlcValue::Real(value)) => {
529 unsafe { *result = value as f64; }
530 0
531 }
532 _ => -1,
533 }
534 }
535 None => -1,
536 }
537}
538
539#[no_mangle]
541pub extern "C" fn eip_write_real(client_id: c_int, tag_name: *const c_char, value: f64) -> c_int {
542 if tag_name.is_null() {
543 return -1;
544 }
545
546 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
547 Ok(s) => s,
548 Err(_) => return -1,
549 };
550
551 let mut clients = FFI_CLIENTS.lock().unwrap();
552 match clients.get_mut(&client_id) {
553 Some(client) => {
554 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Real(value as f32))) {
555 Ok(_) => 0,
556 Err(_) => -1,
557 }
558 }
559 None => -1,
560 }
561}
562
563#[no_mangle]
565pub extern "C" fn eip_read_lreal(client_id: c_int, tag_name: *const c_char, result: *mut f64) -> c_int {
566 if tag_name.is_null() || result.is_null() {
567 return -1;
568 }
569
570 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
571 Ok(s) => s,
572 Err(_) => return -1,
573 };
574
575 let mut clients = FFI_CLIENTS.lock().unwrap();
576 match clients.get_mut(&client_id) {
577 Some(client) => {
578 match RUNTIME.block_on(client.read_tag(tag_name_str)) {
579 Ok(PlcValue::Lreal(value)) => {
580 unsafe { *result = value; }
581 0
582 }
583 _ => -1,
584 }
585 }
586 None => -1,
587 }
588}
589
590#[no_mangle]
591pub extern "C" fn eip_write_lreal(client_id: c_int, tag_name: *const c_char, value: f64) -> c_int {
592 if tag_name.is_null() {
593 return -1;
594 }
595
596 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
597 Ok(s) => s,
598 Err(_) => return -1,
599 };
600
601 let mut clients = FFI_CLIENTS.lock().unwrap();
602 match clients.get_mut(&client_id) {
603 Some(client) => {
604 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::Lreal(value))) {
605 Ok(_) => 0,
606 Err(_) => -1,
607 }
608 }
609 None => -1,
610 }
611}
612
613#[no_mangle]
615pub extern "C" fn eip_read_string(client_id: c_int, tag_name: *const c_char, result: *mut c_char, max_length: c_int) -> c_int {
616 if tag_name.is_null() || result.is_null() || max_length <= 0 {
617 return -1;
618 }
619
620 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
621 Ok(s) => s,
622 Err(_) => return -1,
623 };
624
625 let mut clients = FFI_CLIENTS.lock().unwrap();
626 let client = match clients.get_mut(&client_id) {
627 Some(client) => client,
628 None => return -1,
629 };
630
631 let value = match RUNTIME.block_on(client.read_tag(tag_name_str)) {
632 Ok(PlcValue::String(value)) => value,
633 Ok(_) => return -1, Err(_) => return -1, };
636
637 let c_string = match CString::new(value) {
638 Ok(s) => s,
639 Err(_) => return -1,
640 };
641
642 let bytes = c_string.as_bytes_with_nul();
643 if bytes.len() > max_length as usize {
644 return -1; }
646
647 unsafe {
648 ptr::copy_nonoverlapping(bytes.as_ptr(), result as *mut u8, bytes.len());
649 }
650 0
651}
652
653#[no_mangle]
655pub extern "C" fn eip_write_string(client_id: c_int, tag_name: *const c_char, value: *const c_char) -> c_int {
656 if tag_name.is_null() || value.is_null() {
657 return -1;
658 }
659
660 let tag_name_str = match unsafe { CStr::from_ptr(tag_name) }.to_str() {
661 Ok(s) => s,
662 Err(_) => return -1,
663 };
664
665 let value_str = match unsafe { CStr::from_ptr(value) }.to_str() {
666 Ok(s) => s,
667 Err(_) => return -1,
668 };
669
670 let mut clients = FFI_CLIENTS.lock().unwrap();
671 let client = match clients.get_mut(&client_id) {
672 Some(client) => client,
673 None => return -1,
674 };
675
676 match RUNTIME.block_on(client.write_tag(tag_name_str, PlcValue::String(value_str.to_string()))) {
677 Ok(_) => 0,
678 Err(_) => -1,
679 }
680}
681
682#[no_mangle]
684pub extern "C" fn eip_read_udt(client_id: c_int, tag_name: *const c_char, result: *mut c_char, max_size: c_int) -> c_int {
685 -1
687}
688
689#[no_mangle]
690pub extern "C" fn eip_write_udt(client_id: c_int, tag_name: *const c_char, value: *const c_char, size: c_int) -> c_int {
691 -1
693}
694
695#[no_mangle]
697pub extern "C" fn eip_discover_tags(client_id: c_int) -> c_int {
698 0
700}
701
702#[no_mangle]
703pub extern "C" fn eip_get_tag_metadata(client_id: c_int, tag_name: *const c_char, metadata: *mut u8) -> c_int {
704 -1
706}
707
708#[no_mangle]
710pub extern "C" fn eip_set_max_packet_size(client_id: c_int, size: c_int) -> c_int {
711 0
713}
714
715#[no_mangle]
717pub extern "C" fn eip_check_health(client_id: c_int, is_healthy: *mut c_int) -> c_int {
718 if is_healthy.is_null() {
719 return -1;
720 }
721
722 let clients = FFI_CLIENTS.lock().unwrap();
723 match clients.get(&client_id) {
724 Some(_) => {
725 unsafe { *is_healthy = 1; }
726 0
727 }
728 None => {
729 unsafe { *is_healthy = 0; }
730 -1
731 }
732 }
733}
734
735#[no_mangle]
736pub extern "C" fn eip_check_health_detailed(client_id: c_int, is_healthy: *mut c_int) -> c_int {
737 eip_check_health(client_id, is_healthy)
739}
740
741#[no_mangle]
743pub extern "C" fn eip_read_tags_batch(client_id: c_int, tag_names: *mut *const c_char, tag_count: c_int, results: *mut c_char, results_capacity: c_int) -> c_int {
744 if tag_names.is_null() || results.is_null() || tag_count <= 0 {
745 return -1;
746 }
747
748 let mut clients = FFI_CLIENTS.lock().unwrap();
749 let client = match clients.get_mut(&client_id) {
750 Some(client) => client,
751 None => return -1,
752 };
753
754 let mut tag_name_strs = Vec::new();
756 unsafe {
757 for i in 0..tag_count {
758 let tag_name_ptr = *tag_names.offset(i as isize);
759 if tag_name_ptr.is_null() {
760 return -1;
761 }
762 let tag_name = match CStr::from_ptr(tag_name_ptr).to_str() {
763 Ok(s) => s,
764 Err(_) => return -1,
765 };
766 tag_name_strs.push(tag_name);
767 }
768 }
769
770 let batch_results = RUNTIME.block_on(async {
772 client.read_tags_batch(&tag_name_strs).await
773 });
774
775 let results_data = match batch_results {
776 Ok(results) => {
777 let mut formatted = String::new();
779 for (i, (tag_name, result)) in results.iter().enumerate() {
780 if i > 0 {
781 formatted.push(';');
782 }
783 formatted.push_str(tag_name);
784 formatted.push(':');
785 match result {
786 Ok(value) => formatted.push_str(&format!("{:?}", value)),
787 Err(e) => formatted.push_str(&format!("ERROR:{}", e)),
788 }
789 }
790 formatted
791 }
792 Err(_) => return -1,
793 };
794
795 let results_bytes = results_data.as_bytes();
797 if results_bytes.len() >= results_capacity as usize {
798 return -1;
799 }
800
801 unsafe {
802 std::ptr::copy_nonoverlapping(results_bytes.as_ptr(), results as *mut u8, results_bytes.len());
803 *results.offset(results_bytes.len() as isize) = 0; }
805
806 0
807}
808
809#[no_mangle]
810pub extern "C" fn eip_write_tags_batch(client_id: c_int, tag_values: *const c_char, tag_count: c_int, results: *mut c_char, results_capacity: c_int) -> c_int {
811 if tag_values.is_null() || results.is_null() || tag_count <= 0 {
812 return -1;
813 }
814
815 let mut clients = FFI_CLIENTS.lock().unwrap();
816 let _client = match clients.get_mut(&client_id) {
817 Some(client) => client,
818 None => return -1,
819 };
820
821 let _input_str = unsafe {
823 match CStr::from_ptr(tag_values).to_str() {
824 Ok(s) => s,
825 Err(_) => return -1,
826 }
827 };
828
829 let results_data = "ERROR:Batch write not yet implemented in FFI";
832 let results_bytes = results_data.as_bytes();
833
834 if results_bytes.len() >= results_capacity as usize {
835 return -1;
836 }
837
838 unsafe {
839 std::ptr::copy_nonoverlapping(results_bytes.as_ptr(), results as *mut u8, results_bytes.len());
840 *results.offset(results_bytes.len() as isize) = 0; }
842
843 0
844}
845
846#[no_mangle]
847pub extern "C" fn eip_execute_batch(client_id: c_int, operations: *const c_char, operation_count: c_int, results: *mut c_char, results_capacity: c_int) -> c_int {
848 if operations.is_null() || results.is_null() || operation_count <= 0 {
849 return -1;
850 }
851
852 let mut clients = FFI_CLIENTS.lock().unwrap();
853 let _client = match clients.get_mut(&client_id) {
854 Some(client) => client,
855 None => return -1,
856 };
857
858 let _input_str = unsafe {
860 match CStr::from_ptr(operations).to_str() {
861 Ok(s) => s,
862 Err(_) => return -1,
863 }
864 };
865
866 let results_data = "ERROR:Mixed batch operations not yet implemented in FFI";
869 let results_bytes = results_data.as_bytes();
870
871 if results_bytes.len() >= results_capacity as usize {
872 return -1;
873 }
874
875 unsafe {
876 std::ptr::copy_nonoverlapping(results_bytes.as_ptr(), results as *mut u8, results_bytes.len());
877 *results.offset(results_bytes.len() as isize) = 0; }
879
880 0
881}
882
883#[no_mangle]
884pub extern "C" fn eip_configure_batch_operations(client_id: c_int, config: *const u8) -> c_int {
885 0 }
887
888#[no_mangle]
889pub extern "C" fn eip_get_batch_config(client_id: c_int, config: *mut u8) -> c_int {
890 -1 }