Skip to main content

sz_configtool_lib/
ffi.rs

1//! C FFI bindings for sz_configtool_lib
2//!
3//! This module provides a C-compatible interface to the Rust sz_configtool_lib library.
4//! Functions follow the pattern established by Senzing's SzLang_helpers.h.
5//!
6//! # Safety
7//!
8//! All functions in this module that accept raw pointers require:
9//! - Non-null pointers (null pointers will return error codes)
10//! - Valid UTF-8 strings for string parameters
11//! - Memory allocated by this library must be freed with `SzConfigTool_free`
12
13#![allow(clippy::missing_safety_doc)]
14#![allow(clippy::not_unsafe_ptr_arg_deref)]
15
16use std::ffi::{CStr, CString};
17use std::os::raw::c_char;
18use std::sync::Mutex;
19
20use crate::error::SzConfigError;
21
22// Thread-safe error storage
23static LAST_ERROR: Mutex<Option<String>> = Mutex::new(None);
24static LAST_ERROR_CODE: Mutex<i64> = Mutex::new(0);
25
26/// Platform-specific export macro
27#[cfg(target_os = "windows")]
28const _DLEXPORT: &str = "__declspec(dllexport)";
29
30#[cfg(not(target_os = "windows"))]
31const _DLEXPORT: &str = "";
32
33// ============================================================================
34// Result Structures (matching SzLang_helpers.h pattern)
35// ============================================================================
36
37/// Result structure for operations that return modified configuration JSON
38#[repr(C)]
39#[allow(non_snake_case)] // Match C convention from SzHelpers
40pub struct SzConfigTool_result {
41    /// Modified configuration JSON (caller must free with SzConfigTool_free)
42    pub response: *mut c_char,
43    /// Return code: 0 = success, negative = error (matches SzHelpers convention)
44    pub returnCode: i64,
45}
46
47// ============================================================================
48// Infrastructure Functions
49// ============================================================================
50
51/// Free memory allocated by this library
52///
53/// # Safety
54/// ptr must be a valid pointer previously returned by this library, or null
55#[unsafe(no_mangle)]
56pub unsafe extern "C" fn SzConfigTool_free(ptr: *mut c_char) {
57    if !ptr.is_null() {
58        unsafe {
59            drop(CString::from_raw(ptr));
60        }
61    }
62}
63
64/// Get the last error message
65///
66/// # Returns
67/// Pointer to error string (do not free), or null if no error
68#[unsafe(no_mangle)]
69pub extern "C" fn SzConfigTool_getLastError() -> *const c_char {
70    let error = LAST_ERROR.lock().unwrap();
71    match error.as_ref() {
72        Some(err) => err.as_ptr() as *const c_char,
73        None => std::ptr::null(),
74    }
75}
76
77/// Get the last error code
78///
79/// # Returns
80/// Error code (0 = no error, negative = error)
81#[unsafe(no_mangle)]
82pub extern "C" fn SzConfigTool_getLastErrorCode() -> i64 {
83    *LAST_ERROR_CODE.lock().unwrap()
84}
85
86/// Clear the last error
87#[unsafe(no_mangle)]
88pub extern "C" fn SzConfigTool_clearLastError() {
89    *LAST_ERROR.lock().unwrap() = None;
90    *LAST_ERROR_CODE.lock().unwrap() = 0;
91}
92
93// ============================================================================
94// Helper Macros for Error Handling
95// ============================================================================
96
97macro_rules! handle_result {
98    ($result:expr) => {
99        match $result {
100            Ok(json) => {
101                SzConfigTool_clearLastError();
102                match CString::new(json) {
103                    Ok(c_str) => SzConfigTool_result {
104                        response: c_str.into_raw(),
105                        returnCode: 0,
106                    },
107                    Err(e) => {
108                        set_error(format!("Failed to convert result to C string: {}", e), -1);
109                        SzConfigTool_result {
110                            response: std::ptr::null_mut(),
111                            returnCode: -1,
112                        }
113                    }
114                }
115            }
116            Err(e) => {
117                set_error(format!("{}", e), -2);
118                SzConfigTool_result {
119                    response: std::ptr::null_mut(),
120                    returnCode: -2,
121                }
122            }
123        }
124    };
125}
126
127fn set_error(msg: String, code: i64) {
128    *LAST_ERROR.lock().unwrap() = Some(msg);
129    *LAST_ERROR_CODE.lock().unwrap() = code;
130}
131
132fn clear_error() {
133    *LAST_ERROR.lock().unwrap() = None;
134    *LAST_ERROR_CODE.lock().unwrap() = 0;
135}
136
137// ============================================================================
138// Data Source Functions
139// ============================================================================
140
141/// Add a data source to the configuration
142///
143/// # Safety
144/// configJson and dataSourceCode must be valid null-terminated C strings
145#[unsafe(no_mangle)]
146pub unsafe extern "C" fn SzConfigTool_addDataSource(
147    config_json: *const c_char,
148    data_source_code: *const c_char,
149) -> SzConfigTool_result {
150    if config_json.is_null() || data_source_code.is_null() {
151        set_error("Null pointer provided".to_string(), -1);
152        return SzConfigTool_result {
153            response: std::ptr::null_mut(),
154            returnCode: -1,
155        };
156    }
157
158    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
159        Ok(s) => s,
160        Err(e) => {
161            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
162            return SzConfigTool_result {
163                response: std::ptr::null_mut(),
164                returnCode: -1,
165            };
166        }
167    };
168
169    let ds_code = match unsafe { CStr::from_ptr(data_source_code) }.to_str() {
170        Ok(s) => s,
171        Err(e) => {
172            set_error(format!("Invalid UTF-8 in dataSourceCode: {e}"), -1);
173            return SzConfigTool_result {
174                response: std::ptr::null_mut(),
175                returnCode: -1,
176            };
177        }
178    };
179
180    // Use default values for optional parameters (matches Python defaults)
181    let result = crate::datasources::add_data_source(
182        config,
183        crate::datasources::AddDataSourceParams {
184            code: ds_code,
185            ..Default::default()
186        },
187    );
188    handle_result!(result)
189}
190
191/// Delete a data source from the configuration
192///
193/// # Safety
194/// configJson and dataSourceCode must be valid null-terminated C strings
195#[unsafe(no_mangle)]
196pub unsafe extern "C" fn SzConfigTool_deleteDataSource(
197    config_json: *const c_char,
198    data_source_code: *const c_char,
199) -> SzConfigTool_result {
200    if config_json.is_null() || data_source_code.is_null() {
201        set_error("Null pointer provided".to_string(), -1);
202        return SzConfigTool_result {
203            response: std::ptr::null_mut(),
204            returnCode: -1,
205        };
206    }
207
208    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
209        Ok(s) => s,
210        Err(e) => {
211            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
212            return SzConfigTool_result {
213                response: std::ptr::null_mut(),
214                returnCode: -1,
215            };
216        }
217    };
218
219    let ds_code = match unsafe { CStr::from_ptr(data_source_code) }.to_str() {
220        Ok(s) => s,
221        Err(e) => {
222            set_error(format!("Invalid UTF-8 in dataSourceCode: {e}"), -1);
223            return SzConfigTool_result {
224                response: std::ptr::null_mut(),
225                returnCode: -1,
226            };
227        }
228    };
229
230    let result = crate::datasources::delete_data_source(config, ds_code);
231    handle_result!(result)
232}
233
234/// List all data sources in the configuration (returns JSON array string)
235///
236/// # Safety
237/// configJson must be a valid null-terminated C string
238#[unsafe(no_mangle)]
239pub unsafe extern "C" fn SzConfigTool_listDataSources(
240    config_json: *const c_char,
241) -> SzConfigTool_result {
242    if config_json.is_null() {
243        set_error("Null pointer provided".to_string(), -1);
244        return SzConfigTool_result {
245            response: std::ptr::null_mut(),
246            returnCode: -1,
247        };
248    }
249
250    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
251        Ok(s) => s,
252        Err(e) => {
253            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
254            return SzConfigTool_result {
255                response: std::ptr::null_mut(),
256                returnCode: -1,
257            };
258        }
259    };
260
261    let result = crate::datasources::list_data_sources(config).and_then(|vec| {
262        serde_json::to_string(&vec).map_err(|e| SzConfigError::JsonParse(e.to_string()))
263    });
264    handle_result!(result)
265}
266
267// ============================================================================
268// Attribute Functions
269// ============================================================================
270
271/// Add an attribute to the configuration
272///
273/// # Safety
274/// All string parameters must be valid null-terminated C strings
275/// Optional parameters can be null
276#[unsafe(no_mangle)]
277pub unsafe extern "C" fn SzConfigTool_addAttribute(
278    config_json: *const c_char,
279    attribute_code: *const c_char,
280    feature_code: *const c_char,
281    element_code: *const c_char,
282    attr_class: *const c_char,
283    default_value: *const c_char,
284    internal: *const c_char,
285    required: *const c_char,
286) -> SzConfigTool_result {
287    if config_json.is_null()
288        || attribute_code.is_null()
289        || feature_code.is_null()
290        || element_code.is_null()
291        || attr_class.is_null()
292    {
293        set_error("Required parameter is null".to_string(), -1);
294        return SzConfigTool_result {
295            response: std::ptr::null_mut(),
296            returnCode: -1,
297        };
298    }
299
300    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
301        Ok(s) => s,
302        Err(e) => {
303            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
304            return SzConfigTool_result {
305                response: std::ptr::null_mut(),
306                returnCode: -1,
307            };
308        }
309    };
310
311    let attr_code = match unsafe { CStr::from_ptr(attribute_code) }.to_str() {
312        Ok(s) => s,
313        Err(e) => {
314            set_error(format!("Invalid UTF-8 in attributeCode: {e}"), -1);
315            return SzConfigTool_result {
316                response: std::ptr::null_mut(),
317                returnCode: -1,
318            };
319        }
320    };
321
322    let feat_code = match unsafe { CStr::from_ptr(feature_code) }.to_str() {
323        Ok(s) => s,
324        Err(e) => {
325            set_error(format!("Invalid UTF-8 in featureCode: {e}"), -1);
326            return SzConfigTool_result {
327                response: std::ptr::null_mut(),
328                returnCode: -1,
329            };
330        }
331    };
332
333    let elem_code = match unsafe { CStr::from_ptr(element_code) }.to_str() {
334        Ok(s) => s,
335        Err(e) => {
336            set_error(format!("Invalid UTF-8 in elementCode: {e}"), -1);
337            return SzConfigTool_result {
338                response: std::ptr::null_mut(),
339                returnCode: -1,
340            };
341        }
342    };
343
344    let class = match unsafe { CStr::from_ptr(attr_class) }.to_str() {
345        Ok(s) => s,
346        Err(e) => {
347            set_error(format!("Invalid UTF-8 in attrClass: {e}"), -1);
348            return SzConfigTool_result {
349                response: std::ptr::null_mut(),
350                returnCode: -1,
351            };
352        }
353    };
354
355    let def_val = if default_value.is_null() {
356        None
357    } else {
358        match unsafe { CStr::from_ptr(default_value) }.to_str() {
359            Ok(s) => Some(s),
360            Err(e) => {
361                set_error(format!("Invalid UTF-8 in defaultValue: {e}"), -1);
362                return SzConfigTool_result {
363                    response: std::ptr::null_mut(),
364                    returnCode: -1,
365                };
366            }
367        }
368    };
369
370    let int_val = if internal.is_null() {
371        None
372    } else {
373        match unsafe { CStr::from_ptr(internal) }.to_str() {
374            Ok(s) => Some(s),
375            Err(e) => {
376                set_error(format!("Invalid UTF-8 in internal: {e}"), -1);
377                return SzConfigTool_result {
378                    response: std::ptr::null_mut(),
379                    returnCode: -1,
380                };
381            }
382        }
383    };
384
385    let req_val = if required.is_null() {
386        None
387    } else {
388        match unsafe { CStr::from_ptr(required) }.to_str() {
389            Ok(s) => Some(s),
390            Err(e) => {
391                set_error(format!("Invalid UTF-8 in required: {e}"), -1);
392                return SzConfigTool_result {
393                    response: std::ptr::null_mut(),
394                    returnCode: -1,
395                };
396            }
397        }
398    };
399
400    let result = crate::attributes::add_attribute(
401        config,
402        crate::attributes::AddAttributeParams {
403            attribute: attr_code,
404            feature: feat_code,
405            element: elem_code,
406            class,
407            default_value: def_val,
408            internal: int_val,
409            required: req_val,
410        },
411    )
412    .map(|(json, _item)| json);
413
414    handle_result!(result)
415}
416
417/// Delete an attribute from the configuration
418///
419/// # Safety
420/// configJson and attributeCode must be valid null-terminated C strings
421#[unsafe(no_mangle)]
422pub unsafe extern "C" fn SzConfigTool_deleteAttribute(
423    config_json: *const c_char,
424    attribute_code: *const c_char,
425) -> SzConfigTool_result {
426    if config_json.is_null() || attribute_code.is_null() {
427        set_error("Null pointer provided".to_string(), -1);
428        return SzConfigTool_result {
429            response: std::ptr::null_mut(),
430            returnCode: -1,
431        };
432    }
433
434    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
435        Ok(s) => s,
436        Err(e) => {
437            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
438            return SzConfigTool_result {
439                response: std::ptr::null_mut(),
440                returnCode: -1,
441            };
442        }
443    };
444
445    let attr_code = match unsafe { CStr::from_ptr(attribute_code) }.to_str() {
446        Ok(s) => s,
447        Err(e) => {
448            set_error(format!("Invalid UTF-8 in attributeCode: {e}"), -1);
449            return SzConfigTool_result {
450                response: std::ptr::null_mut(),
451                returnCode: -1,
452            };
453        }
454    };
455
456    let result = crate::attributes::delete_attribute(config, attr_code);
457    handle_result!(result)
458}
459
460/// Get an attribute from the configuration (returns JSON object string)
461///
462/// # Safety
463/// configJson and attributeCode must be valid null-terminated C strings
464#[unsafe(no_mangle)]
465pub unsafe extern "C" fn SzConfigTool_getAttribute(
466    config_json: *const c_char,
467    attribute_code: *const c_char,
468) -> SzConfigTool_result {
469    if config_json.is_null() || attribute_code.is_null() {
470        set_error("Null pointer provided".to_string(), -1);
471        return SzConfigTool_result {
472            response: std::ptr::null_mut(),
473            returnCode: -1,
474        };
475    }
476
477    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
478        Ok(s) => s,
479        Err(e) => {
480            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
481            return SzConfigTool_result {
482                response: std::ptr::null_mut(),
483                returnCode: -1,
484            };
485        }
486    };
487
488    let attr_code = match unsafe { CStr::from_ptr(attribute_code) }.to_str() {
489        Ok(s) => s,
490        Err(e) => {
491            set_error(format!("Invalid UTF-8 in attributeCode: {e}"), -1);
492            return SzConfigTool_result {
493                response: std::ptr::null_mut(),
494                returnCode: -1,
495            };
496        }
497    };
498
499    let result = crate::attributes::get_attribute(config, attr_code).and_then(|val| {
500        serde_json::to_string(&val).map_err(|e| SzConfigError::JsonParse(e.to_string()))
501    });
502    handle_result!(result)
503}
504
505/// List all attributes in the configuration (returns JSON array string)
506///
507/// # Safety
508/// configJson must be a valid null-terminated C string
509#[unsafe(no_mangle)]
510pub unsafe extern "C" fn SzConfigTool_listAttributes(
511    config_json: *const c_char,
512) -> SzConfigTool_result {
513    if config_json.is_null() {
514        set_error("Null pointer provided".to_string(), -1);
515        return SzConfigTool_result {
516            response: std::ptr::null_mut(),
517            returnCode: -1,
518        };
519    }
520
521    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
522        Ok(s) => s,
523        Err(e) => {
524            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
525            return SzConfigTool_result {
526                response: std::ptr::null_mut(),
527                returnCode: -1,
528            };
529        }
530    };
531
532    let result = crate::attributes::list_attributes(config).and_then(|vec| {
533        serde_json::to_string(&vec).map_err(|e| SzConfigError::JsonParse(e.to_string()))
534    });
535    handle_result!(result)
536}
537
538/// Set (update) an attribute's properties
539///
540/// # Safety
541/// configJson, attributeCode, and updatesJson must be valid null-terminated C strings
542#[unsafe(no_mangle)]
543pub unsafe extern "C" fn SzConfigTool_setAttribute(
544    config_json: *const c_char,
545    attribute_code: *const c_char,
546    updates_json: *const c_char,
547) -> SzConfigTool_result {
548    if config_json.is_null() || attribute_code.is_null() || updates_json.is_null() {
549        set_error("Null pointer provided".to_string(), -1);
550        return SzConfigTool_result {
551            response: std::ptr::null_mut(),
552            returnCode: -1,
553        };
554    }
555
556    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
557        Ok(s) => s,
558        Err(e) => {
559            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
560            return SzConfigTool_result {
561                response: std::ptr::null_mut(),
562                returnCode: -1,
563            };
564        }
565    };
566
567    let attr_code = match unsafe { CStr::from_ptr(attribute_code) }.to_str() {
568        Ok(s) => s,
569        Err(e) => {
570            set_error(format!("Invalid UTF-8 in attributeCode: {e}"), -1);
571            return SzConfigTool_result {
572                response: std::ptr::null_mut(),
573                returnCode: -1,
574            };
575        }
576    };
577
578    let updates_str = match unsafe { CStr::from_ptr(updates_json) }.to_str() {
579        Ok(s) => s,
580        Err(e) => {
581            set_error(format!("Invalid UTF-8 in updatesJson: {e}"), -1);
582            return SzConfigTool_result {
583                response: std::ptr::null_mut(),
584                returnCode: -1,
585            };
586        }
587    };
588
589    let updates: serde_json::Value = match serde_json::from_str(updates_str) {
590        Ok(v) => v,
591        Err(e) => {
592            set_error(format!("Invalid JSON in updatesJson: {e}"), -1);
593            return SzConfigTool_result {
594                response: std::ptr::null_mut(),
595                returnCode: -1,
596            };
597        }
598    };
599
600    // Build params with attribute from parameter and optional updates from JSON
601    let params = crate::attributes::SetAttributeParams {
602        attribute: attr_code,
603        internal: updates.get("internal").and_then(|v| v.as_str()),
604        required: updates.get("required").and_then(|v| v.as_str()),
605        default_value: updates.get("default").and_then(|v| v.as_str()),
606    };
607
608    handle_result!(crate::attributes::set_attribute(config, params))
609}
610
611// ============================================================================
612// Feature Functions (Phase 1: read-only)
613// ============================================================================
614// Note: add_feature/delete_feature require 15 parameters and JSON objects.
615// These will be added in Phase 2.
616
617/// Get a feature from the configuration (returns JSON object string)
618///
619/// # Safety
620/// configJson and featureCode must be valid null-terminated C strings
621#[unsafe(no_mangle)]
622pub unsafe extern "C" fn SzConfigTool_getFeature(
623    config_json: *const c_char,
624    feature_code: *const c_char,
625) -> SzConfigTool_result {
626    if config_json.is_null() || feature_code.is_null() {
627        set_error("Null pointer provided".to_string(), -1);
628        return SzConfigTool_result {
629            response: std::ptr::null_mut(),
630            returnCode: -1,
631        };
632    }
633
634    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
635        Ok(s) => s,
636        Err(e) => {
637            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
638            return SzConfigTool_result {
639                response: std::ptr::null_mut(),
640                returnCode: -1,
641            };
642        }
643    };
644
645    let feat_code = match unsafe { CStr::from_ptr(feature_code) }.to_str() {
646        Ok(s) => s,
647        Err(e) => {
648            set_error(format!("Invalid UTF-8 in featureCode: {e}"), -1);
649            return SzConfigTool_result {
650                response: std::ptr::null_mut(),
651                returnCode: -1,
652            };
653        }
654    };
655
656    let result = crate::features::get_feature(config, feat_code).and_then(|val| {
657        serde_json::to_string(&val).map_err(|e| SzConfigError::JsonParse(e.to_string()))
658    });
659    handle_result!(result)
660}
661
662/// List all features in the configuration (returns JSON array string)
663///
664/// # Safety
665/// configJson must be a valid null-terminated C string
666#[unsafe(no_mangle)]
667pub unsafe extern "C" fn SzConfigTool_listFeatures(
668    config_json: *const c_char,
669) -> SzConfigTool_result {
670    if config_json.is_null() {
671        set_error("Null pointer provided".to_string(), -1);
672        return SzConfigTool_result {
673            response: std::ptr::null_mut(),
674            returnCode: -1,
675        };
676    }
677
678    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
679        Ok(s) => s,
680        Err(e) => {
681            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
682            return SzConfigTool_result {
683                response: std::ptr::null_mut(),
684                returnCode: -1,
685            };
686        }
687    };
688
689    let result = crate::features::list_features(config).and_then(|vec| {
690        serde_json::to_string(&vec).map_err(|e| SzConfigError::JsonParse(e.to_string()))
691    });
692    handle_result!(result)
693}
694
695// ============================================================================
696// Element Functions (Phase 1: read-only)
697// ============================================================================
698// Note: add_element/delete_element require JSON object parameters.
699// These will be added in Phase 2.
700
701/// Get an element from the configuration (returns JSON object string)
702///
703/// # Safety
704/// configJson and elementCode must be valid null-terminated C strings
705#[unsafe(no_mangle)]
706pub unsafe extern "C" fn SzConfigTool_getElement(
707    config_json: *const c_char,
708    element_code: *const c_char,
709) -> SzConfigTool_result {
710    if config_json.is_null() || element_code.is_null() {
711        set_error("Null pointer provided".to_string(), -1);
712        return SzConfigTool_result {
713            response: std::ptr::null_mut(),
714            returnCode: -1,
715        };
716    }
717
718    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
719        Ok(s) => s,
720        Err(e) => {
721            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
722            return SzConfigTool_result {
723                response: std::ptr::null_mut(),
724                returnCode: -1,
725            };
726        }
727    };
728
729    let elem_code = match unsafe { CStr::from_ptr(element_code) }.to_str() {
730        Ok(s) => s,
731        Err(e) => {
732            set_error(format!("Invalid UTF-8 in elementCode: {e}"), -1);
733            return SzConfigTool_result {
734                response: std::ptr::null_mut(),
735                returnCode: -1,
736            };
737        }
738    };
739
740    let result = crate::elements::get_element(config, elem_code).and_then(|val| {
741        serde_json::to_string(&val).map_err(|e| SzConfigError::JsonParse(e.to_string()))
742    });
743    handle_result!(result)
744}
745
746/// List all elements in the configuration (returns JSON array string)
747///
748/// # Safety
749/// configJson must be a valid null-terminated C string
750#[unsafe(no_mangle)]
751pub unsafe extern "C" fn SzConfigTool_listElements(
752    config_json: *const c_char,
753) -> SzConfigTool_result {
754    if config_json.is_null() {
755        set_error("Null pointer provided".to_string(), -1);
756        return SzConfigTool_result {
757            response: std::ptr::null_mut(),
758            returnCode: -1,
759        };
760    }
761
762    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
763        Ok(s) => s,
764        Err(e) => {
765            set_error(format!("Invalid UTF-8 in configJson: {e}"), -1);
766            return SzConfigTool_result {
767                response: std::ptr::null_mut(),
768                returnCode: -1,
769            };
770        }
771    };
772
773    let result = crate::elements::list_elements(config).and_then(|vec| {
774        serde_json::to_string(&vec).map_err(|e| SzConfigError::JsonParse(e.to_string()))
775    });
776    handle_result!(result)
777}
778
779/// Set/update a fragment with JSON parameters
780#[unsafe(no_mangle)]
781pub unsafe extern "C" fn SzConfigTool_setFragmentWithJson(
782    config_json: *const c_char,
783    fragment_code: *const c_char,
784    fragment_config_json: *const c_char,
785) -> SzConfigTool_result {
786    if config_json.is_null() || fragment_code.is_null() || fragment_config_json.is_null() {
787        set_error("Required parameter is null".to_string(), -1);
788        return SzConfigTool_result {
789            response: std::ptr::null_mut(),
790            returnCode: -1,
791        };
792    }
793
794    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
795        Ok(s) => s,
796        Err(e) => {
797            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
798            return SzConfigTool_result {
799                response: std::ptr::null_mut(),
800                returnCode: -2,
801            };
802        }
803    };
804
805    let code = match unsafe { CStr::from_ptr(fragment_code) }.to_str() {
806        Ok(s) => s,
807        Err(e) => {
808            set_error(format!("Invalid UTF-8 in fragment_code: {e}"), -2);
809            return SzConfigTool_result {
810                response: std::ptr::null_mut(),
811                returnCode: -2,
812            };
813        }
814    };
815
816    let fragment_str = match unsafe { CStr::from_ptr(fragment_config_json) }.to_str() {
817        Ok(s) => s,
818        Err(e) => {
819            set_error(format!("Invalid UTF-8 in fragment_config_json: {e}"), -2);
820            return SzConfigTool_result {
821                response: std::ptr::null_mut(),
822                returnCode: -2,
823            };
824        }
825    };
826
827    let fragment_config: serde_json::Value = match serde_json::from_str(fragment_str) {
828        Ok(v) => v,
829        Err(e) => {
830            set_error(format!("Failed to parse fragment_config_json: {e}"), -3);
831            return SzConfigTool_result {
832                response: std::ptr::null_mut(),
833                returnCode: -3,
834            };
835        }
836    };
837
838    let result = crate::fragments::set_fragment(config, code, &fragment_config);
839    handle_result!(result)
840}
841
842/// Clone a generic plan
843#[unsafe(no_mangle)]
844pub unsafe extern "C" fn SzConfigTool_cloneGenericPlan(
845    config_json: *const c_char,
846    source_gplan_code: *const c_char,
847    new_gplan_code: *const c_char,
848    new_gplan_desc: *const c_char,
849) -> SzConfigTool_result {
850    if config_json.is_null() || source_gplan_code.is_null() || new_gplan_code.is_null() {
851        set_error("Required parameter is null".to_string(), -1);
852        return SzConfigTool_result {
853            response: std::ptr::null_mut(),
854            returnCode: -1,
855        };
856    }
857
858    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
859        Ok(s) => s,
860        Err(e) => {
861            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
862            return SzConfigTool_result {
863                response: std::ptr::null_mut(),
864                returnCode: -2,
865            };
866        }
867    };
868
869    let source_code = match unsafe { CStr::from_ptr(source_gplan_code) }.to_str() {
870        Ok(s) => s,
871        Err(e) => {
872            set_error(format!("Invalid UTF-8 in source_gplan_code: {e}"), -2);
873            return SzConfigTool_result {
874                response: std::ptr::null_mut(),
875                returnCode: -2,
876            };
877        }
878    };
879
880    let new_code = match unsafe { CStr::from_ptr(new_gplan_code) }.to_str() {
881        Ok(s) => s,
882        Err(e) => {
883            set_error(format!("Invalid UTF-8 in new_gplan_code: {e}"), -2);
884            return SzConfigTool_result {
885                response: std::ptr::null_mut(),
886                returnCode: -2,
887            };
888        }
889    };
890
891    let new_desc = if new_gplan_desc.is_null() {
892        None
893    } else {
894        match unsafe { CStr::from_ptr(new_gplan_desc) }.to_str() {
895            Ok(s) => Some(s),
896            Err(e) => {
897                set_error(format!("Invalid UTF-8 in new_gplan_desc: {e}"), -2);
898                return SzConfigTool_result {
899                    response: std::ptr::null_mut(),
900                    returnCode: -2,
901                };
902            }
903        }
904    };
905
906    match crate::generic_plans::clone_generic_plan(config, source_code, new_code, new_desc) {
907        Ok((modified_config, _gplan_id)) => match CString::new(modified_config) {
908            Ok(c_str) => {
909                clear_error();
910                SzConfigTool_result {
911                    response: c_str.into_raw(),
912                    returnCode: 0,
913                }
914            }
915            Err(e) => {
916                set_error(format!("Failed to convert result: {e}"), -4);
917                SzConfigTool_result {
918                    response: std::ptr::null_mut(),
919                    returnCode: -4,
920                }
921            }
922        },
923        Err(e) => {
924            set_error(e.to_string(), -5);
925            SzConfigTool_result {
926                response: std::ptr::null_mut(),
927                returnCode: -5,
928            }
929        }
930    }
931}
932
933/// Set/update a generic plan
934#[unsafe(no_mangle)]
935pub unsafe extern "C" fn SzConfigTool_setGenericPlan(
936    config_json: *const c_char,
937    gplan_code: *const c_char,
938    gplan_desc: *const c_char,
939) -> SzConfigTool_result {
940    if config_json.is_null() || gplan_code.is_null() || gplan_desc.is_null() {
941        set_error("Required parameter is null".to_string(), -1);
942        return SzConfigTool_result {
943            response: std::ptr::null_mut(),
944            returnCode: -1,
945        };
946    }
947
948    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
949        Ok(s) => s,
950        Err(e) => {
951            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
952            return SzConfigTool_result {
953                response: std::ptr::null_mut(),
954                returnCode: -2,
955            };
956        }
957    };
958
959    let code = match unsafe { CStr::from_ptr(gplan_code) }.to_str() {
960        Ok(s) => s,
961        Err(e) => {
962            set_error(format!("Invalid UTF-8 in gplan_code: {e}"), -2);
963            return SzConfigTool_result {
964                response: std::ptr::null_mut(),
965                returnCode: -2,
966            };
967        }
968    };
969
970    let desc = match unsafe { CStr::from_ptr(gplan_desc) }.to_str() {
971        Ok(s) => s,
972        Err(e) => {
973            set_error(format!("Invalid UTF-8 in gplan_desc: {e}"), -2);
974            return SzConfigTool_result {
975                response: std::ptr::null_mut(),
976                returnCode: -2,
977            };
978        }
979    };
980
981    match crate::generic_plans::set_generic_plan(config, code, desc) {
982        Ok((modified_config, _gplan_id, _was_created)) => match CString::new(modified_config) {
983            Ok(c_str) => {
984                clear_error();
985                SzConfigTool_result {
986                    response: c_str.into_raw(),
987                    returnCode: 0,
988                }
989            }
990            Err(e) => {
991                set_error(format!("Failed to convert result: {e}"), -4);
992                SzConfigTool_result {
993                    response: std::ptr::null_mut(),
994                    returnCode: -4,
995                }
996            }
997        },
998        Err(e) => {
999            set_error(e.to_string(), -5);
1000            SzConfigTool_result {
1001                response: std::ptr::null_mut(),
1002                returnCode: -5,
1003            }
1004        }
1005    }
1006}
1007
1008/// List generic plans
1009#[unsafe(no_mangle)]
1010pub unsafe extern "C" fn SzConfigTool_listGenericPlans(
1011    config_json: *const c_char,
1012    filter: *const c_char,
1013) -> SzConfigTool_result {
1014    if config_json.is_null() {
1015        set_error("Required parameter is null".to_string(), -1);
1016        return SzConfigTool_result {
1017            response: std::ptr::null_mut(),
1018            returnCode: -1,
1019        };
1020    }
1021
1022    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1023        Ok(s) => s,
1024        Err(e) => {
1025            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1026            return SzConfigTool_result {
1027                response: std::ptr::null_mut(),
1028                returnCode: -2,
1029            };
1030        }
1031    };
1032
1033    let filter_opt = if filter.is_null() {
1034        None
1035    } else {
1036        match unsafe { CStr::from_ptr(filter) }.to_str() {
1037            Ok(s) => Some(s),
1038            Err(e) => {
1039                set_error(format!("Invalid UTF-8 in filter: {e}"), -2);
1040                return SzConfigTool_result {
1041                    response: std::ptr::null_mut(),
1042                    returnCode: -2,
1043                };
1044            }
1045        }
1046    };
1047
1048    match crate::generic_plans::list_generic_plans(config, filter_opt) {
1049        Ok(list) => match serde_json::to_string(&list) {
1050            Ok(json_str) => match CString::new(json_str) {
1051                Ok(c_str) => {
1052                    clear_error();
1053                    SzConfigTool_result {
1054                        response: c_str.into_raw(),
1055                        returnCode: 0,
1056                    }
1057                }
1058                Err(e) => {
1059                    set_error(format!("Failed to convert result: {e}"), -4);
1060                    SzConfigTool_result {
1061                        response: std::ptr::null_mut(),
1062                        returnCode: -4,
1063                    }
1064                }
1065            },
1066            Err(e) => {
1067                set_error(format!("Failed to serialize result: {e}"), -3);
1068                SzConfigTool_result {
1069                    response: std::ptr::null_mut(),
1070                    returnCode: -3,
1071                }
1072            }
1073        },
1074        Err(e) => {
1075            set_error(e.to_string(), -5);
1076            SzConfigTool_result {
1077                response: std::ptr::null_mut(),
1078                returnCode: -5,
1079            }
1080        }
1081    }
1082}
1083
1084/// Add a name to the SSN_LAST4 hash
1085#[unsafe(no_mangle)]
1086pub unsafe extern "C" fn SzConfigTool_addToSsnLast4Hash(
1087    config_json: *const c_char,
1088    name: *const c_char,
1089) -> SzConfigTool_result {
1090    if config_json.is_null() || name.is_null() {
1091        set_error("Required parameter is null".to_string(), -1);
1092        return SzConfigTool_result {
1093            response: std::ptr::null_mut(),
1094            returnCode: -1,
1095        };
1096    }
1097
1098    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1099        Ok(s) => s,
1100        Err(e) => {
1101            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1102            return SzConfigTool_result {
1103                response: std::ptr::null_mut(),
1104                returnCode: -2,
1105            };
1106        }
1107    };
1108
1109    let name_str = match unsafe { CStr::from_ptr(name) }.to_str() {
1110        Ok(s) => s,
1111        Err(e) => {
1112            set_error(format!("Invalid UTF-8 in name: {e}"), -2);
1113            return SzConfigTool_result {
1114                response: std::ptr::null_mut(),
1115                returnCode: -2,
1116            };
1117        }
1118    };
1119
1120    let result = crate::hashes::add_to_ssn_last4_hash(config, name_str);
1121    handle_result!(result)
1122}
1123
1124/// Delete a name from the SSN_LAST4 hash
1125#[unsafe(no_mangle)]
1126pub unsafe extern "C" fn SzConfigTool_deleteFromSsnLast4Hash(
1127    config_json: *const c_char,
1128    name: *const c_char,
1129) -> SzConfigTool_result {
1130    if config_json.is_null() || name.is_null() {
1131        set_error("Required parameter is null".to_string(), -1);
1132        return SzConfigTool_result {
1133            response: std::ptr::null_mut(),
1134            returnCode: -1,
1135        };
1136    }
1137
1138    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1139        Ok(s) => s,
1140        Err(e) => {
1141            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1142            return SzConfigTool_result {
1143                response: std::ptr::null_mut(),
1144                returnCode: -2,
1145            };
1146        }
1147    };
1148
1149    let name_str = match unsafe { CStr::from_ptr(name) }.to_str() {
1150        Ok(s) => s,
1151        Err(e) => {
1152            set_error(format!("Invalid UTF-8 in name: {e}"), -2);
1153            return SzConfigTool_result {
1154                response: std::ptr::null_mut(),
1155                returnCode: -2,
1156            };
1157        }
1158    };
1159
1160    let result = crate::hashes::delete_from_ssn_last4_hash(config, name_str);
1161    handle_result!(result)
1162}
1163
1164/// Get a threshold by ID
1165#[unsafe(no_mangle)]
1166pub unsafe extern "C" fn SzConfigTool_getThreshold(
1167    config_json: *const c_char,
1168    threshold_id: i64,
1169) -> SzConfigTool_result {
1170    if config_json.is_null() {
1171        set_error("Required parameter is null".to_string(), -1);
1172        return SzConfigTool_result {
1173            response: std::ptr::null_mut(),
1174            returnCode: -1,
1175        };
1176    }
1177
1178    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1179        Ok(s) => s,
1180        Err(e) => {
1181            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1182            return SzConfigTool_result {
1183                response: std::ptr::null_mut(),
1184                returnCode: -2,
1185            };
1186        }
1187    };
1188
1189    match crate::thresholds::get_threshold(config, threshold_id) {
1190        Ok(record) => match serde_json::to_string(&record) {
1191            Ok(json_str) => match CString::new(json_str) {
1192                Ok(c_str) => {
1193                    clear_error();
1194                    SzConfigTool_result {
1195                        response: c_str.into_raw(),
1196                        returnCode: 0,
1197                    }
1198                }
1199                Err(e) => {
1200                    set_error(format!("Failed to convert result: {e}"), -4);
1201                    SzConfigTool_result {
1202                        response: std::ptr::null_mut(),
1203                        returnCode: -4,
1204                    }
1205                }
1206            },
1207            Err(e) => {
1208                set_error(format!("Failed to serialize result: {e}"), -3);
1209                SzConfigTool_result {
1210                    response: std::ptr::null_mut(),
1211                    returnCode: -3,
1212                }
1213            }
1214        },
1215        Err(e) => {
1216            set_error(e.to_string(), -5);
1217            SzConfigTool_result {
1218                response: std::ptr::null_mut(),
1219                returnCode: -5,
1220            }
1221        }
1222    }
1223}
1224
1225/// List system parameters
1226#[unsafe(no_mangle)]
1227pub unsafe extern "C" fn SzConfigTool_listSystemParameters(
1228    config_json: *const c_char,
1229) -> SzConfigTool_result {
1230    if config_json.is_null() {
1231        set_error("Required parameter is null".to_string(), -1);
1232        return SzConfigTool_result {
1233            response: std::ptr::null_mut(),
1234            returnCode: -1,
1235        };
1236    }
1237
1238    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1239        Ok(s) => s,
1240        Err(e) => {
1241            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1242            return SzConfigTool_result {
1243                response: std::ptr::null_mut(),
1244                returnCode: -2,
1245            };
1246        }
1247    };
1248
1249    match crate::system_params::list_system_parameters(config) {
1250        Ok(params) => match serde_json::to_string(&params) {
1251            Ok(json_str) => match CString::new(json_str) {
1252                Ok(c_str) => {
1253                    clear_error();
1254                    SzConfigTool_result {
1255                        response: c_str.into_raw(),
1256                        returnCode: 0,
1257                    }
1258                }
1259                Err(e) => {
1260                    set_error(format!("Failed to convert result: {e}"), -4);
1261                    SzConfigTool_result {
1262                        response: std::ptr::null_mut(),
1263                        returnCode: -4,
1264                    }
1265                }
1266            },
1267            Err(e) => {
1268                set_error(format!("Failed to serialize result: {e}"), -3);
1269                SzConfigTool_result {
1270                    response: std::ptr::null_mut(),
1271                    returnCode: -3,
1272                }
1273            }
1274        },
1275        Err(e) => {
1276            set_error(e.to_string(), -5);
1277            SzConfigTool_result {
1278                response: std::ptr::null_mut(),
1279                returnCode: -5,
1280            }
1281        }
1282    }
1283}
1284
1285/// Set a system parameter with JSON value
1286#[unsafe(no_mangle)]
1287pub unsafe extern "C" fn SzConfigTool_setSystemParameterWithJson(
1288    config_json: *const c_char,
1289    parameter_name: *const c_char,
1290    parameter_value_json: *const c_char,
1291) -> SzConfigTool_result {
1292    if config_json.is_null() || parameter_name.is_null() || parameter_value_json.is_null() {
1293        set_error("Required parameter is null".to_string(), -1);
1294        return SzConfigTool_result {
1295            response: std::ptr::null_mut(),
1296            returnCode: -1,
1297        };
1298    }
1299
1300    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1301        Ok(s) => s,
1302        Err(e) => {
1303            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1304            return SzConfigTool_result {
1305                response: std::ptr::null_mut(),
1306                returnCode: -2,
1307            };
1308        }
1309    };
1310
1311    let param_name = match unsafe { CStr::from_ptr(parameter_name) }.to_str() {
1312        Ok(s) => s,
1313        Err(e) => {
1314            set_error(format!("Invalid UTF-8 in parameter_name: {e}"), -2);
1315            return SzConfigTool_result {
1316                response: std::ptr::null_mut(),
1317                returnCode: -2,
1318            };
1319        }
1320    };
1321
1322    let value_str = match unsafe { CStr::from_ptr(parameter_value_json) }.to_str() {
1323        Ok(s) => s,
1324        Err(e) => {
1325            set_error(format!("Invalid UTF-8 in parameter_value_json: {e}"), -2);
1326            return SzConfigTool_result {
1327                response: std::ptr::null_mut(),
1328                returnCode: -2,
1329            };
1330        }
1331    };
1332
1333    let param_value: serde_json::Value = match serde_json::from_str(value_str) {
1334        Ok(v) => v,
1335        Err(e) => {
1336            set_error(format!("Failed to parse parameter_value_json: {e}"), -3);
1337            return SzConfigTool_result {
1338                response: std::ptr::null_mut(),
1339                returnCode: -3,
1340            };
1341        }
1342    };
1343
1344    let result = crate::system_params::set_system_parameter(config, param_name, &param_value);
1345    handle_result!(result)
1346}
1347
1348/// Get the configuration version
1349#[unsafe(no_mangle)]
1350pub unsafe extern "C" fn SzConfigTool_getVersion(
1351    config_json: *const c_char,
1352) -> SzConfigTool_result {
1353    if config_json.is_null() {
1354        set_error("Required parameter is null".to_string(), -1);
1355        return SzConfigTool_result {
1356            response: std::ptr::null_mut(),
1357            returnCode: -1,
1358        };
1359    }
1360
1361    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1362        Ok(s) => s,
1363        Err(e) => {
1364            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1365            return SzConfigTool_result {
1366                response: std::ptr::null_mut(),
1367                returnCode: -2,
1368            };
1369        }
1370    };
1371
1372    match crate::versioning::get_version(config) {
1373        Ok(version) => match CString::new(version) {
1374            Ok(c_str) => {
1375                clear_error();
1376                SzConfigTool_result {
1377                    response: c_str.into_raw(),
1378                    returnCode: 0,
1379                }
1380            }
1381            Err(e) => {
1382                set_error(format!("Failed to convert result: {e}"), -4);
1383                SzConfigTool_result {
1384                    response: std::ptr::null_mut(),
1385                    returnCode: -4,
1386                }
1387            }
1388        },
1389        Err(e) => {
1390            set_error(e.to_string(), -5);
1391            SzConfigTool_result {
1392                response: std::ptr::null_mut(),
1393                returnCode: -5,
1394            }
1395        }
1396    }
1397}
1398
1399/// Get the compatibility version
1400#[unsafe(no_mangle)]
1401pub unsafe extern "C" fn SzConfigTool_getCompatibilityVersion(
1402    config_json: *const c_char,
1403) -> SzConfigTool_result {
1404    if config_json.is_null() {
1405        set_error("Required parameter is null".to_string(), -1);
1406        return SzConfigTool_result {
1407            response: std::ptr::null_mut(),
1408            returnCode: -1,
1409        };
1410    }
1411
1412    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1413        Ok(s) => s,
1414        Err(e) => {
1415            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1416            return SzConfigTool_result {
1417                response: std::ptr::null_mut(),
1418                returnCode: -2,
1419            };
1420        }
1421    };
1422
1423    match crate::versioning::get_compatibility_version(config) {
1424        Ok(version) => match CString::new(version) {
1425            Ok(c_str) => {
1426                clear_error();
1427                SzConfigTool_result {
1428                    response: c_str.into_raw(),
1429                    returnCode: 0,
1430                }
1431            }
1432            Err(e) => {
1433                set_error(format!("Failed to convert result: {e}"), -4);
1434                SzConfigTool_result {
1435                    response: std::ptr::null_mut(),
1436                    returnCode: -4,
1437                }
1438            }
1439        },
1440        Err(e) => {
1441            set_error(e.to_string(), -5);
1442            SzConfigTool_result {
1443                response: std::ptr::null_mut(),
1444                returnCode: -5,
1445            }
1446        }
1447    }
1448}
1449
1450/// Update the compatibility version
1451#[unsafe(no_mangle)]
1452pub unsafe extern "C" fn SzConfigTool_updateCompatibilityVersion(
1453    config_json: *const c_char,
1454    new_version: *const c_char,
1455) -> SzConfigTool_result {
1456    if config_json.is_null() || new_version.is_null() {
1457        set_error("Required parameter is null".to_string(), -1);
1458        return SzConfigTool_result {
1459            response: std::ptr::null_mut(),
1460            returnCode: -1,
1461        };
1462    }
1463
1464    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1465        Ok(s) => s,
1466        Err(e) => {
1467            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1468            return SzConfigTool_result {
1469                response: std::ptr::null_mut(),
1470                returnCode: -2,
1471            };
1472        }
1473    };
1474
1475    let version = match unsafe { CStr::from_ptr(new_version) }.to_str() {
1476        Ok(s) => s,
1477        Err(e) => {
1478            set_error(format!("Invalid UTF-8 in new_version: {e}"), -2);
1479            return SzConfigTool_result {
1480                response: std::ptr::null_mut(),
1481                returnCode: -2,
1482            };
1483        }
1484    };
1485
1486    let result = crate::versioning::update_compatibility_version(config, version);
1487    handle_result!(result)
1488}
1489
1490/// Update the feature version
1491#[unsafe(no_mangle)]
1492pub unsafe extern "C" fn SzConfigTool_updateFeatureVersion(
1493    config_json: *const c_char,
1494    version: *const c_char,
1495) -> SzConfigTool_result {
1496    if config_json.is_null() || version.is_null() {
1497        set_error("Required parameter is null".to_string(), -1);
1498        return SzConfigTool_result {
1499            response: std::ptr::null_mut(),
1500            returnCode: -1,
1501        };
1502    }
1503
1504    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1505        Ok(s) => s,
1506        Err(e) => {
1507            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1508            return SzConfigTool_result {
1509                response: std::ptr::null_mut(),
1510                returnCode: -2,
1511            };
1512        }
1513    };
1514
1515    let version_str = match unsafe { CStr::from_ptr(version) }.to_str() {
1516        Ok(s) => s,
1517        Err(e) => {
1518            set_error(format!("Invalid UTF-8 in version: {e}"), -2);
1519            return SzConfigTool_result {
1520                response: std::ptr::null_mut(),
1521                returnCode: -2,
1522            };
1523        }
1524    };
1525
1526    let result = crate::features::update_feature_version(config, version_str);
1527    handle_result!(result)
1528}
1529
1530/// Verify compatibility version
1531#[unsafe(no_mangle)]
1532pub unsafe extern "C" fn SzConfigTool_verifyCompatibilityVersion(
1533    config_json: *const c_char,
1534    expected_version: *const c_char,
1535) -> SzConfigTool_result {
1536    if config_json.is_null() || expected_version.is_null() {
1537        set_error("Required parameter is null".to_string(), -1);
1538        return SzConfigTool_result {
1539            response: std::ptr::null_mut(),
1540            returnCode: -1,
1541        };
1542    }
1543
1544    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1545        Ok(s) => s,
1546        Err(e) => {
1547            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1548            return SzConfigTool_result {
1549                response: std::ptr::null_mut(),
1550                returnCode: -2,
1551            };
1552        }
1553    };
1554
1555    let version = match unsafe { CStr::from_ptr(expected_version) }.to_str() {
1556        Ok(s) => s,
1557        Err(e) => {
1558            set_error(format!("Invalid UTF-8 in expected_version: {e}"), -2);
1559            return SzConfigTool_result {
1560                response: std::ptr::null_mut(),
1561                returnCode: -2,
1562            };
1563        }
1564    };
1565
1566    match crate::versioning::verify_compatibility_version(config, version) {
1567        Ok((message, _matches)) => match CString::new(message) {
1568            Ok(c_str) => {
1569                clear_error();
1570                SzConfigTool_result {
1571                    response: c_str.into_raw(),
1572                    returnCode: 0,
1573                }
1574            }
1575            Err(e) => {
1576                set_error(format!("Failed to convert result: {e}"), -4);
1577                SzConfigTool_result {
1578                    response: std::ptr::null_mut(),
1579                    returnCode: -4,
1580                }
1581            }
1582        },
1583        Err(e) => {
1584            set_error(e.to_string(), -5);
1585            SzConfigTool_result {
1586                response: std::ptr::null_mut(),
1587                returnCode: -5,
1588            }
1589        }
1590    }
1591}
1592
1593/// Add a config section
1594#[unsafe(no_mangle)]
1595pub unsafe extern "C" fn SzConfigTool_addConfigSection(
1596    config_json: *const c_char,
1597    section_name: *const c_char,
1598) -> SzConfigTool_result {
1599    if config_json.is_null() || section_name.is_null() {
1600        set_error("Required parameter is null".to_string(), -1);
1601        return SzConfigTool_result {
1602            response: std::ptr::null_mut(),
1603            returnCode: -1,
1604        };
1605    }
1606
1607    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1608        Ok(s) => s,
1609        Err(e) => {
1610            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1611            return SzConfigTool_result {
1612                response: std::ptr::null_mut(),
1613                returnCode: -2,
1614            };
1615        }
1616    };
1617
1618    let section = match unsafe { CStr::from_ptr(section_name) }.to_str() {
1619        Ok(s) => s,
1620        Err(e) => {
1621            set_error(format!("Invalid UTF-8 in section_name: {e}"), -2);
1622            return SzConfigTool_result {
1623                response: std::ptr::null_mut(),
1624                returnCode: -2,
1625            };
1626        }
1627    };
1628
1629    let result = crate::config_sections::add_config_section(config, section);
1630    handle_result!(result)
1631}
1632
1633/// Remove a config section
1634#[unsafe(no_mangle)]
1635pub unsafe extern "C" fn SzConfigTool_removeConfigSection(
1636    config_json: *const c_char,
1637    section_name: *const c_char,
1638) -> SzConfigTool_result {
1639    if config_json.is_null() || section_name.is_null() {
1640        set_error("Required parameter is null".to_string(), -1);
1641        return SzConfigTool_result {
1642            response: std::ptr::null_mut(),
1643            returnCode: -1,
1644        };
1645    }
1646
1647    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1648        Ok(s) => s,
1649        Err(e) => {
1650            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1651            return SzConfigTool_result {
1652                response: std::ptr::null_mut(),
1653                returnCode: -2,
1654            };
1655        }
1656    };
1657
1658    let section = match unsafe { CStr::from_ptr(section_name) }.to_str() {
1659        Ok(s) => s,
1660        Err(e) => {
1661            set_error(format!("Invalid UTF-8 in section_name: {e}"), -2);
1662            return SzConfigTool_result {
1663                response: std::ptr::null_mut(),
1664                returnCode: -2,
1665            };
1666        }
1667    };
1668
1669    let result = crate::config_sections::remove_config_section(config, section);
1670    handle_result!(result)
1671}
1672
1673/// Get a config section
1674#[unsafe(no_mangle)]
1675pub unsafe extern "C" fn SzConfigTool_getConfigSection(
1676    config_json: *const c_char,
1677    section_name: *const c_char,
1678    filter: *const c_char,
1679) -> SzConfigTool_result {
1680    if config_json.is_null() || section_name.is_null() {
1681        set_error("Required parameter is null".to_string(), -1);
1682        return SzConfigTool_result {
1683            response: std::ptr::null_mut(),
1684            returnCode: -1,
1685        };
1686    }
1687
1688    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1689        Ok(s) => s,
1690        Err(e) => {
1691            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1692            return SzConfigTool_result {
1693                response: std::ptr::null_mut(),
1694                returnCode: -2,
1695            };
1696        }
1697    };
1698
1699    let section = match unsafe { CStr::from_ptr(section_name) }.to_str() {
1700        Ok(s) => s,
1701        Err(e) => {
1702            set_error(format!("Invalid UTF-8 in section_name: {e}"), -2);
1703            return SzConfigTool_result {
1704                response: std::ptr::null_mut(),
1705                returnCode: -2,
1706            };
1707        }
1708    };
1709
1710    let filter_opt = if filter.is_null() {
1711        None
1712    } else {
1713        match unsafe { CStr::from_ptr(filter) }.to_str() {
1714            Ok(s) => Some(s),
1715            Err(e) => {
1716                set_error(format!("Invalid UTF-8 in filter: {e}"), -2);
1717                return SzConfigTool_result {
1718                    response: std::ptr::null_mut(),
1719                    returnCode: -2,
1720                };
1721            }
1722        }
1723    };
1724
1725    match crate::config_sections::get_config_section(config, section, filter_opt) {
1726        Ok(section_data) => match serde_json::to_string(&section_data) {
1727            Ok(json_str) => match CString::new(json_str) {
1728                Ok(c_str) => {
1729                    clear_error();
1730                    SzConfigTool_result {
1731                        response: c_str.into_raw(),
1732                        returnCode: 0,
1733                    }
1734                }
1735                Err(e) => {
1736                    set_error(format!("Failed to convert result: {e}"), -4);
1737                    SzConfigTool_result {
1738                        response: std::ptr::null_mut(),
1739                        returnCode: -4,
1740                    }
1741                }
1742            },
1743            Err(e) => {
1744                set_error(format!("Failed to serialize result: {e}"), -3);
1745                SzConfigTool_result {
1746                    response: std::ptr::null_mut(),
1747                    returnCode: -3,
1748                }
1749            }
1750        },
1751        Err(e) => {
1752            set_error(e.to_string(), -5);
1753            SzConfigTool_result {
1754                response: std::ptr::null_mut(),
1755                returnCode: -5,
1756            }
1757        }
1758    }
1759}
1760
1761/// List all config sections
1762#[unsafe(no_mangle)]
1763pub unsafe extern "C" fn SzConfigTool_listConfigSections(
1764    config_json: *const c_char,
1765) -> SzConfigTool_result {
1766    if config_json.is_null() {
1767        set_error("Required parameter is null".to_string(), -1);
1768        return SzConfigTool_result {
1769            response: std::ptr::null_mut(),
1770            returnCode: -1,
1771        };
1772    }
1773
1774    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1775        Ok(s) => s,
1776        Err(e) => {
1777            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1778            return SzConfigTool_result {
1779                response: std::ptr::null_mut(),
1780                returnCode: -2,
1781            };
1782        }
1783    };
1784
1785    match crate::config_sections::list_config_sections(config) {
1786        Ok(sections) => match serde_json::to_string(&sections) {
1787            Ok(json_str) => match CString::new(json_str) {
1788                Ok(c_str) => {
1789                    clear_error();
1790                    SzConfigTool_result {
1791                        response: c_str.into_raw(),
1792                        returnCode: 0,
1793                    }
1794                }
1795                Err(e) => {
1796                    set_error(format!("Failed to convert result: {e}"), -4);
1797                    SzConfigTool_result {
1798                        response: std::ptr::null_mut(),
1799                        returnCode: -4,
1800                    }
1801                }
1802            },
1803            Err(e) => {
1804                set_error(format!("Failed to serialize result: {e}"), -3);
1805                SzConfigTool_result {
1806                    response: std::ptr::null_mut(),
1807                    returnCode: -3,
1808                }
1809            }
1810        },
1811        Err(e) => {
1812            set_error(e.to_string(), -5);
1813            SzConfigTool_result {
1814                response: std::ptr::null_mut(),
1815                returnCode: -5,
1816            }
1817        }
1818    }
1819}
1820
1821/// Add a field to a config section (returns tuple)
1822#[unsafe(no_mangle)]
1823pub unsafe extern "C" fn SzConfigTool_addConfigSectionField(
1824    config_json: *const c_char,
1825    section_name: *const c_char,
1826    field_name: *const c_char,
1827    field_value_json: *const c_char,
1828) -> SzConfigTool_result {
1829    if config_json.is_null()
1830        || section_name.is_null()
1831        || field_name.is_null()
1832        || field_value_json.is_null()
1833    {
1834        set_error("Required parameter is null".to_string(), -1);
1835        return SzConfigTool_result {
1836            response: std::ptr::null_mut(),
1837            returnCode: -1,
1838        };
1839    }
1840
1841    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1842        Ok(s) => s,
1843        Err(e) => {
1844            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1845            return SzConfigTool_result {
1846                response: std::ptr::null_mut(),
1847                returnCode: -2,
1848            };
1849        }
1850    };
1851
1852    let section = match unsafe { CStr::from_ptr(section_name) }.to_str() {
1853        Ok(s) => s,
1854        Err(e) => {
1855            set_error(format!("Invalid UTF-8 in section_name: {e}"), -2);
1856            return SzConfigTool_result {
1857                response: std::ptr::null_mut(),
1858                returnCode: -2,
1859            };
1860        }
1861    };
1862
1863    let field = match unsafe { CStr::from_ptr(field_name) }.to_str() {
1864        Ok(s) => s,
1865        Err(e) => {
1866            set_error(format!("Invalid UTF-8 in field_name: {e}"), -2);
1867            return SzConfigTool_result {
1868                response: std::ptr::null_mut(),
1869                returnCode: -2,
1870            };
1871        }
1872    };
1873
1874    let value_str = match unsafe { CStr::from_ptr(field_value_json) }.to_str() {
1875        Ok(s) => s,
1876        Err(e) => {
1877            set_error(format!("Invalid UTF-8 in field_value_json: {e}"), -2);
1878            return SzConfigTool_result {
1879                response: std::ptr::null_mut(),
1880                returnCode: -2,
1881            };
1882        }
1883    };
1884
1885    let field_value: serde_json::Value = match serde_json::from_str(value_str) {
1886        Ok(v) => v,
1887        Err(e) => {
1888            set_error(format!("Failed to parse field_value_json: {e}"), -3);
1889            return SzConfigTool_result {
1890                response: std::ptr::null_mut(),
1891                returnCode: -3,
1892            };
1893        }
1894    };
1895
1896    match crate::config_sections::add_config_section_field(config, section, field, &field_value) {
1897        Ok((modified_config, _count)) => match CString::new(modified_config) {
1898            Ok(c_str) => {
1899                clear_error();
1900                SzConfigTool_result {
1901                    response: c_str.into_raw(),
1902                    returnCode: 0,
1903                }
1904            }
1905            Err(e) => {
1906                set_error(format!("Failed to convert result: {e}"), -4);
1907                SzConfigTool_result {
1908                    response: std::ptr::null_mut(),
1909                    returnCode: -4,
1910                }
1911            }
1912        },
1913        Err(e) => {
1914            set_error(e.to_string(), -5);
1915            SzConfigTool_result {
1916                response: std::ptr::null_mut(),
1917                returnCode: -5,
1918            }
1919        }
1920    }
1921}
1922
1923/// Remove a field from a config section (returns tuple)
1924#[unsafe(no_mangle)]
1925pub unsafe extern "C" fn SzConfigTool_removeConfigSectionField(
1926    config_json: *const c_char,
1927    section_name: *const c_char,
1928    field_name: *const c_char,
1929) -> SzConfigTool_result {
1930    if config_json.is_null() || section_name.is_null() || field_name.is_null() {
1931        set_error("Required parameter is null".to_string(), -1);
1932        return SzConfigTool_result {
1933            response: std::ptr::null_mut(),
1934            returnCode: -1,
1935        };
1936    }
1937
1938    let config = match unsafe { CStr::from_ptr(config_json) }.to_str() {
1939        Ok(s) => s,
1940        Err(e) => {
1941            set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
1942            return SzConfigTool_result {
1943                response: std::ptr::null_mut(),
1944                returnCode: -2,
1945            };
1946        }
1947    };
1948
1949    let section = match unsafe { CStr::from_ptr(section_name) }.to_str() {
1950        Ok(s) => s,
1951        Err(e) => {
1952            set_error(format!("Invalid UTF-8 in section_name: {e}"), -2);
1953            return SzConfigTool_result {
1954                response: std::ptr::null_mut(),
1955                returnCode: -2,
1956            };
1957        }
1958    };
1959
1960    let field = match unsafe { CStr::from_ptr(field_name) }.to_str() {
1961        Ok(s) => s,
1962        Err(e) => {
1963            set_error(format!("Invalid UTF-8 in field_name: {e}"), -2);
1964            return SzConfigTool_result {
1965                response: std::ptr::null_mut(),
1966                returnCode: -2,
1967            };
1968        }
1969    };
1970
1971    match crate::config_sections::remove_config_section_field(config, section, field) {
1972        Ok((modified_config, _count)) => match CString::new(modified_config) {
1973            Ok(c_str) => {
1974                clear_error();
1975                SzConfigTool_result {
1976                    response: c_str.into_raw(),
1977                    returnCode: 0,
1978                }
1979            }
1980            Err(e) => {
1981                set_error(format!("Failed to convert result: {e}"), -4);
1982                SzConfigTool_result {
1983                    response: std::ptr::null_mut(),
1984                    returnCode: -4,
1985                }
1986            }
1987        },
1988        Err(e) => {
1989            set_error(e.to_string(), -5);
1990            SzConfigTool_result {
1991                response: std::ptr::null_mut(),
1992                returnCode: -5,
1993            }
1994        }
1995    }
1996}
1997
1998/* ============================================================================
1999 * Rule Functions (Batch 4)
2000 * ============================================================================ */
2001
2002/// Add a rule with JSON configuration
2003#[unsafe(no_mangle)]
2004pub extern "C" fn SzConfigTool_addRule(
2005    config_json: *const c_char,
2006    rule_json: *const c_char,
2007) -> SzConfigTool_result {
2008    let config = unsafe {
2009        if config_json.is_null() {
2010            set_error("config_json is null".to_string(), -1);
2011            return SzConfigTool_result {
2012                response: std::ptr::null_mut(),
2013                returnCode: -1,
2014            };
2015        }
2016        match CStr::from_ptr(config_json).to_str() {
2017            Ok(s) => s,
2018            Err(e) => {
2019                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2020                return SzConfigTool_result {
2021                    response: std::ptr::null_mut(),
2022                    returnCode: -2,
2023                };
2024            }
2025        }
2026    };
2027
2028    let rule_config = unsafe {
2029        if rule_json.is_null() {
2030            set_error("rule_json is null".to_string(), -1);
2031            return SzConfigTool_result {
2032                response: std::ptr::null_mut(),
2033                returnCode: -1,
2034            };
2035        }
2036        match CStr::from_ptr(rule_json).to_str() {
2037            Ok(s) => s,
2038            Err(e) => {
2039                set_error(format!("Invalid UTF-8 in rule_json: {e}"), -2);
2040                return SzConfigTool_result {
2041                    response: std::ptr::null_mut(),
2042                    returnCode: -2,
2043                };
2044            }
2045        }
2046    };
2047
2048    let rule_value: serde_json::Value = match serde_json::from_str(rule_config) {
2049        Ok(v) => v,
2050        Err(e) => {
2051            set_error(format!("Invalid JSON in rule_json: {e}"), -3);
2052            return SzConfigTool_result {
2053                response: std::ptr::null_mut(),
2054                returnCode: -3,
2055            };
2056        }
2057    };
2058
2059    let id = rule_value
2060        .get("ERRULE_ID")
2061        .and_then(|v| v.as_i64())
2062        .unwrap_or(0);
2063    match crate::rules::add_rule(config, id, &rule_value) {
2064        Ok((modified_config, _rule_id)) => match CString::new(modified_config) {
2065            Ok(c_str) => {
2066                clear_error();
2067                SzConfigTool_result {
2068                    response: c_str.into_raw(),
2069                    returnCode: 0,
2070                }
2071            }
2072            Err(e) => {
2073                set_error(format!("Failed to convert result: {e}"), -4);
2074                SzConfigTool_result {
2075                    response: std::ptr::null_mut(),
2076                    returnCode: -4,
2077                }
2078            }
2079        },
2080        Err(e) => {
2081            set_error(e.to_string(), -5);
2082            SzConfigTool_result {
2083                response: std::ptr::null_mut(),
2084                returnCode: -5,
2085            }
2086        }
2087    }
2088}
2089
2090/// Delete a rule
2091#[unsafe(no_mangle)]
2092pub extern "C" fn SzConfigTool_deleteRule(
2093    config_json: *const c_char,
2094    rule_code: *const c_char,
2095) -> SzConfigTool_result {
2096    let config = unsafe {
2097        if config_json.is_null() {
2098            set_error("config_json is null".to_string(), -1);
2099            return SzConfigTool_result {
2100                response: std::ptr::null_mut(),
2101                returnCode: -1,
2102            };
2103        }
2104        match CStr::from_ptr(config_json).to_str() {
2105            Ok(s) => s,
2106            Err(e) => {
2107                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2108                return SzConfigTool_result {
2109                    response: std::ptr::null_mut(),
2110                    returnCode: -2,
2111                };
2112            }
2113        }
2114    };
2115
2116    let code = unsafe {
2117        if rule_code.is_null() {
2118            set_error("rule_code is null".to_string(), -1);
2119            return SzConfigTool_result {
2120                response: std::ptr::null_mut(),
2121                returnCode: -1,
2122            };
2123        }
2124        match CStr::from_ptr(rule_code).to_str() {
2125            Ok(s) => s,
2126            Err(e) => {
2127                set_error(format!("Invalid UTF-8 in rule_code: {e}"), -2);
2128                return SzConfigTool_result {
2129                    response: std::ptr::null_mut(),
2130                    returnCode: -2,
2131                };
2132            }
2133        }
2134    };
2135
2136    handle_result!(crate::rules::delete_rule(config, code))
2137}
2138
2139/// Get a rule by code or ID
2140#[unsafe(no_mangle)]
2141pub extern "C" fn SzConfigTool_getRule(
2142    config_json: *const c_char,
2143    code_or_id: *const c_char,
2144) -> SzConfigTool_result {
2145    let config = unsafe {
2146        if config_json.is_null() {
2147            set_error("config_json is null".to_string(), -1);
2148            return SzConfigTool_result {
2149                response: std::ptr::null_mut(),
2150                returnCode: -1,
2151            };
2152        }
2153        match CStr::from_ptr(config_json).to_str() {
2154            Ok(s) => s,
2155            Err(e) => {
2156                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2157                return SzConfigTool_result {
2158                    response: std::ptr::null_mut(),
2159                    returnCode: -2,
2160                };
2161            }
2162        }
2163    };
2164
2165    let identifier = unsafe {
2166        if code_or_id.is_null() {
2167            set_error("code_or_id is null".to_string(), -1);
2168            return SzConfigTool_result {
2169                response: std::ptr::null_mut(),
2170                returnCode: -1,
2171            };
2172        }
2173        match CStr::from_ptr(code_or_id).to_str() {
2174            Ok(s) => s,
2175            Err(e) => {
2176                set_error(format!("Invalid UTF-8 in code_or_id: {e}"), -2);
2177                return SzConfigTool_result {
2178                    response: std::ptr::null_mut(),
2179                    returnCode: -2,
2180                };
2181            }
2182        }
2183    };
2184
2185    match crate::rules::get_rule(config, identifier) {
2186        Ok(rule_json_value) => {
2187            let rule_str = serde_json::to_string(&rule_json_value)
2188                .unwrap_or_else(|e| format!("{{\"error\": \"Failed to serialize: {e}\"}}"));
2189            match CString::new(rule_str) {
2190                Ok(c_str) => {
2191                    clear_error();
2192                    SzConfigTool_result {
2193                        response: c_str.into_raw(),
2194                        returnCode: 0,
2195                    }
2196                }
2197                Err(e) => {
2198                    set_error(format!("Failed to convert result: {e}"), -4);
2199                    SzConfigTool_result {
2200                        response: std::ptr::null_mut(),
2201                        returnCode: -4,
2202                    }
2203                }
2204            }
2205        }
2206        Err(e) => {
2207            set_error(e.to_string(), -5);
2208            SzConfigTool_result {
2209                response: std::ptr::null_mut(),
2210                returnCode: -5,
2211            }
2212        }
2213    }
2214}
2215
2216/// List all rules
2217#[unsafe(no_mangle)]
2218pub extern "C" fn SzConfigTool_listRules(config_json: *const c_char) -> SzConfigTool_result {
2219    let config = unsafe {
2220        if config_json.is_null() {
2221            set_error("config_json is null".to_string(), -1);
2222            return SzConfigTool_result {
2223                response: std::ptr::null_mut(),
2224                returnCode: -1,
2225            };
2226        }
2227        match CStr::from_ptr(config_json).to_str() {
2228            Ok(s) => s,
2229            Err(e) => {
2230                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2231                return SzConfigTool_result {
2232                    response: std::ptr::null_mut(),
2233                    returnCode: -2,
2234                };
2235            }
2236        }
2237    };
2238
2239    match crate::rules::list_rules(config) {
2240        Ok(rules_vec) => {
2241            let rules_str = serde_json::to_string(&rules_vec)
2242                .unwrap_or_else(|e| format!("{{\"error\": \"Failed to serialize: {e}\"}}"));
2243            match CString::new(rules_str) {
2244                Ok(c_str) => {
2245                    clear_error();
2246                    SzConfigTool_result {
2247                        response: c_str.into_raw(),
2248                        returnCode: 0,
2249                    }
2250                }
2251                Err(e) => {
2252                    set_error(format!("Failed to convert result: {e}"), -4);
2253                    SzConfigTool_result {
2254                        response: std::ptr::null_mut(),
2255                        returnCode: -4,
2256                    }
2257                }
2258            }
2259        }
2260        Err(e) => {
2261            set_error(e.to_string(), -5);
2262            SzConfigTool_result {
2263                response: std::ptr::null_mut(),
2264                returnCode: -5,
2265            }
2266        }
2267    }
2268}
2269
2270/// Set/update a rule with JSON configuration
2271#[unsafe(no_mangle)]
2272pub extern "C" fn SzConfigTool_setRule(
2273    config_json: *const c_char,
2274    rule_code: *const c_char,
2275    rule_json: *const c_char,
2276) -> SzConfigTool_result {
2277    let config = unsafe {
2278        if config_json.is_null() {
2279            set_error("config_json is null".to_string(), -1);
2280            return SzConfigTool_result {
2281                response: std::ptr::null_mut(),
2282                returnCode: -1,
2283            };
2284        }
2285        match CStr::from_ptr(config_json).to_str() {
2286            Ok(s) => s,
2287            Err(e) => {
2288                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2289                return SzConfigTool_result {
2290                    response: std::ptr::null_mut(),
2291                    returnCode: -2,
2292                };
2293            }
2294        }
2295    };
2296
2297    let code = unsafe {
2298        if rule_code.is_null() {
2299            set_error("rule_code is null".to_string(), -1);
2300            return SzConfigTool_result {
2301                response: std::ptr::null_mut(),
2302                returnCode: -1,
2303            };
2304        }
2305        match CStr::from_ptr(rule_code).to_str() {
2306            Ok(s) => s,
2307            Err(e) => {
2308                set_error(format!("Invalid UTF-8 in rule_code: {e}"), -2);
2309                return SzConfigTool_result {
2310                    response: std::ptr::null_mut(),
2311                    returnCode: -2,
2312                };
2313            }
2314        }
2315    };
2316
2317    let rule_config = unsafe {
2318        if rule_json.is_null() {
2319            set_error("rule_json is null".to_string(), -1);
2320            return SzConfigTool_result {
2321                response: std::ptr::null_mut(),
2322                returnCode: -1,
2323            };
2324        }
2325        match CStr::from_ptr(rule_json).to_str() {
2326            Ok(s) => s,
2327            Err(e) => {
2328                set_error(format!("Invalid UTF-8 in rule_json: {e}"), -2);
2329                return SzConfigTool_result {
2330                    response: std::ptr::null_mut(),
2331                    returnCode: -2,
2332                };
2333            }
2334        }
2335    };
2336
2337    let rule_value: serde_json::Value = match serde_json::from_str(rule_config) {
2338        Ok(v) => v,
2339        Err(e) => {
2340            set_error(format!("Invalid JSON in rule_json: {e}"), -3);
2341            return SzConfigTool_result {
2342                response: std::ptr::null_mut(),
2343                returnCode: -3,
2344            };
2345        }
2346    };
2347
2348    // Build params from code and JSON config
2349    let params = crate::rules::SetRuleParams {
2350        code,
2351        resolve: rule_value
2352            .get("resolve")
2353            .and_then(|v| v.as_str())
2354            .or_else(|| rule_value.get("RESOLVE").and_then(|v| v.as_str())),
2355        relate: rule_value
2356            .get("relate")
2357            .and_then(|v| v.as_str())
2358            .or_else(|| rule_value.get("RELATE").and_then(|v| v.as_str())),
2359        rtype_id: rule_value
2360            .get("rtypeId")
2361            .and_then(|v| v.as_i64())
2362            .or_else(|| rule_value.get("RTYPE_ID").and_then(|v| v.as_i64())),
2363        fragment: None,
2364        disqualifier: None,
2365        tier: None,
2366    };
2367
2368    handle_result!(crate::rules::set_rule(config, params))
2369}
2370
2371/* ============================================================================
2372 * Standardize Function Operations (Batch 5a)
2373 * ============================================================================ */
2374
2375/// Add a standardize function
2376#[unsafe(no_mangle)]
2377pub extern "C" fn SzConfigTool_addStandardizeFunction(
2378    config_json: *const c_char,
2379    sfunc_code: *const c_char,
2380    connect_str: *const c_char,
2381    sfunc_desc: *const c_char,
2382    language: *const c_char,
2383) -> SzConfigTool_result {
2384    let config = unsafe {
2385        if config_json.is_null() {
2386            set_error("config_json is null".to_string(), -1);
2387            return SzConfigTool_result {
2388                response: std::ptr::null_mut(),
2389                returnCode: -1,
2390            };
2391        }
2392        match CStr::from_ptr(config_json).to_str() {
2393            Ok(s) => s,
2394            Err(e) => {
2395                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2396                return SzConfigTool_result {
2397                    response: std::ptr::null_mut(),
2398                    returnCode: -2,
2399                };
2400            }
2401        }
2402    };
2403
2404    let code = unsafe {
2405        if sfunc_code.is_null() {
2406            set_error("sfunc_code is null".to_string(), -1);
2407            return SzConfigTool_result {
2408                response: std::ptr::null_mut(),
2409                returnCode: -1,
2410            };
2411        }
2412        match CStr::from_ptr(sfunc_code).to_str() {
2413            Ok(s) => s,
2414            Err(e) => {
2415                set_error(format!("Invalid UTF-8 in sfunc_code: {e}"), -2);
2416                return SzConfigTool_result {
2417                    response: std::ptr::null_mut(),
2418                    returnCode: -2,
2419                };
2420            }
2421        }
2422    };
2423
2424    let conn = unsafe {
2425        if connect_str.is_null() {
2426            set_error("connect_str is null".to_string(), -1);
2427            return SzConfigTool_result {
2428                response: std::ptr::null_mut(),
2429                returnCode: -1,
2430            };
2431        }
2432        match CStr::from_ptr(connect_str).to_str() {
2433            Ok(s) => s,
2434            Err(e) => {
2435                set_error(format!("Invalid UTF-8 in connect_str: {e}"), -2);
2436                return SzConfigTool_result {
2437                    response: std::ptr::null_mut(),
2438                    returnCode: -2,
2439                };
2440            }
2441        }
2442    };
2443
2444    let desc_opt = if sfunc_desc.is_null() {
2445        None
2446    } else {
2447        unsafe {
2448            match CStr::from_ptr(sfunc_desc).to_str() {
2449                Ok(s) if !s.is_empty() => Some(s),
2450                Ok(_) => None,
2451                Err(e) => {
2452                    set_error(format!("Invalid UTF-8 in sfunc_desc: {e}"), -2);
2453                    return SzConfigTool_result {
2454                        response: std::ptr::null_mut(),
2455                        returnCode: -2,
2456                    };
2457                }
2458            }
2459        }
2460    };
2461
2462    let lang_opt = if language.is_null() {
2463        None
2464    } else {
2465        unsafe {
2466            match CStr::from_ptr(language).to_str() {
2467                Ok(s) if !s.is_empty() => Some(s),
2468                Ok(_) => None,
2469                Err(e) => {
2470                    set_error(format!("Invalid UTF-8 in language: {e}"), -2);
2471                    return SzConfigTool_result {
2472                        response: std::ptr::null_mut(),
2473                        returnCode: -2,
2474                    };
2475                }
2476            }
2477        }
2478    };
2479
2480    match crate::functions::standardize::add_standardize_function(
2481        config,
2482        code,
2483        crate::functions::standardize::AddStandardizeFunctionParams {
2484            connect_str: conn,
2485            description: desc_opt,
2486            language: lang_opt,
2487        },
2488    ) {
2489        Ok((modified_config, _record)) => match CString::new(modified_config) {
2490            Ok(c_str) => {
2491                clear_error();
2492                SzConfigTool_result {
2493                    response: c_str.into_raw(),
2494                    returnCode: 0,
2495                }
2496            }
2497            Err(e) => {
2498                set_error(format!("Failed to convert result: {e}"), -4);
2499                SzConfigTool_result {
2500                    response: std::ptr::null_mut(),
2501                    returnCode: -4,
2502                }
2503            }
2504        },
2505        Err(e) => {
2506            set_error(e.to_string(), -5);
2507            SzConfigTool_result {
2508                response: std::ptr::null_mut(),
2509                returnCode: -5,
2510            }
2511        }
2512    }
2513}
2514
2515/// Delete a standardize function
2516#[unsafe(no_mangle)]
2517pub extern "C" fn SzConfigTool_deleteStandardizeFunction(
2518    config_json: *const c_char,
2519    sfunc_code: *const c_char,
2520) -> SzConfigTool_result {
2521    let config = unsafe {
2522        if config_json.is_null() {
2523            set_error("config_json is null".to_string(), -1);
2524            return SzConfigTool_result {
2525                response: std::ptr::null_mut(),
2526                returnCode: -1,
2527            };
2528        }
2529        match CStr::from_ptr(config_json).to_str() {
2530            Ok(s) => s,
2531            Err(e) => {
2532                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2533                return SzConfigTool_result {
2534                    response: std::ptr::null_mut(),
2535                    returnCode: -2,
2536                };
2537            }
2538        }
2539    };
2540
2541    let code = unsafe {
2542        if sfunc_code.is_null() {
2543            set_error("sfunc_code is null".to_string(), -1);
2544            return SzConfigTool_result {
2545                response: std::ptr::null_mut(),
2546                returnCode: -1,
2547            };
2548        }
2549        match CStr::from_ptr(sfunc_code).to_str() {
2550            Ok(s) => s,
2551            Err(e) => {
2552                set_error(format!("Invalid UTF-8 in sfunc_code: {e}"), -2);
2553                return SzConfigTool_result {
2554                    response: std::ptr::null_mut(),
2555                    returnCode: -2,
2556                };
2557            }
2558        }
2559    };
2560
2561    match crate::functions::standardize::delete_standardize_function(config, code) {
2562        Ok((modified_config, _record)) => match CString::new(modified_config) {
2563            Ok(c_str) => {
2564                clear_error();
2565                SzConfigTool_result {
2566                    response: c_str.into_raw(),
2567                    returnCode: 0,
2568                }
2569            }
2570            Err(e) => {
2571                set_error(format!("Failed to convert result: {e}"), -4);
2572                SzConfigTool_result {
2573                    response: std::ptr::null_mut(),
2574                    returnCode: -4,
2575                }
2576            }
2577        },
2578        Err(e) => {
2579            set_error(e.to_string(), -5);
2580            SzConfigTool_result {
2581                response: std::ptr::null_mut(),
2582                returnCode: -5,
2583            }
2584        }
2585    }
2586}
2587
2588/// Get a standardize function
2589#[unsafe(no_mangle)]
2590pub extern "C" fn SzConfigTool_getStandardizeFunction(
2591    config_json: *const c_char,
2592    sfunc_code: *const c_char,
2593) -> SzConfigTool_result {
2594    let config = unsafe {
2595        if config_json.is_null() {
2596            set_error("config_json is null".to_string(), -1);
2597            return SzConfigTool_result {
2598                response: std::ptr::null_mut(),
2599                returnCode: -1,
2600            };
2601        }
2602        match CStr::from_ptr(config_json).to_str() {
2603            Ok(s) => s,
2604            Err(e) => {
2605                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2606                return SzConfigTool_result {
2607                    response: std::ptr::null_mut(),
2608                    returnCode: -2,
2609                };
2610            }
2611        }
2612    };
2613
2614    let code = unsafe {
2615        if sfunc_code.is_null() {
2616            set_error("sfunc_code is null".to_string(), -1);
2617            return SzConfigTool_result {
2618                response: std::ptr::null_mut(),
2619                returnCode: -1,
2620            };
2621        }
2622        match CStr::from_ptr(sfunc_code).to_str() {
2623            Ok(s) => s,
2624            Err(e) => {
2625                set_error(format!("Invalid UTF-8 in sfunc_code: {e}"), -2);
2626                return SzConfigTool_result {
2627                    response: std::ptr::null_mut(),
2628                    returnCode: -2,
2629                };
2630            }
2631        }
2632    };
2633
2634    match crate::functions::standardize::get_standardize_function(config, code) {
2635        Ok(value) => {
2636            let json_str = serde_json::to_string(&value)
2637                .unwrap_or_else(|e| format!("{{\"error\": \"Failed to serialize: {e}\"}}"));
2638            match CString::new(json_str) {
2639                Ok(c_str) => {
2640                    clear_error();
2641                    SzConfigTool_result {
2642                        response: c_str.into_raw(),
2643                        returnCode: 0,
2644                    }
2645                }
2646                Err(e) => {
2647                    set_error(format!("Failed to convert result: {e}"), -4);
2648                    SzConfigTool_result {
2649                        response: std::ptr::null_mut(),
2650                        returnCode: -4,
2651                    }
2652                }
2653            }
2654        }
2655        Err(e) => {
2656            set_error(e.to_string(), -5);
2657            SzConfigTool_result {
2658                response: std::ptr::null_mut(),
2659                returnCode: -5,
2660            }
2661        }
2662    }
2663}
2664
2665/// List all standardize functions
2666#[unsafe(no_mangle)]
2667pub extern "C" fn SzConfigTool_listStandardizeFunctions(
2668    config_json: *const c_char,
2669) -> SzConfigTool_result {
2670    let config = unsafe {
2671        if config_json.is_null() {
2672            set_error("config_json is null".to_string(), -1);
2673            return SzConfigTool_result {
2674                response: std::ptr::null_mut(),
2675                returnCode: -1,
2676            };
2677        }
2678        match CStr::from_ptr(config_json).to_str() {
2679            Ok(s) => s,
2680            Err(e) => {
2681                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2682                return SzConfigTool_result {
2683                    response: std::ptr::null_mut(),
2684                    returnCode: -2,
2685                };
2686            }
2687        }
2688    };
2689
2690    match crate::functions::standardize::list_standardize_functions(config) {
2691        Ok(vec) => {
2692            let json_str = serde_json::to_string(&vec)
2693                .unwrap_or_else(|e| format!("{{\"error\": \"Failed to serialize: {e}\"}}"));
2694            match CString::new(json_str) {
2695                Ok(c_str) => {
2696                    clear_error();
2697                    SzConfigTool_result {
2698                        response: c_str.into_raw(),
2699                        returnCode: 0,
2700                    }
2701                }
2702                Err(e) => {
2703                    set_error(format!("Failed to convert result: {e}"), -4);
2704                    SzConfigTool_result {
2705                        response: std::ptr::null_mut(),
2706                        returnCode: -4,
2707                    }
2708                }
2709            }
2710        }
2711        Err(e) => {
2712            set_error(e.to_string(), -5);
2713            SzConfigTool_result {
2714                response: std::ptr::null_mut(),
2715                returnCode: -5,
2716            }
2717        }
2718    }
2719}
2720
2721/// Set (update) a standardize function
2722#[unsafe(no_mangle)]
2723pub extern "C" fn SzConfigTool_setStandardizeFunction(
2724    config_json: *const c_char,
2725    sfunc_code: *const c_char,
2726    connect_str: *const c_char,
2727    sfunc_desc: *const c_char,
2728    language: *const c_char,
2729) -> SzConfigTool_result {
2730    let config = unsafe {
2731        if config_json.is_null() {
2732            set_error("config_json is null".to_string(), -1);
2733            return SzConfigTool_result {
2734                response: std::ptr::null_mut(),
2735                returnCode: -1,
2736            };
2737        }
2738        match CStr::from_ptr(config_json).to_str() {
2739            Ok(s) => s,
2740            Err(e) => {
2741                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2742                return SzConfigTool_result {
2743                    response: std::ptr::null_mut(),
2744                    returnCode: -2,
2745                };
2746            }
2747        }
2748    };
2749
2750    let code = unsafe {
2751        if sfunc_code.is_null() {
2752            set_error("sfunc_code is null".to_string(), -1);
2753            return SzConfigTool_result {
2754                response: std::ptr::null_mut(),
2755                returnCode: -1,
2756            };
2757        }
2758        match CStr::from_ptr(sfunc_code).to_str() {
2759            Ok(s) => s,
2760            Err(e) => {
2761                set_error(format!("Invalid UTF-8 in sfunc_code: {e}"), -2);
2762                return SzConfigTool_result {
2763                    response: std::ptr::null_mut(),
2764                    returnCode: -2,
2765                };
2766            }
2767        }
2768    };
2769
2770    let conn_opt = if connect_str.is_null() {
2771        None
2772    } else {
2773        unsafe {
2774            match CStr::from_ptr(connect_str).to_str() {
2775                Ok(s) if !s.is_empty() => Some(s),
2776                Ok(_) => None,
2777                Err(e) => {
2778                    set_error(format!("Invalid UTF-8 in connect_str: {e}"), -2);
2779                    return SzConfigTool_result {
2780                        response: std::ptr::null_mut(),
2781                        returnCode: -2,
2782                    };
2783                }
2784            }
2785        }
2786    };
2787
2788    let desc_opt = if sfunc_desc.is_null() {
2789        None
2790    } else {
2791        unsafe {
2792            match CStr::from_ptr(sfunc_desc).to_str() {
2793                Ok(s) if !s.is_empty() => Some(s),
2794                Ok(_) => None,
2795                Err(e) => {
2796                    set_error(format!("Invalid UTF-8 in sfunc_desc: {e}"), -2);
2797                    return SzConfigTool_result {
2798                        response: std::ptr::null_mut(),
2799                        returnCode: -2,
2800                    };
2801                }
2802            }
2803        }
2804    };
2805
2806    let lang_opt = if language.is_null() {
2807        None
2808    } else {
2809        unsafe {
2810            match CStr::from_ptr(language).to_str() {
2811                Ok(s) if !s.is_empty() => Some(s),
2812                Ok(_) => None,
2813                Err(e) => {
2814                    set_error(format!("Invalid UTF-8 in language: {e}"), -2);
2815                    return SzConfigTool_result {
2816                        response: std::ptr::null_mut(),
2817                        returnCode: -2,
2818                    };
2819                }
2820            }
2821        }
2822    };
2823
2824    match crate::functions::standardize::set_standardize_function(
2825        config,
2826        code,
2827        crate::functions::standardize::SetStandardizeFunctionParams {
2828            connect_str: conn_opt,
2829            description: desc_opt,
2830            language: lang_opt,
2831        },
2832    ) {
2833        Ok((modified_config, _record)) => match CString::new(modified_config) {
2834            Ok(c_str) => {
2835                clear_error();
2836                SzConfigTool_result {
2837                    response: c_str.into_raw(),
2838                    returnCode: 0,
2839                }
2840            }
2841            Err(e) => {
2842                set_error(format!("Failed to convert result: {e}"), -4);
2843                SzConfigTool_result {
2844                    response: std::ptr::null_mut(),
2845                    returnCode: -4,
2846                }
2847            }
2848        },
2849        Err(e) => {
2850            set_error(e.to_string(), -5);
2851            SzConfigTool_result {
2852                response: std::ptr::null_mut(),
2853                returnCode: -5,
2854            }
2855        }
2856    }
2857}
2858
2859/* ============================================================================
2860 * Expression Function Operations (Batch 5b)
2861 * ============================================================================ */
2862
2863/// Add an expression function
2864#[unsafe(no_mangle)]
2865pub extern "C" fn SzConfigTool_addExpressionFunction(
2866    config_json: *const c_char,
2867    efunc_code: *const c_char,
2868    connect_str: *const c_char,
2869    efunc_desc: *const c_char,
2870    language: *const c_char,
2871) -> SzConfigTool_result {
2872    let config = unsafe {
2873        if config_json.is_null() {
2874            set_error("config_json is null".to_string(), -1);
2875            return SzConfigTool_result {
2876                response: std::ptr::null_mut(),
2877                returnCode: -1,
2878            };
2879        }
2880        match CStr::from_ptr(config_json).to_str() {
2881            Ok(s) => s,
2882            Err(e) => {
2883                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
2884                return SzConfigTool_result {
2885                    response: std::ptr::null_mut(),
2886                    returnCode: -2,
2887                };
2888            }
2889        }
2890    };
2891
2892    let code = unsafe {
2893        if efunc_code.is_null() {
2894            set_error("efunc_code is null".to_string(), -1);
2895            return SzConfigTool_result {
2896                response: std::ptr::null_mut(),
2897                returnCode: -1,
2898            };
2899        }
2900        match CStr::from_ptr(efunc_code).to_str() {
2901            Ok(s) => s,
2902            Err(e) => {
2903                set_error(format!("Invalid UTF-8 in efunc_code: {e}"), -2);
2904                return SzConfigTool_result {
2905                    response: std::ptr::null_mut(),
2906                    returnCode: -2,
2907                };
2908            }
2909        }
2910    };
2911
2912    let conn = unsafe {
2913        if connect_str.is_null() {
2914            set_error("connect_str is null".to_string(), -1);
2915            return SzConfigTool_result {
2916                response: std::ptr::null_mut(),
2917                returnCode: -1,
2918            };
2919        }
2920        match CStr::from_ptr(connect_str).to_str() {
2921            Ok(s) => s,
2922            Err(e) => {
2923                set_error(format!("Invalid UTF-8 in connect_str: {e}"), -2);
2924                return SzConfigTool_result {
2925                    response: std::ptr::null_mut(),
2926                    returnCode: -2,
2927                };
2928            }
2929        }
2930    };
2931
2932    let desc_opt = if efunc_desc.is_null() {
2933        None
2934    } else {
2935        unsafe {
2936            match CStr::from_ptr(efunc_desc).to_str() {
2937                Ok(s) if !s.is_empty() => Some(s),
2938                Ok(_) => None,
2939                Err(e) => {
2940                    set_error(format!("Invalid UTF-8 in efunc_desc: {e}"), -2);
2941                    return SzConfigTool_result {
2942                        response: std::ptr::null_mut(),
2943                        returnCode: -2,
2944                    };
2945                }
2946            }
2947        }
2948    };
2949
2950    let lang_opt = if language.is_null() {
2951        None
2952    } else {
2953        unsafe {
2954            match CStr::from_ptr(language).to_str() {
2955                Ok(s) if !s.is_empty() => Some(s),
2956                Ok(_) => None,
2957                Err(e) => {
2958                    set_error(format!("Invalid UTF-8 in language: {e}"), -2);
2959                    return SzConfigTool_result {
2960                        response: std::ptr::null_mut(),
2961                        returnCode: -2,
2962                    };
2963                }
2964            }
2965        }
2966    };
2967
2968    match crate::functions::expression::add_expression_function(
2969        config,
2970        code,
2971        crate::functions::expression::AddExpressionFunctionParams {
2972            connect_str: conn,
2973            description: desc_opt,
2974            language: lang_opt,
2975        },
2976    ) {
2977        Ok((modified_config, _)) => match CString::new(modified_config) {
2978            Ok(c_str) => {
2979                clear_error();
2980                SzConfigTool_result {
2981                    response: c_str.into_raw(),
2982                    returnCode: 0,
2983                }
2984            }
2985            Err(e) => {
2986                set_error(format!("Failed to convert result: {e}"), -4);
2987                SzConfigTool_result {
2988                    response: std::ptr::null_mut(),
2989                    returnCode: -4,
2990                }
2991            }
2992        },
2993        Err(e) => {
2994            set_error(e.to_string(), -5);
2995            SzConfigTool_result {
2996                response: std::ptr::null_mut(),
2997                returnCode: -5,
2998            }
2999        }
3000    }
3001}
3002
3003/// Delete an expression function
3004#[unsafe(no_mangle)]
3005pub extern "C" fn SzConfigTool_deleteExpressionFunction(
3006    config_json: *const c_char,
3007    efunc_code: *const c_char,
3008) -> SzConfigTool_result {
3009    let config = unsafe {
3010        if config_json.is_null() {
3011            set_error("config_json is null".to_string(), -1);
3012            return SzConfigTool_result {
3013                response: std::ptr::null_mut(),
3014                returnCode: -1,
3015            };
3016        }
3017        match CStr::from_ptr(config_json).to_str() {
3018            Ok(s) => s,
3019            Err(e) => {
3020                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
3021                return SzConfigTool_result {
3022                    response: std::ptr::null_mut(),
3023                    returnCode: -2,
3024                };
3025            }
3026        }
3027    };
3028
3029    let code = unsafe {
3030        if efunc_code.is_null() {
3031            set_error("efunc_code is null".to_string(), -1);
3032            return SzConfigTool_result {
3033                response: std::ptr::null_mut(),
3034                returnCode: -1,
3035            };
3036        }
3037        match CStr::from_ptr(efunc_code).to_str() {
3038            Ok(s) => s,
3039            Err(e) => {
3040                set_error(format!("Invalid UTF-8 in efunc_code: {e}"), -2);
3041                return SzConfigTool_result {
3042                    response: std::ptr::null_mut(),
3043                    returnCode: -2,
3044                };
3045            }
3046        }
3047    };
3048
3049    match crate::functions::expression::delete_expression_function(config, code) {
3050        Ok((modified_config, _)) => match CString::new(modified_config) {
3051            Ok(c_str) => {
3052                clear_error();
3053                SzConfigTool_result {
3054                    response: c_str.into_raw(),
3055                    returnCode: 0,
3056                }
3057            }
3058            Err(e) => {
3059                set_error(format!("Failed to convert result: {e}"), -4);
3060                SzConfigTool_result {
3061                    response: std::ptr::null_mut(),
3062                    returnCode: -4,
3063                }
3064            }
3065        },
3066        Err(e) => {
3067            set_error(e.to_string(), -5);
3068            SzConfigTool_result {
3069                response: std::ptr::null_mut(),
3070                returnCode: -5,
3071            }
3072        }
3073    }
3074}
3075
3076/// Get an expression function
3077#[unsafe(no_mangle)]
3078pub extern "C" fn SzConfigTool_getExpressionFunction(
3079    config_json: *const c_char,
3080    efunc_code: *const c_char,
3081) -> SzConfigTool_result {
3082    let config = unsafe {
3083        if config_json.is_null() {
3084            set_error("config_json is null".to_string(), -1);
3085            return SzConfigTool_result {
3086                response: std::ptr::null_mut(),
3087                returnCode: -1,
3088            };
3089        }
3090        match CStr::from_ptr(config_json).to_str() {
3091            Ok(s) => s,
3092            Err(e) => {
3093                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
3094                return SzConfigTool_result {
3095                    response: std::ptr::null_mut(),
3096                    returnCode: -2,
3097                };
3098            }
3099        }
3100    };
3101
3102    let code = unsafe {
3103        if efunc_code.is_null() {
3104            set_error("efunc_code is null".to_string(), -1);
3105            return SzConfigTool_result {
3106                response: std::ptr::null_mut(),
3107                returnCode: -1,
3108            };
3109        }
3110        match CStr::from_ptr(efunc_code).to_str() {
3111            Ok(s) => s,
3112            Err(e) => {
3113                set_error(format!("Invalid UTF-8 in efunc_code: {e}"), -2);
3114                return SzConfigTool_result {
3115                    response: std::ptr::null_mut(),
3116                    returnCode: -2,
3117                };
3118            }
3119        }
3120    };
3121
3122    match crate::functions::expression::get_expression_function(config, code) {
3123        Ok(value) => {
3124            let json_str = serde_json::to_string(&value)
3125                .unwrap_or_else(|e| format!("{{\"error\": \"Failed to serialize: {e}\"}}"));
3126            match CString::new(json_str) {
3127                Ok(c_str) => {
3128                    clear_error();
3129                    SzConfigTool_result {
3130                        response: c_str.into_raw(),
3131                        returnCode: 0,
3132                    }
3133                }
3134                Err(e) => {
3135                    set_error(format!("Failed to convert result: {e}"), -4);
3136                    SzConfigTool_result {
3137                        response: std::ptr::null_mut(),
3138                        returnCode: -4,
3139                    }
3140                }
3141            }
3142        }
3143        Err(e) => {
3144            set_error(e.to_string(), -5);
3145            SzConfigTool_result {
3146                response: std::ptr::null_mut(),
3147                returnCode: -5,
3148            }
3149        }
3150    }
3151}
3152
3153/// List all expression functions
3154#[unsafe(no_mangle)]
3155pub extern "C" fn SzConfigTool_listExpressionFunctions(
3156    config_json: *const c_char,
3157) -> SzConfigTool_result {
3158    let config = unsafe {
3159        if config_json.is_null() {
3160            set_error("config_json is null".to_string(), -1);
3161            return SzConfigTool_result {
3162                response: std::ptr::null_mut(),
3163                returnCode: -1,
3164            };
3165        }
3166        match CStr::from_ptr(config_json).to_str() {
3167            Ok(s) => s,
3168            Err(e) => {
3169                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
3170                return SzConfigTool_result {
3171                    response: std::ptr::null_mut(),
3172                    returnCode: -2,
3173                };
3174            }
3175        }
3176    };
3177
3178    match crate::functions::expression::list_expression_functions(config) {
3179        Ok(vec) => {
3180            let json_str = serde_json::to_string(&vec)
3181                .unwrap_or_else(|e| format!("{{\"error\": \"Failed to serialize: {e}\"}}"));
3182            match CString::new(json_str) {
3183                Ok(c_str) => {
3184                    clear_error();
3185                    SzConfigTool_result {
3186                        response: c_str.into_raw(),
3187                        returnCode: 0,
3188                    }
3189                }
3190                Err(e) => {
3191                    set_error(format!("Failed to convert result: {e}"), -4);
3192                    SzConfigTool_result {
3193                        response: std::ptr::null_mut(),
3194                        returnCode: -4,
3195                    }
3196                }
3197            }
3198        }
3199        Err(e) => {
3200            set_error(e.to_string(), -5);
3201            SzConfigTool_result {
3202                response: std::ptr::null_mut(),
3203                returnCode: -5,
3204            }
3205        }
3206    }
3207}
3208
3209/// Set (update) an expression function
3210#[unsafe(no_mangle)]
3211pub extern "C" fn SzConfigTool_setExpressionFunction(
3212    config_json: *const c_char,
3213    efunc_code: *const c_char,
3214    connect_str: *const c_char,
3215    efunc_desc: *const c_char,
3216    language: *const c_char,
3217) -> SzConfigTool_result {
3218    let config = unsafe {
3219        if config_json.is_null() {
3220            set_error("config_json is null".to_string(), -1);
3221            return SzConfigTool_result {
3222                response: std::ptr::null_mut(),
3223                returnCode: -1,
3224            };
3225        }
3226        match CStr::from_ptr(config_json).to_str() {
3227            Ok(s) => s,
3228            Err(e) => {
3229                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
3230                return SzConfigTool_result {
3231                    response: std::ptr::null_mut(),
3232                    returnCode: -2,
3233                };
3234            }
3235        }
3236    };
3237
3238    let code = unsafe {
3239        if efunc_code.is_null() {
3240            set_error("efunc_code is null".to_string(), -1);
3241            return SzConfigTool_result {
3242                response: std::ptr::null_mut(),
3243                returnCode: -1,
3244            };
3245        }
3246        match CStr::from_ptr(efunc_code).to_str() {
3247            Ok(s) => s,
3248            Err(e) => {
3249                set_error(format!("Invalid UTF-8 in efunc_code: {e}"), -2);
3250                return SzConfigTool_result {
3251                    response: std::ptr::null_mut(),
3252                    returnCode: -2,
3253                };
3254            }
3255        }
3256    };
3257
3258    let conn_opt = if connect_str.is_null() {
3259        None
3260    } else {
3261        unsafe {
3262            match CStr::from_ptr(connect_str).to_str() {
3263                Ok(s) if !s.is_empty() => Some(s),
3264                Ok(_) => None,
3265                Err(e) => {
3266                    set_error(format!("Invalid UTF-8 in connect_str: {e}"), -2);
3267                    return SzConfigTool_result {
3268                        response: std::ptr::null_mut(),
3269                        returnCode: -2,
3270                    };
3271                }
3272            }
3273        }
3274    };
3275
3276    let desc_opt = if efunc_desc.is_null() {
3277        None
3278    } else {
3279        unsafe {
3280            match CStr::from_ptr(efunc_desc).to_str() {
3281                Ok(s) if !s.is_empty() => Some(s),
3282                Ok(_) => None,
3283                Err(e) => {
3284                    set_error(format!("Invalid UTF-8 in efunc_desc: {e}"), -2);
3285                    return SzConfigTool_result {
3286                        response: std::ptr::null_mut(),
3287                        returnCode: -2,
3288                    };
3289                }
3290            }
3291        }
3292    };
3293
3294    let lang_opt = if language.is_null() {
3295        None
3296    } else {
3297        unsafe {
3298            match CStr::from_ptr(language).to_str() {
3299                Ok(s) if !s.is_empty() => Some(s),
3300                Ok(_) => None,
3301                Err(e) => {
3302                    set_error(format!("Invalid UTF-8 in language: {e}"), -2);
3303                    return SzConfigTool_result {
3304                        response: std::ptr::null_mut(),
3305                        returnCode: -2,
3306                    };
3307                }
3308            }
3309        }
3310    };
3311
3312    match crate::functions::expression::set_expression_function(
3313        config,
3314        code,
3315        crate::functions::expression::SetExpressionFunctionParams {
3316            connect_str: conn_opt,
3317            description: desc_opt,
3318            language: lang_opt,
3319        },
3320    ) {
3321        Ok((modified_config, _)) => match CString::new(modified_config) {
3322            Ok(c_str) => {
3323                clear_error();
3324                SzConfigTool_result {
3325                    response: c_str.into_raw(),
3326                    returnCode: 0,
3327                }
3328            }
3329            Err(e) => {
3330                set_error(format!("Failed to convert result: {e}"), -4);
3331                SzConfigTool_result {
3332                    response: std::ptr::null_mut(),
3333                    returnCode: -4,
3334                }
3335            }
3336        },
3337        Err(e) => {
3338            set_error(e.to_string(), -5);
3339            SzConfigTool_result {
3340                response: std::ptr::null_mut(),
3341                returnCode: -5,
3342            }
3343        }
3344    }
3345}
3346
3347/* ============================================================================
3348 * Comparison Function Operations (Batch 5c)
3349 * ============================================================================ */
3350
3351/// Add a comparison function
3352#[unsafe(no_mangle)]
3353pub extern "C" fn SzConfigTool_addComparisonFunction(
3354    config_json: *const c_char,
3355    cfunc_code: *const c_char,
3356    connect_str: *const c_char,
3357    cfunc_desc: *const c_char,
3358    language: *const c_char,
3359    anon_support: *const c_char,
3360) -> SzConfigTool_result {
3361    let config = unsafe {
3362        if config_json.is_null() {
3363            set_error("config_json is null".to_string(), -1);
3364            return SzConfigTool_result {
3365                response: std::ptr::null_mut(),
3366                returnCode: -1,
3367            };
3368        }
3369        match CStr::from_ptr(config_json).to_str() {
3370            Ok(s) => s,
3371            Err(e) => {
3372                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
3373                return SzConfigTool_result {
3374                    response: std::ptr::null_mut(),
3375                    returnCode: -2,
3376                };
3377            }
3378        }
3379    };
3380
3381    let code = unsafe {
3382        if cfunc_code.is_null() {
3383            set_error("cfunc_code is null".to_string(), -1);
3384            return SzConfigTool_result {
3385                response: std::ptr::null_mut(),
3386                returnCode: -1,
3387            };
3388        }
3389        match CStr::from_ptr(cfunc_code).to_str() {
3390            Ok(s) => s,
3391            Err(e) => {
3392                set_error(format!("Invalid UTF-8 in cfunc_code: {e}"), -2);
3393                return SzConfigTool_result {
3394                    response: std::ptr::null_mut(),
3395                    returnCode: -2,
3396                };
3397            }
3398        }
3399    };
3400
3401    let conn = unsafe {
3402        if connect_str.is_null() {
3403            set_error("connect_str is null".to_string(), -1);
3404            return SzConfigTool_result {
3405                response: std::ptr::null_mut(),
3406                returnCode: -1,
3407            };
3408        }
3409        match CStr::from_ptr(connect_str).to_str() {
3410            Ok(s) => s,
3411            Err(e) => {
3412                set_error(format!("Invalid UTF-8 in connect_str: {e}"), -2);
3413                return SzConfigTool_result {
3414                    response: std::ptr::null_mut(),
3415                    returnCode: -2,
3416                };
3417            }
3418        }
3419    };
3420
3421    let desc_opt = if cfunc_desc.is_null() {
3422        None
3423    } else {
3424        unsafe {
3425            match CStr::from_ptr(cfunc_desc).to_str() {
3426                Ok(s) if !s.is_empty() => Some(s),
3427                Ok(_) => None,
3428                Err(e) => {
3429                    set_error(format!("Invalid UTF-8 in cfunc_desc: {e}"), -2);
3430                    return SzConfigTool_result {
3431                        response: std::ptr::null_mut(),
3432                        returnCode: -2,
3433                    };
3434                }
3435            }
3436        }
3437    };
3438
3439    let lang_opt = if language.is_null() {
3440        None
3441    } else {
3442        unsafe {
3443            match CStr::from_ptr(language).to_str() {
3444                Ok(s) if !s.is_empty() => Some(s),
3445                Ok(_) => None,
3446                Err(e) => {
3447                    set_error(format!("Invalid UTF-8 in language: {e}"), -2);
3448                    return SzConfigTool_result {
3449                        response: std::ptr::null_mut(),
3450                        returnCode: -2,
3451                    };
3452                }
3453            }
3454        }
3455    };
3456
3457    let anon_opt = if anon_support.is_null() {
3458        None
3459    } else {
3460        unsafe {
3461            match CStr::from_ptr(anon_support).to_str() {
3462                Ok(s) if !s.is_empty() => Some(s),
3463                Ok(_) => None,
3464                Err(e) => {
3465                    set_error(format!("Invalid UTF-8 in anon_support: {e}"), -2);
3466                    return SzConfigTool_result {
3467                        response: std::ptr::null_mut(),
3468                        returnCode: -2,
3469                    };
3470                }
3471            }
3472        }
3473    };
3474
3475    match crate::functions::comparison::add_comparison_function(
3476        config,
3477        code,
3478        crate::functions::comparison::AddComparisonFunctionParams {
3479            connect_str: conn,
3480            description: desc_opt,
3481            language: lang_opt,
3482            anon_support: anon_opt,
3483        },
3484    ) {
3485        Ok((modified_config, _)) => match CString::new(modified_config) {
3486            Ok(c_str) => {
3487                clear_error();
3488                SzConfigTool_result {
3489                    response: c_str.into_raw(),
3490                    returnCode: 0,
3491                }
3492            }
3493            Err(e) => {
3494                set_error(format!("Failed to convert result: {e}"), -4);
3495                SzConfigTool_result {
3496                    response: std::ptr::null_mut(),
3497                    returnCode: -4,
3498                }
3499            }
3500        },
3501        Err(e) => {
3502            set_error(e.to_string(), -5);
3503            SzConfigTool_result {
3504                response: std::ptr::null_mut(),
3505                returnCode: -5,
3506            }
3507        }
3508    }
3509}
3510
3511/// Delete a comparison function
3512#[unsafe(no_mangle)]
3513pub extern "C" fn SzConfigTool_deleteComparisonFunction(
3514    config_json: *const c_char,
3515    cfunc_code: *const c_char,
3516) -> SzConfigTool_result {
3517    let config = unsafe {
3518        if config_json.is_null() {
3519            set_error("config_json is null".to_string(), -1);
3520            return SzConfigTool_result {
3521                response: std::ptr::null_mut(),
3522                returnCode: -1,
3523            };
3524        }
3525        match CStr::from_ptr(config_json).to_str() {
3526            Ok(s) => s,
3527            Err(e) => {
3528                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
3529                return SzConfigTool_result {
3530                    response: std::ptr::null_mut(),
3531                    returnCode: -2,
3532                };
3533            }
3534        }
3535    };
3536
3537    let code = unsafe {
3538        if cfunc_code.is_null() {
3539            set_error("cfunc_code is null".to_string(), -1);
3540            return SzConfigTool_result {
3541                response: std::ptr::null_mut(),
3542                returnCode: -1,
3543            };
3544        }
3545        match CStr::from_ptr(cfunc_code).to_str() {
3546            Ok(s) => s,
3547            Err(e) => {
3548                set_error(format!("Invalid UTF-8 in cfunc_code: {e}"), -2);
3549                return SzConfigTool_result {
3550                    response: std::ptr::null_mut(),
3551                    returnCode: -2,
3552                };
3553            }
3554        }
3555    };
3556
3557    match crate::functions::comparison::delete_comparison_function(config, code) {
3558        Ok((modified_config, _)) => match CString::new(modified_config) {
3559            Ok(c_str) => {
3560                clear_error();
3561                SzConfigTool_result {
3562                    response: c_str.into_raw(),
3563                    returnCode: 0,
3564                }
3565            }
3566            Err(e) => {
3567                set_error(format!("Failed to convert result: {e}"), -4);
3568                SzConfigTool_result {
3569                    response: std::ptr::null_mut(),
3570                    returnCode: -4,
3571                }
3572            }
3573        },
3574        Err(e) => {
3575            set_error(e.to_string(), -5);
3576            SzConfigTool_result {
3577                response: std::ptr::null_mut(),
3578                returnCode: -5,
3579            }
3580        }
3581    }
3582}
3583
3584/// Get a comparison function
3585#[unsafe(no_mangle)]
3586pub extern "C" fn SzConfigTool_getComparisonFunction(
3587    config_json: *const c_char,
3588    cfunc_code: *const c_char,
3589) -> SzConfigTool_result {
3590    let config = unsafe {
3591        if config_json.is_null() {
3592            set_error("config_json is null".to_string(), -1);
3593            return SzConfigTool_result {
3594                response: std::ptr::null_mut(),
3595                returnCode: -1,
3596            };
3597        }
3598        match CStr::from_ptr(config_json).to_str() {
3599            Ok(s) => s,
3600            Err(e) => {
3601                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
3602                return SzConfigTool_result {
3603                    response: std::ptr::null_mut(),
3604                    returnCode: -2,
3605                };
3606            }
3607        }
3608    };
3609
3610    let code = unsafe {
3611        if cfunc_code.is_null() {
3612            set_error("cfunc_code is null".to_string(), -1);
3613            return SzConfigTool_result {
3614                response: std::ptr::null_mut(),
3615                returnCode: -1,
3616            };
3617        }
3618        match CStr::from_ptr(cfunc_code).to_str() {
3619            Ok(s) => s,
3620            Err(e) => {
3621                set_error(format!("Invalid UTF-8 in cfunc_code: {e}"), -2);
3622                return SzConfigTool_result {
3623                    response: std::ptr::null_mut(),
3624                    returnCode: -2,
3625                };
3626            }
3627        }
3628    };
3629
3630    match crate::functions::comparison::get_comparison_function(config, code) {
3631        Ok(value) => {
3632            let json_str = serde_json::to_string(&value)
3633                .unwrap_or_else(|e| format!("{{\"error\": \"Failed to serialize: {e}\"}}"));
3634            match CString::new(json_str) {
3635                Ok(c_str) => {
3636                    clear_error();
3637                    SzConfigTool_result {
3638                        response: c_str.into_raw(),
3639                        returnCode: 0,
3640                    }
3641                }
3642                Err(e) => {
3643                    set_error(format!("Failed to convert result: {e}"), -4);
3644                    SzConfigTool_result {
3645                        response: std::ptr::null_mut(),
3646                        returnCode: -4,
3647                    }
3648                }
3649            }
3650        }
3651        Err(e) => {
3652            set_error(e.to_string(), -5);
3653            SzConfigTool_result {
3654                response: std::ptr::null_mut(),
3655                returnCode: -5,
3656            }
3657        }
3658    }
3659}
3660
3661/// List all comparison functions
3662#[unsafe(no_mangle)]
3663pub extern "C" fn SzConfigTool_listComparisonFunctions(
3664    config_json: *const c_char,
3665) -> SzConfigTool_result {
3666    let config = unsafe {
3667        if config_json.is_null() {
3668            set_error("config_json is null".to_string(), -1);
3669            return SzConfigTool_result {
3670                response: std::ptr::null_mut(),
3671                returnCode: -1,
3672            };
3673        }
3674        match CStr::from_ptr(config_json).to_str() {
3675            Ok(s) => s,
3676            Err(e) => {
3677                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
3678                return SzConfigTool_result {
3679                    response: std::ptr::null_mut(),
3680                    returnCode: -2,
3681                };
3682            }
3683        }
3684    };
3685
3686    match crate::functions::comparison::list_comparison_functions(config) {
3687        Ok(vec) => {
3688            let json_str = serde_json::to_string(&vec)
3689                .unwrap_or_else(|e| format!("{{\"error\": \"Failed to serialize: {e}\"}}"));
3690            match CString::new(json_str) {
3691                Ok(c_str) => {
3692                    clear_error();
3693                    SzConfigTool_result {
3694                        response: c_str.into_raw(),
3695                        returnCode: 0,
3696                    }
3697                }
3698                Err(e) => {
3699                    set_error(format!("Failed to convert result: {e}"), -4);
3700                    SzConfigTool_result {
3701                        response: std::ptr::null_mut(),
3702                        returnCode: -4,
3703                    }
3704                }
3705            }
3706        }
3707        Err(e) => {
3708            set_error(e.to_string(), -5);
3709            SzConfigTool_result {
3710                response: std::ptr::null_mut(),
3711                returnCode: -5,
3712            }
3713        }
3714    }
3715}
3716
3717/// Set (update) a comparison function
3718#[unsafe(no_mangle)]
3719pub extern "C" fn SzConfigTool_setComparisonFunction(
3720    config_json: *const c_char,
3721    cfunc_code: *const c_char,
3722    connect_str: *const c_char,
3723    cfunc_desc: *const c_char,
3724    language: *const c_char,
3725    anon_support: *const c_char,
3726) -> SzConfigTool_result {
3727    let config = unsafe {
3728        if config_json.is_null() {
3729            set_error("config_json is null".to_string(), -1);
3730            return SzConfigTool_result {
3731                response: std::ptr::null_mut(),
3732                returnCode: -1,
3733            };
3734        }
3735        match CStr::from_ptr(config_json).to_str() {
3736            Ok(s) => s,
3737            Err(e) => {
3738                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
3739                return SzConfigTool_result {
3740                    response: std::ptr::null_mut(),
3741                    returnCode: -2,
3742                };
3743            }
3744        }
3745    };
3746
3747    let code = unsafe {
3748        if cfunc_code.is_null() {
3749            set_error("cfunc_code is null".to_string(), -1);
3750            return SzConfigTool_result {
3751                response: std::ptr::null_mut(),
3752                returnCode: -1,
3753            };
3754        }
3755        match CStr::from_ptr(cfunc_code).to_str() {
3756            Ok(s) => s,
3757            Err(e) => {
3758                set_error(format!("Invalid UTF-8 in cfunc_code: {e}"), -2);
3759                return SzConfigTool_result {
3760                    response: std::ptr::null_mut(),
3761                    returnCode: -2,
3762                };
3763            }
3764        }
3765    };
3766
3767    let conn_opt = if connect_str.is_null() {
3768        None
3769    } else {
3770        unsafe {
3771            match CStr::from_ptr(connect_str).to_str() {
3772                Ok(s) if !s.is_empty() => Some(s),
3773                Ok(_) => None,
3774                Err(e) => {
3775                    set_error(format!("Invalid UTF-8 in connect_str: {e}"), -2);
3776                    return SzConfigTool_result {
3777                        response: std::ptr::null_mut(),
3778                        returnCode: -2,
3779                    };
3780                }
3781            }
3782        }
3783    };
3784
3785    let desc_opt = if cfunc_desc.is_null() {
3786        None
3787    } else {
3788        unsafe {
3789            match CStr::from_ptr(cfunc_desc).to_str() {
3790                Ok(s) if !s.is_empty() => Some(s),
3791                Ok(_) => None,
3792                Err(e) => {
3793                    set_error(format!("Invalid UTF-8 in cfunc_desc: {e}"), -2);
3794                    return SzConfigTool_result {
3795                        response: std::ptr::null_mut(),
3796                        returnCode: -2,
3797                    };
3798                }
3799            }
3800        }
3801    };
3802
3803    let lang_opt = if language.is_null() {
3804        None
3805    } else {
3806        unsafe {
3807            match CStr::from_ptr(language).to_str() {
3808                Ok(s) if !s.is_empty() => Some(s),
3809                Ok(_) => None,
3810                Err(e) => {
3811                    set_error(format!("Invalid UTF-8 in language: {e}"), -2);
3812                    return SzConfigTool_result {
3813                        response: std::ptr::null_mut(),
3814                        returnCode: -2,
3815                    };
3816                }
3817            }
3818        }
3819    };
3820
3821    let anon_opt = if anon_support.is_null() {
3822        None
3823    } else {
3824        unsafe {
3825            match CStr::from_ptr(anon_support).to_str() {
3826                Ok(s) if !s.is_empty() => Some(s),
3827                Ok(_) => None,
3828                Err(e) => {
3829                    set_error(format!("Invalid UTF-8 in anon_support: {e}"), -2);
3830                    return SzConfigTool_result {
3831                        response: std::ptr::null_mut(),
3832                        returnCode: -2,
3833                    };
3834                }
3835            }
3836        }
3837    };
3838
3839    match crate::functions::comparison::set_comparison_function(
3840        config,
3841        code,
3842        crate::functions::comparison::SetComparisonFunctionParams {
3843            connect_str: conn_opt,
3844            description: desc_opt,
3845            language: lang_opt,
3846            anon_support: anon_opt,
3847        },
3848    ) {
3849        Ok((modified_config, _)) => match CString::new(modified_config) {
3850            Ok(c_str) => {
3851                clear_error();
3852                SzConfigTool_result {
3853                    response: c_str.into_raw(),
3854                    returnCode: 0,
3855                }
3856            }
3857            Err(e) => {
3858                set_error(format!("Failed to convert result: {e}"), -4);
3859                SzConfigTool_result {
3860                    response: std::ptr::null_mut(),
3861                    returnCode: -4,
3862                }
3863            }
3864        },
3865        Err(e) => {
3866            set_error(e.to_string(), -5);
3867            SzConfigTool_result {
3868                response: std::ptr::null_mut(),
3869                returnCode: -5,
3870            }
3871        }
3872    }
3873}
3874
3875/* ============================================================================
3876 * Standardize Call Operations (Batch 6a)
3877 * ============================================================================ */
3878
3879/// Add a standardize call
3880#[unsafe(no_mangle)]
3881pub extern "C" fn SzConfigTool_addStandardizeCall(
3882    config_json: *const c_char,
3883    ftype_code: *const c_char,
3884    felem_code: *const c_char,
3885    exec_order: i64,
3886    sfunc_code: *const c_char,
3887) -> SzConfigTool_result {
3888    let config = unsafe {
3889        if config_json.is_null() {
3890            set_error("config_json is null".to_string(), -1);
3891            return SzConfigTool_result {
3892                response: std::ptr::null_mut(),
3893                returnCode: -1,
3894            };
3895        }
3896        match CStr::from_ptr(config_json).to_str() {
3897            Ok(s) => s,
3898            Err(e) => {
3899                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
3900                return SzConfigTool_result {
3901                    response: std::ptr::null_mut(),
3902                    returnCode: -2,
3903                };
3904            }
3905        }
3906    };
3907
3908    let ftype_opt = if ftype_code.is_null() {
3909        None
3910    } else {
3911        unsafe {
3912            match CStr::from_ptr(ftype_code).to_str() {
3913                Ok(s) if !s.is_empty() => Some(s),
3914                Ok(_) => None,
3915                Err(e) => {
3916                    set_error(format!("Invalid UTF-8 in ftype_code: {e}"), -2);
3917                    return SzConfigTool_result {
3918                        response: std::ptr::null_mut(),
3919                        returnCode: -2,
3920                    };
3921                }
3922            }
3923        }
3924    };
3925
3926    let felem_opt = if felem_code.is_null() {
3927        None
3928    } else {
3929        unsafe {
3930            match CStr::from_ptr(felem_code).to_str() {
3931                Ok(s) if !s.is_empty() => Some(s),
3932                Ok(_) => None,
3933                Err(e) => {
3934                    set_error(format!("Invalid UTF-8 in felem_code: {e}"), -2);
3935                    return SzConfigTool_result {
3936                        response: std::ptr::null_mut(),
3937                        returnCode: -2,
3938                    };
3939                }
3940            }
3941        }
3942    };
3943
3944    let exec_opt = if exec_order < 0 {
3945        None
3946    } else {
3947        Some(exec_order)
3948    };
3949
3950    let sfunc = unsafe {
3951        if sfunc_code.is_null() {
3952            set_error("sfunc_code is null".to_string(), -1);
3953            return SzConfigTool_result {
3954                response: std::ptr::null_mut(),
3955                returnCode: -1,
3956            };
3957        }
3958        match CStr::from_ptr(sfunc_code).to_str() {
3959            Ok(s) => s,
3960            Err(e) => {
3961                set_error(format!("Invalid UTF-8 in sfunc_code: {e}"), -2);
3962                return SzConfigTool_result {
3963                    response: std::ptr::null_mut(),
3964                    returnCode: -2,
3965                };
3966            }
3967        }
3968    };
3969
3970    let params = crate::calls::standardize::AddStandardizeCallParams {
3971        ftype_code: ftype_opt,
3972        felem_code: felem_opt,
3973        exec_order: exec_opt,
3974        sfunc_code: sfunc,
3975    };
3976
3977    match crate::calls::standardize::add_standardize_call(config, params) {
3978        Ok((modified_config, _)) => match CString::new(modified_config) {
3979            Ok(c_str) => {
3980                clear_error();
3981                SzConfigTool_result {
3982                    response: c_str.into_raw(),
3983                    returnCode: 0,
3984                }
3985            }
3986            Err(e) => {
3987                set_error(format!("Failed to convert result: {e}"), -4);
3988                SzConfigTool_result {
3989                    response: std::ptr::null_mut(),
3990                    returnCode: -4,
3991                }
3992            }
3993        },
3994        Err(e) => {
3995            set_error(e.to_string(), -5);
3996            SzConfigTool_result {
3997                response: std::ptr::null_mut(),
3998                returnCode: -5,
3999            }
4000        }
4001    }
4002}
4003
4004/// Delete a standardize call
4005#[unsafe(no_mangle)]
4006pub extern "C" fn SzConfigTool_deleteStandardizeCall(
4007    config_json: *const c_char,
4008    sfcall_id: i64,
4009) -> SzConfigTool_result {
4010    let config = unsafe {
4011        if config_json.is_null() {
4012            set_error("config_json is null".to_string(), -1);
4013            return SzConfigTool_result {
4014                response: std::ptr::null_mut(),
4015                returnCode: -1,
4016            };
4017        }
4018        match CStr::from_ptr(config_json).to_str() {
4019            Ok(s) => s,
4020            Err(e) => {
4021                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4022                return SzConfigTool_result {
4023                    response: std::ptr::null_mut(),
4024                    returnCode: -2,
4025                };
4026            }
4027        }
4028    };
4029
4030    handle_result!(crate::calls::standardize::delete_standardize_call(
4031        config, sfcall_id
4032    ))
4033}
4034
4035/// Get a standardize call
4036#[unsafe(no_mangle)]
4037pub extern "C" fn SzConfigTool_getStandardizeCall(
4038    config_json: *const c_char,
4039    sfcall_id: i64,
4040) -> SzConfigTool_result {
4041    let config = unsafe {
4042        if config_json.is_null() {
4043            set_error("config_json is null".to_string(), -1);
4044            return SzConfigTool_result {
4045                response: std::ptr::null_mut(),
4046                returnCode: -1,
4047            };
4048        }
4049        match CStr::from_ptr(config_json).to_str() {
4050            Ok(s) => s,
4051            Err(e) => {
4052                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4053                return SzConfigTool_result {
4054                    response: std::ptr::null_mut(),
4055                    returnCode: -2,
4056                };
4057            }
4058        }
4059    };
4060
4061    match crate::calls::standardize::get_standardize_call(config, sfcall_id) {
4062        Ok(value) => {
4063            let json_str = serde_json::to_string(&value)
4064                .unwrap_or_else(|e| format!("{{\"error\": \"Failed to serialize: {e}\"}}"));
4065            match CString::new(json_str) {
4066                Ok(c_str) => {
4067                    clear_error();
4068                    SzConfigTool_result {
4069                        response: c_str.into_raw(),
4070                        returnCode: 0,
4071                    }
4072                }
4073                Err(e) => {
4074                    set_error(format!("Failed to convert result: {e}"), -4);
4075                    SzConfigTool_result {
4076                        response: std::ptr::null_mut(),
4077                        returnCode: -4,
4078                    }
4079                }
4080            }
4081        }
4082        Err(e) => {
4083            set_error(e.to_string(), -5);
4084            SzConfigTool_result {
4085                response: std::ptr::null_mut(),
4086                returnCode: -5,
4087            }
4088        }
4089    }
4090}
4091
4092/// List all standardize calls
4093#[unsafe(no_mangle)]
4094pub extern "C" fn SzConfigTool_listStandardizeCalls(
4095    config_json: *const c_char,
4096) -> SzConfigTool_result {
4097    let config = unsafe {
4098        if config_json.is_null() {
4099            set_error("config_json is null".to_string(), -1);
4100            return SzConfigTool_result {
4101                response: std::ptr::null_mut(),
4102                returnCode: -1,
4103            };
4104        }
4105        match CStr::from_ptr(config_json).to_str() {
4106            Ok(s) => s,
4107            Err(e) => {
4108                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4109                return SzConfigTool_result {
4110                    response: std::ptr::null_mut(),
4111                    returnCode: -2,
4112                };
4113            }
4114        }
4115    };
4116
4117    match crate::calls::standardize::list_standardize_calls(config) {
4118        Ok(vec) => {
4119            let json_str = serde_json::to_string(&vec)
4120                .unwrap_or_else(|e| format!("{{\"error\": \"Failed to serialize: {e}\"}}"));
4121            match CString::new(json_str) {
4122                Ok(c_str) => {
4123                    clear_error();
4124                    SzConfigTool_result {
4125                        response: c_str.into_raw(),
4126                        returnCode: 0,
4127                    }
4128                }
4129                Err(e) => {
4130                    set_error(format!("Failed to convert result: {e}"), -4);
4131                    SzConfigTool_result {
4132                        response: std::ptr::null_mut(),
4133                        returnCode: -4,
4134                    }
4135                }
4136            }
4137        }
4138        Err(e) => {
4139            set_error(e.to_string(), -5);
4140            SzConfigTool_result {
4141                response: std::ptr::null_mut(),
4142                returnCode: -5,
4143            }
4144        }
4145    }
4146}
4147
4148/// Set (update) a standardize call
4149#[unsafe(no_mangle)]
4150pub extern "C" fn SzConfigTool_setStandardizeCall(
4151    config_json: *const c_char,
4152    sfcall_id: i64,
4153    updates_json: *const c_char,
4154) -> SzConfigTool_result {
4155    let config = unsafe {
4156        if config_json.is_null() {
4157            set_error("config_json is null".to_string(), -1);
4158            return SzConfigTool_result {
4159                response: std::ptr::null_mut(),
4160                returnCode: -1,
4161            };
4162        }
4163        match CStr::from_ptr(config_json).to_str() {
4164            Ok(s) => s,
4165            Err(e) => {
4166                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4167                return SzConfigTool_result {
4168                    response: std::ptr::null_mut(),
4169                    returnCode: -2,
4170                };
4171            }
4172        }
4173    };
4174
4175    let updates = unsafe {
4176        if updates_json.is_null() {
4177            set_error("updates_json is null".to_string(), -1);
4178            return SzConfigTool_result {
4179                response: std::ptr::null_mut(),
4180                returnCode: -1,
4181            };
4182        }
4183        match CStr::from_ptr(updates_json).to_str() {
4184            Ok(s) => s,
4185            Err(e) => {
4186                set_error(format!("Invalid UTF-8 in updates_json: {e}"), -2);
4187                return SzConfigTool_result {
4188                    response: std::ptr::null_mut(),
4189                    returnCode: -2,
4190                };
4191            }
4192        }
4193    };
4194
4195    let updates_value: serde_json::Value = match serde_json::from_str(updates) {
4196        Ok(v) => v,
4197        Err(e) => {
4198            set_error(format!("Invalid JSON in updates_json: {e}"), -3);
4199            return SzConfigTool_result {
4200                response: std::ptr::null_mut(),
4201                returnCode: -3,
4202            };
4203        }
4204    };
4205
4206    let params = crate::calls::standardize::SetStandardizeCallParams {
4207        sfcall_id,
4208        exec_order: updates_value.get("execOrder").and_then(|v| v.as_i64()),
4209    };
4210
4211    handle_result!(crate::calls::standardize::set_standardize_call(
4212        config, params
4213    ))
4214}
4215
4216/* ============================================================================
4217 * Threshold Operations (Batch 7)
4218 * ============================================================================ */
4219
4220// ===== Comparison Thresholds =====
4221
4222/// Add a comparison threshold
4223#[unsafe(no_mangle)]
4224pub extern "C" fn SzConfigTool_addComparisonThreshold(
4225    config_json: *const c_char,
4226    cfunc_id: i64,
4227    cfunc_rtnval: *const c_char,
4228    ftype_id: i64,        // Negative = None
4229    exec_order: i64,      // Negative = None
4230    same_score: i64,      // Negative = None
4231    close_score: i64,     // Negative = None
4232    likely_score: i64,    // Negative = None
4233    plausible_score: i64, // Negative = None
4234    un_likely_score: i64, // Negative = None
4235) -> SzConfigTool_result {
4236    let config = unsafe {
4237        if config_json.is_null() {
4238            set_error("config_json is null".to_string(), -1);
4239            return SzConfigTool_result {
4240                response: std::ptr::null_mut(),
4241                returnCode: -1,
4242            };
4243        }
4244        match CStr::from_ptr(config_json).to_str() {
4245            Ok(s) => s,
4246            Err(e) => {
4247                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4248                return SzConfigTool_result {
4249                    response: std::ptr::null_mut(),
4250                    returnCode: -2,
4251                };
4252            }
4253        }
4254    };
4255
4256    let rtnval = unsafe {
4257        if cfunc_rtnval.is_null() {
4258            set_error("cfunc_rtnval is null".to_string(), -1);
4259            return SzConfigTool_result {
4260                response: std::ptr::null_mut(),
4261                returnCode: -1,
4262            };
4263        }
4264        match CStr::from_ptr(cfunc_rtnval).to_str() {
4265            Ok(s) => s,
4266            Err(e) => {
4267                set_error(format!("Invalid UTF-8 in cfunc_rtnval: {e}"), -2);
4268                return SzConfigTool_result {
4269                    response: std::ptr::null_mut(),
4270                    returnCode: -2,
4271                };
4272            }
4273        }
4274    };
4275
4276    // Convert negative values to None
4277    let ftype_opt = if ftype_id < 0 { None } else { Some(ftype_id) };
4278    let exec_opt = if exec_order < 0 {
4279        None
4280    } else {
4281        Some(exec_order)
4282    };
4283    let same_opt = if same_score < 0 {
4284        None
4285    } else {
4286        Some(same_score)
4287    };
4288    let close_opt = if close_score < 0 {
4289        None
4290    } else {
4291        Some(close_score)
4292    };
4293    let likely_opt = if likely_score < 0 {
4294        None
4295    } else {
4296        Some(likely_score)
4297    };
4298    let plausible_opt = if plausible_score < 0 {
4299        None
4300    } else {
4301        Some(plausible_score)
4302    };
4303    let unlikely_opt = if un_likely_score < 0 {
4304        None
4305    } else {
4306        Some(un_likely_score)
4307    };
4308
4309    handle_result!(crate::thresholds::add_comparison_threshold_by_id(
4310        config,
4311        cfunc_id,
4312        ftype_opt,
4313        rtnval,
4314        exec_opt,
4315        same_opt,
4316        close_opt,
4317        likely_opt,
4318        plausible_opt,
4319        unlikely_opt,
4320    ))
4321}
4322
4323/// Delete a comparison threshold
4324#[unsafe(no_mangle)]
4325pub extern "C" fn SzConfigTool_deleteComparisonThreshold(
4326    config_json: *const c_char,
4327    cfrtn_id: i64,
4328) -> SzConfigTool_result {
4329    let config = unsafe {
4330        if config_json.is_null() {
4331            set_error("config_json is null".to_string(), -1);
4332            return SzConfigTool_result {
4333                response: std::ptr::null_mut(),
4334                returnCode: -1,
4335            };
4336        }
4337        match CStr::from_ptr(config_json).to_str() {
4338            Ok(s) => s,
4339            Err(e) => {
4340                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4341                return SzConfigTool_result {
4342                    response: std::ptr::null_mut(),
4343                    returnCode: -2,
4344                };
4345            }
4346        }
4347    };
4348
4349    handle_result!(crate::thresholds::delete_comparison_threshold_by_id(
4350        config, cfrtn_id
4351    ))
4352}
4353
4354/// Set (update) a comparison threshold
4355#[unsafe(no_mangle)]
4356pub extern "C" fn SzConfigTool_setComparisonThreshold(
4357    config_json: *const c_char,
4358    cfrtn_id: i64,
4359    updates_json: *const c_char,
4360) -> SzConfigTool_result {
4361    let config = unsafe {
4362        if config_json.is_null() {
4363            set_error("config_json is null".to_string(), -1);
4364            return SzConfigTool_result {
4365                response: std::ptr::null_mut(),
4366                returnCode: -1,
4367            };
4368        }
4369        match CStr::from_ptr(config_json).to_str() {
4370            Ok(s) => s,
4371            Err(e) => {
4372                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4373                return SzConfigTool_result {
4374                    response: std::ptr::null_mut(),
4375                    returnCode: -2,
4376                };
4377            }
4378        }
4379    };
4380
4381    let updates = unsafe {
4382        if updates_json.is_null() {
4383            set_error("updates_json is null".to_string(), -1);
4384            return SzConfigTool_result {
4385                response: std::ptr::null_mut(),
4386                returnCode: -1,
4387            };
4388        }
4389        match CStr::from_ptr(updates_json).to_str() {
4390            Ok(s) => s,
4391            Err(e) => {
4392                set_error(format!("Invalid UTF-8 in updates_json: {e}"), -2);
4393                return SzConfigTool_result {
4394                    response: std::ptr::null_mut(),
4395                    returnCode: -2,
4396                };
4397            }
4398        }
4399    };
4400
4401    let updates_value: serde_json::Value = match serde_json::from_str(updates) {
4402        Ok(v) => v,
4403        Err(e) => {
4404            set_error(format!("Invalid JSON in updates_json: {e}"), -3);
4405            return SzConfigTool_result {
4406                response: std::ptr::null_mut(),
4407                returnCode: -3,
4408            };
4409        }
4410    };
4411
4412    handle_result!(crate::thresholds::set_comparison_threshold_by_id(
4413        config,
4414        cfrtn_id,
4415        updates_value.get("sameScore").and_then(|v| v.as_i64()),
4416        updates_value.get("closeScore").and_then(|v| v.as_i64()),
4417        updates_value.get("likelyScore").and_then(|v| v.as_i64()),
4418        updates_value.get("plausibleScore").and_then(|v| v.as_i64()),
4419        updates_value.get("unlikelyScore").and_then(|v| v.as_i64()),
4420    ))
4421}
4422
4423/// List all comparison thresholds
4424#[unsafe(no_mangle)]
4425pub extern "C" fn SzConfigTool_listComparisonThresholds(
4426    config_json: *const c_char,
4427) -> SzConfigTool_result {
4428    let config = unsafe {
4429        if config_json.is_null() {
4430            set_error("config_json is null".to_string(), -1);
4431            return SzConfigTool_result {
4432                response: std::ptr::null_mut(),
4433                returnCode: -1,
4434            };
4435        }
4436        match CStr::from_ptr(config_json).to_str() {
4437            Ok(s) => s,
4438            Err(e) => {
4439                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4440                return SzConfigTool_result {
4441                    response: std::ptr::null_mut(),
4442                    returnCode: -2,
4443                };
4444            }
4445        }
4446    };
4447
4448    match crate::thresholds::list_comparison_thresholds(config) {
4449        Ok(list) => match serde_json::to_string(&list) {
4450            Ok(json_str) => match CString::new(json_str) {
4451                Ok(c_str) => {
4452                    clear_error();
4453                    SzConfigTool_result {
4454                        response: c_str.into_raw(),
4455                        returnCode: 0,
4456                    }
4457                }
4458                Err(e) => {
4459                    set_error(format!("Failed to create C string: {e}"), -4);
4460                    SzConfigTool_result {
4461                        response: std::ptr::null_mut(),
4462                        returnCode: -4,
4463                    }
4464                }
4465            },
4466            Err(e) => {
4467                set_error(format!("Failed to serialize list: {e}"), -3);
4468                SzConfigTool_result {
4469                    response: std::ptr::null_mut(),
4470                    returnCode: -3,
4471                }
4472            }
4473        },
4474        Err(e) => {
4475            set_error(e.to_string(), -5);
4476            SzConfigTool_result {
4477                response: std::ptr::null_mut(),
4478                returnCode: -5,
4479            }
4480        }
4481    }
4482}
4483
4484// ===== Generic Thresholds =====
4485
4486/// Add a generic threshold
4487#[unsafe(no_mangle)]
4488pub extern "C" fn SzConfigTool_addGenericThreshold(
4489    config_json: *const c_char,
4490    plan: *const c_char,
4491    behavior: *const c_char,
4492    scoring_cap: i64,
4493    candidate_cap: i64,
4494    send_to_redo: *const c_char,
4495    feature: *const c_char, // Null = "ALL"
4496) -> SzConfigTool_result {
4497    let config = unsafe {
4498        if config_json.is_null() {
4499            set_error("config_json is null".to_string(), -1);
4500            return SzConfigTool_result {
4501                response: std::ptr::null_mut(),
4502                returnCode: -1,
4503            };
4504        }
4505        match CStr::from_ptr(config_json).to_str() {
4506            Ok(s) => s,
4507            Err(e) => {
4508                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4509                return SzConfigTool_result {
4510                    response: std::ptr::null_mut(),
4511                    returnCode: -2,
4512                };
4513            }
4514        }
4515    };
4516
4517    let plan_str = unsafe {
4518        if plan.is_null() {
4519            set_error("plan is null".to_string(), -1);
4520            return SzConfigTool_result {
4521                response: std::ptr::null_mut(),
4522                returnCode: -1,
4523            };
4524        }
4525        match CStr::from_ptr(plan).to_str() {
4526            Ok(s) => s,
4527            Err(e) => {
4528                set_error(format!("Invalid UTF-8 in plan: {e}"), -2);
4529                return SzConfigTool_result {
4530                    response: std::ptr::null_mut(),
4531                    returnCode: -2,
4532                };
4533            }
4534        }
4535    };
4536
4537    let behavior_str = unsafe {
4538        if behavior.is_null() {
4539            set_error("behavior is null".to_string(), -1);
4540            return SzConfigTool_result {
4541                response: std::ptr::null_mut(),
4542                returnCode: -1,
4543            };
4544        }
4545        match CStr::from_ptr(behavior).to_str() {
4546            Ok(s) => s,
4547            Err(e) => {
4548                set_error(format!("Invalid UTF-8 in behavior: {e}"), -2);
4549                return SzConfigTool_result {
4550                    response: std::ptr::null_mut(),
4551                    returnCode: -2,
4552                };
4553            }
4554        }
4555    };
4556
4557    let redo_str = unsafe {
4558        if send_to_redo.is_null() {
4559            set_error("send_to_redo is null".to_string(), -1);
4560            return SzConfigTool_result {
4561                response: std::ptr::null_mut(),
4562                returnCode: -1,
4563            };
4564        }
4565        match CStr::from_ptr(send_to_redo).to_str() {
4566            Ok(s) => s,
4567            Err(e) => {
4568                set_error(format!("Invalid UTF-8 in send_to_redo: {e}"), -2);
4569                return SzConfigTool_result {
4570                    response: std::ptr::null_mut(),
4571                    returnCode: -2,
4572                };
4573            }
4574        }
4575    };
4576
4577    let feature_opt = if feature.is_null() {
4578        None
4579    } else {
4580        unsafe {
4581            match CStr::from_ptr(feature).to_str() {
4582                Ok(s) => Some(s),
4583                Err(e) => {
4584                    set_error(format!("Invalid UTF-8 in feature: {e}"), -2);
4585                    return SzConfigTool_result {
4586                        response: std::ptr::null_mut(),
4587                        returnCode: -2,
4588                    };
4589                }
4590            }
4591        }
4592    };
4593
4594    handle_result!(crate::thresholds::add_generic_threshold(
4595        config,
4596        crate::thresholds::AddGenericThresholdParams {
4597            plan: Some(plan_str),
4598            behavior: Some(behavior_str),
4599            scoring_cap: Some(scoring_cap),
4600            candidate_cap: Some(candidate_cap),
4601            send_to_redo: Some(redo_str),
4602            feature: feature_opt,
4603        },
4604    ))
4605}
4606
4607/// Delete a generic threshold
4608#[unsafe(no_mangle)]
4609pub extern "C" fn SzConfigTool_deleteGenericThreshold(
4610    config_json: *const c_char,
4611    plan: *const c_char,
4612    behavior: *const c_char,
4613    feature: *const c_char, // Null = "ALL"
4614) -> SzConfigTool_result {
4615    let config = unsafe {
4616        if config_json.is_null() {
4617            set_error("config_json is null".to_string(), -1);
4618            return SzConfigTool_result {
4619                response: std::ptr::null_mut(),
4620                returnCode: -1,
4621            };
4622        }
4623        match CStr::from_ptr(config_json).to_str() {
4624            Ok(s) => s,
4625            Err(e) => {
4626                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4627                return SzConfigTool_result {
4628                    response: std::ptr::null_mut(),
4629                    returnCode: -2,
4630                };
4631            }
4632        }
4633    };
4634
4635    let _plan_str = unsafe {
4636        if plan.is_null() {
4637            set_error("plan is null".to_string(), -1);
4638            return SzConfigTool_result {
4639                response: std::ptr::null_mut(),
4640                returnCode: -1,
4641            };
4642        }
4643        match CStr::from_ptr(plan).to_str() {
4644            Ok(s) => s,
4645            Err(e) => {
4646                set_error(format!("Invalid UTF-8 in plan: {e}"), -2);
4647                return SzConfigTool_result {
4648                    response: std::ptr::null_mut(),
4649                    returnCode: -2,
4650                };
4651            }
4652        }
4653    };
4654
4655    let behavior_str = unsafe {
4656        if behavior.is_null() {
4657            set_error("behavior is null".to_string(), -1);
4658            return SzConfigTool_result {
4659                response: std::ptr::null_mut(),
4660                returnCode: -1,
4661            };
4662        }
4663        match CStr::from_ptr(behavior).to_str() {
4664            Ok(s) => s,
4665            Err(e) => {
4666                set_error(format!("Invalid UTF-8 in behavior: {e}"), -2);
4667                return SzConfigTool_result {
4668                    response: std::ptr::null_mut(),
4669                    returnCode: -2,
4670                };
4671            }
4672        }
4673    };
4674
4675    let feature_opt = if feature.is_null() {
4676        None
4677    } else {
4678        unsafe {
4679            match CStr::from_ptr(feature).to_str() {
4680                Ok(s) => Some(s),
4681                Err(e) => {
4682                    set_error(format!("Invalid UTF-8 in feature: {e}"), -2);
4683                    return SzConfigTool_result {
4684                        response: std::ptr::null_mut(),
4685                        returnCode: -2,
4686                    };
4687                }
4688            }
4689        }
4690    };
4691
4692    handle_result!(crate::thresholds::delete_generic_threshold(
4693        config,
4694        crate::thresholds::DeleteGenericThresholdParams {
4695            plan: Some("INGEST"), // Note: gplan_id not provided in this FFI signature
4696            behavior: Some(behavior_str),
4697            feature: feature_opt,
4698        },
4699    ))
4700}
4701
4702/// Set (update) a generic threshold
4703#[unsafe(no_mangle)]
4704pub extern "C" fn SzConfigTool_setGenericThreshold(
4705    config_json: *const c_char,
4706    gplan_id: i64,
4707    behavior: *const c_char,
4708    updates_json: *const c_char,
4709) -> SzConfigTool_result {
4710    let config = unsafe {
4711        if config_json.is_null() {
4712            set_error("config_json is null".to_string(), -1);
4713            return SzConfigTool_result {
4714                response: std::ptr::null_mut(),
4715                returnCode: -1,
4716            };
4717        }
4718        match CStr::from_ptr(config_json).to_str() {
4719            Ok(s) => s,
4720            Err(e) => {
4721                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4722                return SzConfigTool_result {
4723                    response: std::ptr::null_mut(),
4724                    returnCode: -2,
4725                };
4726            }
4727        }
4728    };
4729
4730    let behavior_str = unsafe {
4731        if behavior.is_null() {
4732            set_error("behavior is null".to_string(), -1);
4733            return SzConfigTool_result {
4734                response: std::ptr::null_mut(),
4735                returnCode: -1,
4736            };
4737        }
4738        match CStr::from_ptr(behavior).to_str() {
4739            Ok(s) => s,
4740            Err(e) => {
4741                set_error(format!("Invalid UTF-8 in behavior: {e}"), -2);
4742                return SzConfigTool_result {
4743                    response: std::ptr::null_mut(),
4744                    returnCode: -2,
4745                };
4746            }
4747        }
4748    };
4749
4750    let updates = unsafe {
4751        if updates_json.is_null() {
4752            set_error("updates_json is null".to_string(), -1);
4753            return SzConfigTool_result {
4754                response: std::ptr::null_mut(),
4755                returnCode: -1,
4756            };
4757        }
4758        match CStr::from_ptr(updates_json).to_str() {
4759            Ok(s) => s,
4760            Err(e) => {
4761                set_error(format!("Invalid UTF-8 in updates_json: {e}"), -2);
4762                return SzConfigTool_result {
4763                    response: std::ptr::null_mut(),
4764                    returnCode: -2,
4765                };
4766            }
4767        }
4768    };
4769
4770    let updates_value: serde_json::Value = match serde_json::from_str(updates) {
4771        Ok(v) => v,
4772        Err(e) => {
4773            set_error(format!("Invalid JSON in updates_json: {e}"), -3);
4774            return SzConfigTool_result {
4775                response: std::ptr::null_mut(),
4776                returnCode: -3,
4777            };
4778        }
4779    };
4780
4781    // Lookup plan code from ID
4782    let plan_code_str = match crate::helpers::lookup_gplan_code(config, gplan_id) {
4783        Ok(code) => code,
4784        Err(e) => {
4785            set_error(e.to_string(), -4);
4786            return SzConfigTool_result {
4787                response: std::ptr::null_mut(),
4788                returnCode: -4,
4789            };
4790        }
4791    };
4792
4793    handle_result!(crate::thresholds::set_generic_threshold(
4794        config,
4795        crate::thresholds::SetGenericThresholdParams {
4796            plan: Some(&plan_code_str),
4797            behavior: Some(behavior_str),
4798            feature: updates_value.get("feature").and_then(|v| v.as_str()),
4799            candidate_cap: updates_value.get("candidateCap").and_then(|v| v.as_i64()),
4800            scoring_cap: updates_value.get("scoringCap").and_then(|v| v.as_i64()),
4801            send_to_redo: updates_value.get("sendToRedo").and_then(|v| v.as_str()),
4802        },
4803    ))
4804}
4805
4806/// List all generic thresholds
4807#[unsafe(no_mangle)]
4808pub extern "C" fn SzConfigTool_listGenericThresholds(
4809    config_json: *const c_char,
4810) -> SzConfigTool_result {
4811    let config = unsafe {
4812        if config_json.is_null() {
4813            set_error("config_json is null".to_string(), -1);
4814            return SzConfigTool_result {
4815                response: std::ptr::null_mut(),
4816                returnCode: -1,
4817            };
4818        }
4819        match CStr::from_ptr(config_json).to_str() {
4820            Ok(s) => s,
4821            Err(e) => {
4822                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4823                return SzConfigTool_result {
4824                    response: std::ptr::null_mut(),
4825                    returnCode: -2,
4826                };
4827            }
4828        }
4829    };
4830
4831    match crate::thresholds::list_generic_thresholds(config) {
4832        Ok(list) => match serde_json::to_string(&list) {
4833            Ok(json_str) => match CString::new(json_str) {
4834                Ok(c_str) => {
4835                    clear_error();
4836                    SzConfigTool_result {
4837                        response: c_str.into_raw(),
4838                        returnCode: 0,
4839                    }
4840                }
4841                Err(e) => {
4842                    set_error(format!("Failed to create C string: {e}"), -4);
4843                    SzConfigTool_result {
4844                        response: std::ptr::null_mut(),
4845                        returnCode: -4,
4846                    }
4847                }
4848            },
4849            Err(e) => {
4850                set_error(format!("Failed to serialize list: {e}"), -3);
4851                SzConfigTool_result {
4852                    response: std::ptr::null_mut(),
4853                    returnCode: -3,
4854                }
4855            }
4856        },
4857        Err(e) => {
4858            set_error(e.to_string(), -5);
4859            SzConfigTool_result {
4860                response: std::ptr::null_mut(),
4861                returnCode: -5,
4862            }
4863        }
4864    }
4865}
4866
4867/* ============================================================================
4868 * Fragment & Data Source Operations (Batch 8)
4869 * ============================================================================ */
4870
4871// ===== Fragment Operations =====
4872
4873/// Get a fragment by code or ID
4874#[unsafe(no_mangle)]
4875pub extern "C" fn SzConfigTool_getFragment(
4876    config_json: *const c_char,
4877    code_or_id: *const c_char,
4878) -> SzConfigTool_result {
4879    let config = unsafe {
4880        if config_json.is_null() {
4881            set_error("config_json is null".to_string(), -1);
4882            return SzConfigTool_result {
4883                response: std::ptr::null_mut(),
4884                returnCode: -1,
4885            };
4886        }
4887        match CStr::from_ptr(config_json).to_str() {
4888            Ok(s) => s,
4889            Err(e) => {
4890                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4891                return SzConfigTool_result {
4892                    response: std::ptr::null_mut(),
4893                    returnCode: -2,
4894                };
4895            }
4896        }
4897    };
4898
4899    let code = unsafe {
4900        if code_or_id.is_null() {
4901            set_error("code_or_id is null".to_string(), -1);
4902            return SzConfigTool_result {
4903                response: std::ptr::null_mut(),
4904                returnCode: -1,
4905            };
4906        }
4907        match CStr::from_ptr(code_or_id).to_str() {
4908            Ok(s) => s,
4909            Err(e) => {
4910                set_error(format!("Invalid UTF-8 in code_or_id: {e}"), -2);
4911                return SzConfigTool_result {
4912                    response: std::ptr::null_mut(),
4913                    returnCode: -2,
4914                };
4915            }
4916        }
4917    };
4918
4919    match crate::fragments::get_fragment(config, code) {
4920        Ok(fragment) => match serde_json::to_string(&fragment) {
4921            Ok(json_str) => match CString::new(json_str) {
4922                Ok(c_str) => {
4923                    clear_error();
4924                    SzConfigTool_result {
4925                        response: c_str.into_raw(),
4926                        returnCode: 0,
4927                    }
4928                }
4929                Err(e) => {
4930                    set_error(format!("Failed to create C string: {e}"), -4);
4931                    SzConfigTool_result {
4932                        response: std::ptr::null_mut(),
4933                        returnCode: -4,
4934                    }
4935                }
4936            },
4937            Err(e) => {
4938                set_error(format!("Failed to serialize fragment: {e}"), -3);
4939                SzConfigTool_result {
4940                    response: std::ptr::null_mut(),
4941                    returnCode: -3,
4942                }
4943            }
4944        },
4945        Err(e) => {
4946            set_error(e.to_string(), -5);
4947            SzConfigTool_result {
4948                response: std::ptr::null_mut(),
4949                returnCode: -5,
4950            }
4951        }
4952    }
4953}
4954
4955/// List all fragments
4956#[unsafe(no_mangle)]
4957pub extern "C" fn SzConfigTool_listFragments(config_json: *const c_char) -> SzConfigTool_result {
4958    let config = unsafe {
4959        if config_json.is_null() {
4960            set_error("config_json is null".to_string(), -1);
4961            return SzConfigTool_result {
4962                response: std::ptr::null_mut(),
4963                returnCode: -1,
4964            };
4965        }
4966        match CStr::from_ptr(config_json).to_str() {
4967            Ok(s) => s,
4968            Err(e) => {
4969                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
4970                return SzConfigTool_result {
4971                    response: std::ptr::null_mut(),
4972                    returnCode: -2,
4973                };
4974            }
4975        }
4976    };
4977
4978    match crate::fragments::list_fragments(config) {
4979        Ok(list) => match serde_json::to_string(&list) {
4980            Ok(json_str) => match CString::new(json_str) {
4981                Ok(c_str) => {
4982                    clear_error();
4983                    SzConfigTool_result {
4984                        response: c_str.into_raw(),
4985                        returnCode: 0,
4986                    }
4987                }
4988                Err(e) => {
4989                    set_error(format!("Failed to create C string: {e}"), -4);
4990                    SzConfigTool_result {
4991                        response: std::ptr::null_mut(),
4992                        returnCode: -4,
4993                    }
4994                }
4995            },
4996            Err(e) => {
4997                set_error(format!("Failed to serialize list: {e}"), -3);
4998                SzConfigTool_result {
4999                    response: std::ptr::null_mut(),
5000                    returnCode: -3,
5001                }
5002            }
5003        },
5004        Err(e) => {
5005            set_error(e.to_string(), -5);
5006            SzConfigTool_result {
5007                response: std::ptr::null_mut(),
5008                returnCode: -5,
5009            }
5010        }
5011    }
5012}
5013
5014/// Add a fragment
5015#[unsafe(no_mangle)]
5016pub extern "C" fn SzConfigTool_addFragment(
5017    config_json: *const c_char,
5018    fragment_json: *const c_char,
5019) -> SzConfigTool_result {
5020    let config = unsafe {
5021        if config_json.is_null() {
5022            set_error("config_json is null".to_string(), -1);
5023            return SzConfigTool_result {
5024                response: std::ptr::null_mut(),
5025                returnCode: -1,
5026            };
5027        }
5028        match CStr::from_ptr(config_json).to_str() {
5029            Ok(s) => s,
5030            Err(e) => {
5031                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5032                return SzConfigTool_result {
5033                    response: std::ptr::null_mut(),
5034                    returnCode: -2,
5035                };
5036            }
5037        }
5038    };
5039
5040    let fragment_str = unsafe {
5041        if fragment_json.is_null() {
5042            set_error("fragment_json is null".to_string(), -1);
5043            return SzConfigTool_result {
5044                response: std::ptr::null_mut(),
5045                returnCode: -1,
5046            };
5047        }
5048        match CStr::from_ptr(fragment_json).to_str() {
5049            Ok(s) => s,
5050            Err(e) => {
5051                set_error(format!("Invalid UTF-8 in fragment_json: {e}"), -2);
5052                return SzConfigTool_result {
5053                    response: std::ptr::null_mut(),
5054                    returnCode: -2,
5055                };
5056            }
5057        }
5058    };
5059
5060    let fragment_value: serde_json::Value = match serde_json::from_str(fragment_str) {
5061        Ok(v) => v,
5062        Err(e) => {
5063            set_error(format!("Invalid JSON in fragment_json: {e}"), -3);
5064            return SzConfigTool_result {
5065                response: std::ptr::null_mut(),
5066                returnCode: -3,
5067            };
5068        }
5069    };
5070
5071    match crate::fragments::add_fragment(config, &fragment_value) {
5072        Ok((modified_config, _frag_id)) => match CString::new(modified_config) {
5073            Ok(c_str) => {
5074                clear_error();
5075                SzConfigTool_result {
5076                    response: c_str.into_raw(),
5077                    returnCode: 0,
5078                }
5079            }
5080            Err(e) => {
5081                set_error(format!("Failed to create C string: {e}"), -4);
5082                SzConfigTool_result {
5083                    response: std::ptr::null_mut(),
5084                    returnCode: -4,
5085                }
5086            }
5087        },
5088        Err(e) => {
5089            set_error(e.to_string(), -5);
5090            SzConfigTool_result {
5091                response: std::ptr::null_mut(),
5092                returnCode: -5,
5093            }
5094        }
5095    }
5096}
5097
5098/// Delete a fragment
5099#[unsafe(no_mangle)]
5100pub extern "C" fn SzConfigTool_deleteFragment(
5101    config_json: *const c_char,
5102    fragment_code: *const c_char,
5103) -> SzConfigTool_result {
5104    let config = unsafe {
5105        if config_json.is_null() {
5106            set_error("config_json is null".to_string(), -1);
5107            return SzConfigTool_result {
5108                response: std::ptr::null_mut(),
5109                returnCode: -1,
5110            };
5111        }
5112        match CStr::from_ptr(config_json).to_str() {
5113            Ok(s) => s,
5114            Err(e) => {
5115                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5116                return SzConfigTool_result {
5117                    response: std::ptr::null_mut(),
5118                    returnCode: -2,
5119                };
5120            }
5121        }
5122    };
5123
5124    let code = unsafe {
5125        if fragment_code.is_null() {
5126            set_error("fragment_code is null".to_string(), -1);
5127            return SzConfigTool_result {
5128                response: std::ptr::null_mut(),
5129                returnCode: -1,
5130            };
5131        }
5132        match CStr::from_ptr(fragment_code).to_str() {
5133            Ok(s) => s,
5134            Err(e) => {
5135                set_error(format!("Invalid UTF-8 in fragment_code: {e}"), -2);
5136                return SzConfigTool_result {
5137                    response: std::ptr::null_mut(),
5138                    returnCode: -2,
5139                };
5140            }
5141        }
5142    };
5143
5144    handle_result!(crate::fragments::delete_fragment(config, code))
5145}
5146
5147// ===== Data Source Operations =====
5148
5149/// Get a data source by code
5150#[unsafe(no_mangle)]
5151pub extern "C" fn SzConfigTool_getDataSource(
5152    config_json: *const c_char,
5153    code: *const c_char,
5154) -> SzConfigTool_result {
5155    let config = unsafe {
5156        if config_json.is_null() {
5157            set_error("config_json is null".to_string(), -1);
5158            return SzConfigTool_result {
5159                response: std::ptr::null_mut(),
5160                returnCode: -1,
5161            };
5162        }
5163        match CStr::from_ptr(config_json).to_str() {
5164            Ok(s) => s,
5165            Err(e) => {
5166                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5167                return SzConfigTool_result {
5168                    response: std::ptr::null_mut(),
5169                    returnCode: -2,
5170                };
5171            }
5172        }
5173    };
5174
5175    let ds_code = unsafe {
5176        if code.is_null() {
5177            set_error("code is null".to_string(), -1);
5178            return SzConfigTool_result {
5179                response: std::ptr::null_mut(),
5180                returnCode: -1,
5181            };
5182        }
5183        match CStr::from_ptr(code).to_str() {
5184            Ok(s) => s,
5185            Err(e) => {
5186                set_error(format!("Invalid UTF-8 in code: {e}"), -2);
5187                return SzConfigTool_result {
5188                    response: std::ptr::null_mut(),
5189                    returnCode: -2,
5190                };
5191            }
5192        }
5193    };
5194
5195    match crate::datasources::get_data_source(config, ds_code) {
5196        Ok(data_source) => match serde_json::to_string(&data_source) {
5197            Ok(json_str) => match CString::new(json_str) {
5198                Ok(c_str) => {
5199                    clear_error();
5200                    SzConfigTool_result {
5201                        response: c_str.into_raw(),
5202                        returnCode: 0,
5203                    }
5204                }
5205                Err(e) => {
5206                    set_error(format!("Failed to create C string: {e}"), -4);
5207                    SzConfigTool_result {
5208                        response: std::ptr::null_mut(),
5209                        returnCode: -4,
5210                    }
5211                }
5212            },
5213            Err(e) => {
5214                set_error(format!("Failed to serialize data source: {e}"), -3);
5215                SzConfigTool_result {
5216                    response: std::ptr::null_mut(),
5217                    returnCode: -3,
5218                }
5219            }
5220        },
5221        Err(e) => {
5222            set_error(e.to_string(), -5);
5223            SzConfigTool_result {
5224                response: std::ptr::null_mut(),
5225                returnCode: -5,
5226            }
5227        }
5228    }
5229}
5230
5231/// Set (update) a data source
5232#[unsafe(no_mangle)]
5233pub extern "C" fn SzConfigTool_setDataSource(
5234    config_json: *const c_char,
5235    code: *const c_char,
5236    updates_json: *const c_char,
5237) -> SzConfigTool_result {
5238    let config = unsafe {
5239        if config_json.is_null() {
5240            set_error("config_json is null".to_string(), -1);
5241            return SzConfigTool_result {
5242                response: std::ptr::null_mut(),
5243                returnCode: -1,
5244            };
5245        }
5246        match CStr::from_ptr(config_json).to_str() {
5247            Ok(s) => s,
5248            Err(e) => {
5249                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5250                return SzConfigTool_result {
5251                    response: std::ptr::null_mut(),
5252                    returnCode: -2,
5253                };
5254            }
5255        }
5256    };
5257
5258    let ds_code = unsafe {
5259        if code.is_null() {
5260            set_error("code is null".to_string(), -1);
5261            return SzConfigTool_result {
5262                response: std::ptr::null_mut(),
5263                returnCode: -1,
5264            };
5265        }
5266        match CStr::from_ptr(code).to_str() {
5267            Ok(s) => s,
5268            Err(e) => {
5269                set_error(format!("Invalid UTF-8 in code: {e}"), -2);
5270                return SzConfigTool_result {
5271                    response: std::ptr::null_mut(),
5272                    returnCode: -2,
5273                };
5274            }
5275        }
5276    };
5277
5278    let updates = unsafe {
5279        if updates_json.is_null() {
5280            set_error("updates_json is null".to_string(), -1);
5281            return SzConfigTool_result {
5282                response: std::ptr::null_mut(),
5283                returnCode: -1,
5284            };
5285        }
5286        match CStr::from_ptr(updates_json).to_str() {
5287            Ok(s) => s,
5288            Err(e) => {
5289                set_error(format!("Invalid UTF-8 in updates_json: {e}"), -2);
5290                return SzConfigTool_result {
5291                    response: std::ptr::null_mut(),
5292                    returnCode: -2,
5293                };
5294            }
5295        }
5296    };
5297
5298    let updates_value: serde_json::Value = match serde_json::from_str(updates) {
5299        Ok(v) => v,
5300        Err(e) => {
5301            set_error(format!("Invalid JSON in updates_json: {e}"), -3);
5302            return SzConfigTool_result {
5303                response: std::ptr::null_mut(),
5304                returnCode: -3,
5305            };
5306        }
5307    };
5308
5309    // Build params with code from parameter and optional updates from JSON
5310    let params = crate::datasources::SetDataSourceParams {
5311        code: ds_code,
5312        retention_level: updates_value.get("retentionLevel").and_then(|v| v.as_str()),
5313        conversational: updates_value.get("conversational").and_then(|v| v.as_str()),
5314        reliability: updates_value.get("reliability").and_then(|v| v.as_i64()),
5315    };
5316
5317    handle_result!(crate::datasources::set_data_source(config, params))
5318}
5319
5320/* ============================================================================
5321 * Feature & Element Operations (Batch 9)
5322 * ============================================================================ */
5323
5324// ===== Feature Operations =====
5325
5326/// Add a feature with JSON configuration
5327///
5328/// # Safety
5329/// config_json and feature_json must be valid null-terminated C strings
5330///
5331/// # Parameters
5332/// - config_json: Current configuration
5333/// - feature_code: Feature code (will be uppercased)
5334/// - feature_json: JSON object with feature configuration including:
5335///   - elementList: Array of element definitions (required)
5336///   - class, behavior, candidates, anonymize, derived, history, matchkey (optional)
5337///   - standardize, expression, comparison: Function codes (optional)
5338///   - version, rtype_id (optional)
5339#[unsafe(no_mangle)]
5340pub extern "C" fn SzConfigTool_addFeature(
5341    config_json: *const c_char,
5342    feature_code: *const c_char,
5343    feature_json: *const c_char,
5344) -> SzConfigTool_result {
5345    let config = unsafe {
5346        if config_json.is_null() {
5347            set_error("config_json is null".to_string(), -1);
5348            return SzConfigTool_result {
5349                response: std::ptr::null_mut(),
5350                returnCode: -1,
5351            };
5352        }
5353        match CStr::from_ptr(config_json).to_str() {
5354            Ok(s) => s,
5355            Err(e) => {
5356                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5357                return SzConfigTool_result {
5358                    response: std::ptr::null_mut(),
5359                    returnCode: -2,
5360                };
5361            }
5362        }
5363    };
5364
5365    let code = unsafe {
5366        if feature_code.is_null() {
5367            set_error("feature_code is null".to_string(), -1);
5368            return SzConfigTool_result {
5369                response: std::ptr::null_mut(),
5370                returnCode: -1,
5371            };
5372        }
5373        match CStr::from_ptr(feature_code).to_str() {
5374            Ok(s) => s,
5375            Err(e) => {
5376                set_error(format!("Invalid UTF-8 in feature_code: {e}"), -2);
5377                return SzConfigTool_result {
5378                    response: std::ptr::null_mut(),
5379                    returnCode: -2,
5380                };
5381            }
5382        }
5383    };
5384
5385    let feature_str = unsafe {
5386        if feature_json.is_null() {
5387            set_error("feature_json is null".to_string(), -1);
5388            return SzConfigTool_result {
5389                response: std::ptr::null_mut(),
5390                returnCode: -1,
5391            };
5392        }
5393        match CStr::from_ptr(feature_json).to_str() {
5394            Ok(s) => s,
5395            Err(e) => {
5396                set_error(format!("Invalid UTF-8 in feature_json: {e}"), -2);
5397                return SzConfigTool_result {
5398                    response: std::ptr::null_mut(),
5399                    returnCode: -2,
5400                };
5401            }
5402        }
5403    };
5404
5405    // Parse feature configuration
5406    let feature_config: serde_json::Value = match serde_json::from_str(feature_str) {
5407        Ok(v) => v,
5408        Err(e) => {
5409            set_error(format!("Invalid JSON in feature_json: {e}"), -3);
5410            return SzConfigTool_result {
5411                response: std::ptr::null_mut(),
5412                returnCode: -3,
5413            };
5414        }
5415    };
5416
5417    // Extract parameters from JSON
5418    let element_list = match feature_config
5419        .get("elementList")
5420        .or_else(|| feature_config.get("element_list"))
5421    {
5422        Some(v) => v,
5423        None => {
5424            set_error("Missing required field: elementList".to_string(), -3);
5425            return SzConfigTool_result {
5426                response: std::ptr::null_mut(),
5427                returnCode: -3,
5428            };
5429        }
5430    };
5431
5432    let class = feature_config.get("class").and_then(|v| v.as_str());
5433    let behavior = feature_config.get("behavior").and_then(|v| v.as_str());
5434    let candidates = feature_config.get("candidates").and_then(|v| v.as_str());
5435    let anonymize = feature_config.get("anonymize").and_then(|v| v.as_str());
5436    let derived = feature_config.get("derived").and_then(|v| v.as_str());
5437    let history = feature_config.get("history").and_then(|v| v.as_str());
5438    let matchkey = feature_config
5439        .get("matchkey")
5440        .or_else(|| feature_config.get("matchKey"))
5441        .and_then(|v| v.as_str());
5442    let standardize = feature_config.get("standardize").and_then(|v| v.as_str());
5443    let expression = feature_config.get("expression").and_then(|v| v.as_str());
5444    let comparison = feature_config.get("comparison").and_then(|v| v.as_str());
5445    let version = feature_config.get("version").and_then(|v| v.as_i64());
5446    let rtype_id = feature_config
5447        .get("rtype_id")
5448        .or_else(|| feature_config.get("rtypeId"))
5449        .and_then(|v| v.as_i64());
5450
5451    match crate::features::add_feature(
5452        config,
5453        crate::features::AddFeatureParams {
5454            feature: code,
5455            element_list,
5456            class,
5457            behavior,
5458            candidates,
5459            anonymize,
5460            derived,
5461            history,
5462            matchkey,
5463            standardize,
5464            expression,
5465            comparison,
5466            version,
5467            rtype_id,
5468        },
5469    ) {
5470        Ok(modified_config) => match CString::new(modified_config) {
5471            Ok(c_str) => {
5472                clear_error();
5473                SzConfigTool_result {
5474                    response: c_str.into_raw(),
5475                    returnCode: 0,
5476                }
5477            }
5478            Err(e) => {
5479                set_error(format!("Failed to create C string: {e}"), -4);
5480                SzConfigTool_result {
5481                    response: std::ptr::null_mut(),
5482                    returnCode: -4,
5483                }
5484            }
5485        },
5486        Err(e) => {
5487            set_error(e.to_string(), -5);
5488            SzConfigTool_result {
5489                response: std::ptr::null_mut(),
5490                returnCode: -5,
5491            }
5492        }
5493    }
5494}
5495
5496/// Delete a feature by code or ID
5497#[unsafe(no_mangle)]
5498pub extern "C" fn SzConfigTool_deleteFeature(
5499    config_json: *const c_char,
5500    feature_code_or_id: *const c_char,
5501) -> SzConfigTool_result {
5502    let config = unsafe {
5503        if config_json.is_null() {
5504            set_error("config_json is null".to_string(), -1);
5505            return SzConfigTool_result {
5506                response: std::ptr::null_mut(),
5507                returnCode: -1,
5508            };
5509        }
5510        match CStr::from_ptr(config_json).to_str() {
5511            Ok(s) => s,
5512            Err(e) => {
5513                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5514                return SzConfigTool_result {
5515                    response: std::ptr::null_mut(),
5516                    returnCode: -2,
5517                };
5518            }
5519        }
5520    };
5521
5522    let code_or_id = unsafe {
5523        if feature_code_or_id.is_null() {
5524            set_error("feature_code_or_id is null".to_string(), -1);
5525            return SzConfigTool_result {
5526                response: std::ptr::null_mut(),
5527                returnCode: -1,
5528            };
5529        }
5530        match CStr::from_ptr(feature_code_or_id).to_str() {
5531            Ok(s) => s,
5532            Err(e) => {
5533                set_error(format!("Invalid UTF-8 in feature_code_or_id: {e}"), -2);
5534                return SzConfigTool_result {
5535                    response: std::ptr::null_mut(),
5536                    returnCode: -2,
5537                };
5538            }
5539        }
5540    };
5541
5542    handle_result!(crate::features::delete_feature(config, code_or_id))
5543}
5544
5545/// Set (update) feature properties with JSON
5546#[unsafe(no_mangle)]
5547pub extern "C" fn SzConfigTool_setFeature(
5548    config_json: *const c_char,
5549    feature_code_or_id: *const c_char,
5550    updates_json: *const c_char,
5551) -> SzConfigTool_result {
5552    let config = unsafe {
5553        if config_json.is_null() {
5554            set_error("config_json is null".to_string(), -1);
5555            return SzConfigTool_result {
5556                response: std::ptr::null_mut(),
5557                returnCode: -1,
5558            };
5559        }
5560        match CStr::from_ptr(config_json).to_str() {
5561            Ok(s) => s,
5562            Err(e) => {
5563                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5564                return SzConfigTool_result {
5565                    response: std::ptr::null_mut(),
5566                    returnCode: -2,
5567                };
5568            }
5569        }
5570    };
5571
5572    let code_or_id = unsafe {
5573        if feature_code_or_id.is_null() {
5574            set_error("feature_code_or_id is null".to_string(), -1);
5575            return SzConfigTool_result {
5576                response: std::ptr::null_mut(),
5577                returnCode: -1,
5578            };
5579        }
5580        match CStr::from_ptr(feature_code_or_id).to_str() {
5581            Ok(s) => s,
5582            Err(e) => {
5583                set_error(format!("Invalid UTF-8 in feature_code_or_id: {e}"), -2);
5584                return SzConfigTool_result {
5585                    response: std::ptr::null_mut(),
5586                    returnCode: -2,
5587                };
5588            }
5589        }
5590    };
5591
5592    let updates = unsafe {
5593        if updates_json.is_null() {
5594            set_error("updates_json is null".to_string(), -1);
5595            return SzConfigTool_result {
5596                response: std::ptr::null_mut(),
5597                returnCode: -1,
5598            };
5599        }
5600        match CStr::from_ptr(updates_json).to_str() {
5601            Ok(s) => s,
5602            Err(e) => {
5603                set_error(format!("Invalid UTF-8 in updates_json: {e}"), -2);
5604                return SzConfigTool_result {
5605                    response: std::ptr::null_mut(),
5606                    returnCode: -2,
5607                };
5608            }
5609        }
5610    };
5611
5612    // Parse updates JSON
5613    let updates_config: serde_json::Value = match serde_json::from_str(updates) {
5614        Ok(v) => v,
5615        Err(e) => {
5616            set_error(format!("Invalid JSON in updates_json: {e}"), -3);
5617            return SzConfigTool_result {
5618                response: std::ptr::null_mut(),
5619                returnCode: -3,
5620            };
5621        }
5622    };
5623
5624    // Extract optional parameters
5625    let candidates = updates_config.get("candidates").and_then(|v| v.as_str());
5626    let anonymize = updates_config.get("anonymize").and_then(|v| v.as_str());
5627    let derived = updates_config.get("derived").and_then(|v| v.as_str());
5628    let history = updates_config.get("history").and_then(|v| v.as_str());
5629    let matchkey = updates_config
5630        .get("matchkey")
5631        .or_else(|| updates_config.get("matchKey"))
5632        .and_then(|v| v.as_str());
5633    let behavior = updates_config.get("behavior").and_then(|v| v.as_str());
5634    let class = updates_config.get("class").and_then(|v| v.as_str());
5635    let version = updates_config.get("version").and_then(|v| v.as_i64());
5636    let rtype_id = updates_config
5637        .get("rtypeId")
5638        .or_else(|| updates_config.get("RTYPE_ID"))
5639        .and_then(|v| v.as_i64());
5640
5641    handle_result!(crate::features::set_feature(
5642        config,
5643        crate::features::SetFeatureParams {
5644            feature: code_or_id,
5645            candidates,
5646            anonymize,
5647            derived,
5648            history,
5649            matchkey,
5650            behavior,
5651            class,
5652            version,
5653            rtype_id,
5654        }
5655    ))
5656}
5657
5658// ===== Behavior Override Operations =====
5659
5660/// Add a behavior override for a feature based on usage type
5661#[unsafe(no_mangle)]
5662pub extern "C" fn SzConfigTool_addBehaviorOverride(
5663    config_json: *const c_char,
5664    feature_code: *const c_char,
5665    usage_type: *const c_char,
5666    behavior: *const c_char,
5667) -> SzConfigTool_result {
5668    let config = unsafe {
5669        if config_json.is_null() {
5670            set_error("config_json is null".to_string(), -1);
5671            return SzConfigTool_result {
5672                response: std::ptr::null_mut(),
5673                returnCode: -1,
5674            };
5675        }
5676        match CStr::from_ptr(config_json).to_str() {
5677            Ok(s) => s,
5678            Err(e) => {
5679                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5680                return SzConfigTool_result {
5681                    response: std::ptr::null_mut(),
5682                    returnCode: -2,
5683                };
5684            }
5685        }
5686    };
5687
5688    let feature = unsafe {
5689        if feature_code.is_null() {
5690            set_error("feature_code is null".to_string(), -1);
5691            return SzConfigTool_result {
5692                response: std::ptr::null_mut(),
5693                returnCode: -1,
5694            };
5695        }
5696        match CStr::from_ptr(feature_code).to_str() {
5697            Ok(s) => s,
5698            Err(e) => {
5699                set_error(format!("Invalid UTF-8 in feature_code: {e}"), -2);
5700                return SzConfigTool_result {
5701                    response: std::ptr::null_mut(),
5702                    returnCode: -2,
5703                };
5704            }
5705        }
5706    };
5707
5708    let utype = unsafe {
5709        if usage_type.is_null() {
5710            set_error("usage_type is null".to_string(), -1);
5711            return SzConfigTool_result {
5712                response: std::ptr::null_mut(),
5713                returnCode: -1,
5714            };
5715        }
5716        match CStr::from_ptr(usage_type).to_str() {
5717            Ok(s) => s,
5718            Err(e) => {
5719                set_error(format!("Invalid UTF-8 in usage_type: {e}"), -2);
5720                return SzConfigTool_result {
5721                    response: std::ptr::null_mut(),
5722                    returnCode: -2,
5723                };
5724            }
5725        }
5726    };
5727
5728    let bhvr = unsafe {
5729        if behavior.is_null() {
5730            set_error("behavior is null".to_string(), -1);
5731            return SzConfigTool_result {
5732                response: std::ptr::null_mut(),
5733                returnCode: -1,
5734            };
5735        }
5736        match CStr::from_ptr(behavior).to_str() {
5737            Ok(s) => s,
5738            Err(e) => {
5739                set_error(format!("Invalid UTF-8 in behavior: {e}"), -2);
5740                return SzConfigTool_result {
5741                    response: std::ptr::null_mut(),
5742                    returnCode: -2,
5743                };
5744            }
5745        }
5746    };
5747
5748    handle_result!(crate::behavior_overrides::add_behavior_override(
5749        config,
5750        crate::behavior_overrides::AddBehaviorOverrideParams::new(feature, utype, bhvr)
5751    ))
5752}
5753
5754/// Delete a behavior override
5755#[unsafe(no_mangle)]
5756pub extern "C" fn SzConfigTool_deleteBehaviorOverride(
5757    config_json: *const c_char,
5758    feature_code: *const c_char,
5759    usage_type: *const c_char,
5760) -> SzConfigTool_result {
5761    let config = unsafe {
5762        if config_json.is_null() {
5763            set_error("config_json is null".to_string(), -1);
5764            return SzConfigTool_result {
5765                response: std::ptr::null_mut(),
5766                returnCode: -1,
5767            };
5768        }
5769        match CStr::from_ptr(config_json).to_str() {
5770            Ok(s) => s,
5771            Err(e) => {
5772                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5773                return SzConfigTool_result {
5774                    response: std::ptr::null_mut(),
5775                    returnCode: -2,
5776                };
5777            }
5778        }
5779    };
5780
5781    let feature = unsafe {
5782        if feature_code.is_null() {
5783            set_error("feature_code is null".to_string(), -1);
5784            return SzConfigTool_result {
5785                response: std::ptr::null_mut(),
5786                returnCode: -1,
5787            };
5788        }
5789        match CStr::from_ptr(feature_code).to_str() {
5790            Ok(s) => s,
5791            Err(e) => {
5792                set_error(format!("Invalid UTF-8 in feature_code: {e}"), -2);
5793                return SzConfigTool_result {
5794                    response: std::ptr::null_mut(),
5795                    returnCode: -2,
5796                };
5797            }
5798        }
5799    };
5800
5801    let utype = unsafe {
5802        if usage_type.is_null() {
5803            set_error("usage_type is null".to_string(), -1);
5804            return SzConfigTool_result {
5805                response: std::ptr::null_mut(),
5806                returnCode: -1,
5807            };
5808        }
5809        match CStr::from_ptr(usage_type).to_str() {
5810            Ok(s) => s,
5811            Err(e) => {
5812                set_error(format!("Invalid UTF-8 in usage_type: {e}"), -2);
5813                return SzConfigTool_result {
5814                    response: std::ptr::null_mut(),
5815                    returnCode: -2,
5816                };
5817            }
5818        }
5819    };
5820
5821    handle_result!(crate::behavior_overrides::delete_behavior_override(
5822        config, feature, utype
5823    ))
5824}
5825
5826/// List all behavior overrides
5827#[unsafe(no_mangle)]
5828pub extern "C" fn SzConfigTool_listBehaviorOverrides(
5829    config_json: *const c_char,
5830) -> SzConfigTool_result {
5831    let config = unsafe {
5832        if config_json.is_null() {
5833            set_error("config_json is null".to_string(), -1);
5834            return SzConfigTool_result {
5835                response: std::ptr::null_mut(),
5836                returnCode: -1,
5837            };
5838        }
5839        match CStr::from_ptr(config_json).to_str() {
5840            Ok(s) => s,
5841            Err(e) => {
5842                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5843                return SzConfigTool_result {
5844                    response: std::ptr::null_mut(),
5845                    returnCode: -2,
5846                };
5847            }
5848        }
5849    };
5850
5851    let result = crate::behavior_overrides::list_behavior_overrides(config).and_then(|vec| {
5852        serde_json::to_string(&vec).map_err(|e| SzConfigError::JsonParse(e.to_string()))
5853    });
5854    handle_result!(result)
5855}
5856
5857// ===== Element Operations =====
5858
5859/// Add an element with JSON configuration
5860#[unsafe(no_mangle)]
5861pub extern "C" fn SzConfigTool_addElement(
5862    config_json: *const c_char,
5863    element_code: *const c_char,
5864    element_json: *const c_char,
5865) -> SzConfigTool_result {
5866    let config = unsafe {
5867        if config_json.is_null() {
5868            set_error("config_json is null".to_string(), -1);
5869            return SzConfigTool_result {
5870                response: std::ptr::null_mut(),
5871                returnCode: -1,
5872            };
5873        }
5874        match CStr::from_ptr(config_json).to_str() {
5875            Ok(s) => s,
5876            Err(e) => {
5877                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5878                return SzConfigTool_result {
5879                    response: std::ptr::null_mut(),
5880                    returnCode: -2,
5881                };
5882            }
5883        }
5884    };
5885
5886    let code = unsafe {
5887        if element_code.is_null() {
5888            set_error("element_code is null".to_string(), -1);
5889            return SzConfigTool_result {
5890                response: std::ptr::null_mut(),
5891                returnCode: -1,
5892            };
5893        }
5894        match CStr::from_ptr(element_code).to_str() {
5895            Ok(s) => s,
5896            Err(e) => {
5897                set_error(format!("Invalid UTF-8 in element_code: {e}"), -2);
5898                return SzConfigTool_result {
5899                    response: std::ptr::null_mut(),
5900                    returnCode: -2,
5901                };
5902            }
5903        }
5904    };
5905
5906    let element_str = unsafe {
5907        if element_json.is_null() {
5908            set_error("element_json is null".to_string(), -1);
5909            return SzConfigTool_result {
5910                response: std::ptr::null_mut(),
5911                returnCode: -1,
5912            };
5913        }
5914        match CStr::from_ptr(element_json).to_str() {
5915            Ok(s) => s,
5916            Err(e) => {
5917                set_error(format!("Invalid UTF-8 in element_json: {e}"), -2);
5918                return SzConfigTool_result {
5919                    response: std::ptr::null_mut(),
5920                    returnCode: -2,
5921                };
5922            }
5923        }
5924    };
5925
5926    let element_config: serde_json::Value = match serde_json::from_str(element_str) {
5927        Ok(v) => v,
5928        Err(e) => {
5929            set_error(format!("Invalid JSON in element_json: {e}"), -3);
5930            return SzConfigTool_result {
5931                response: std::ptr::null_mut(),
5932                returnCode: -3,
5933            };
5934        }
5935    };
5936
5937    // Build params from code and JSON config
5938    let params = crate::elements::AddElementParams {
5939        code,
5940        description: element_config
5941            .get("description")
5942            .and_then(|v| v.as_str())
5943            .or_else(|| element_config.get("FELEM_DESC").and_then(|v| v.as_str())),
5944        data_type: element_config
5945            .get("dataType")
5946            .and_then(|v| v.as_str())
5947            .or_else(|| element_config.get("DATA_TYPE").and_then(|v| v.as_str())),
5948        tokenized: element_config
5949            .get("tokenized")
5950            .and_then(|v| v.as_str())
5951            .or_else(|| element_config.get("TOKENIZED").and_then(|v| v.as_str())),
5952    };
5953
5954    handle_result!(crate::elements::add_element(config, params))
5955}
5956
5957/// Delete an element by code
5958#[unsafe(no_mangle)]
5959pub extern "C" fn SzConfigTool_deleteElement(
5960    config_json: *const c_char,
5961    element_code: *const c_char,
5962) -> SzConfigTool_result {
5963    let config = unsafe {
5964        if config_json.is_null() {
5965            set_error("config_json is null".to_string(), -1);
5966            return SzConfigTool_result {
5967                response: std::ptr::null_mut(),
5968                returnCode: -1,
5969            };
5970        }
5971        match CStr::from_ptr(config_json).to_str() {
5972            Ok(s) => s,
5973            Err(e) => {
5974                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
5975                return SzConfigTool_result {
5976                    response: std::ptr::null_mut(),
5977                    returnCode: -2,
5978                };
5979            }
5980        }
5981    };
5982
5983    let code = unsafe {
5984        if element_code.is_null() {
5985            set_error("element_code is null".to_string(), -1);
5986            return SzConfigTool_result {
5987                response: std::ptr::null_mut(),
5988                returnCode: -1,
5989            };
5990        }
5991        match CStr::from_ptr(element_code).to_str() {
5992            Ok(s) => s,
5993            Err(e) => {
5994                set_error(format!("Invalid UTF-8 in element_code: {e}"), -2);
5995                return SzConfigTool_result {
5996                    response: std::ptr::null_mut(),
5997                    returnCode: -2,
5998                };
5999            }
6000        }
6001    };
6002
6003    handle_result!(crate::elements::delete_element(config, code))
6004}
6005
6006/// Set (update) element properties with JSON
6007#[unsafe(no_mangle)]
6008pub extern "C" fn SzConfigTool_setElement(
6009    config_json: *const c_char,
6010    element_code: *const c_char,
6011    updates_json: *const c_char,
6012) -> SzConfigTool_result {
6013    let config = unsafe {
6014        if config_json.is_null() {
6015            set_error("config_json is null".to_string(), -1);
6016            return SzConfigTool_result {
6017                response: std::ptr::null_mut(),
6018                returnCode: -1,
6019            };
6020        }
6021        match CStr::from_ptr(config_json).to_str() {
6022            Ok(s) => s,
6023            Err(e) => {
6024                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6025                return SzConfigTool_result {
6026                    response: std::ptr::null_mut(),
6027                    returnCode: -2,
6028                };
6029            }
6030        }
6031    };
6032
6033    let code = unsafe {
6034        if element_code.is_null() {
6035            set_error("element_code is null".to_string(), -1);
6036            return SzConfigTool_result {
6037                response: std::ptr::null_mut(),
6038                returnCode: -1,
6039            };
6040        }
6041        match CStr::from_ptr(element_code).to_str() {
6042            Ok(s) => s,
6043            Err(e) => {
6044                set_error(format!("Invalid UTF-8 in element_code: {e}"), -2);
6045                return SzConfigTool_result {
6046                    response: std::ptr::null_mut(),
6047                    returnCode: -2,
6048                };
6049            }
6050        }
6051    };
6052
6053    let updates = unsafe {
6054        if updates_json.is_null() {
6055            set_error("updates_json is null".to_string(), -1);
6056            return SzConfigTool_result {
6057                response: std::ptr::null_mut(),
6058                returnCode: -1,
6059            };
6060        }
6061        match CStr::from_ptr(updates_json).to_str() {
6062            Ok(s) => s,
6063            Err(e) => {
6064                set_error(format!("Invalid UTF-8 in updates_json: {e}"), -2);
6065                return SzConfigTool_result {
6066                    response: std::ptr::null_mut(),
6067                    returnCode: -2,
6068                };
6069            }
6070        }
6071    };
6072
6073    let updates_config: serde_json::Value = match serde_json::from_str(updates) {
6074        Ok(v) => v,
6075        Err(e) => {
6076            set_error(format!("Invalid JSON in updates_json: {e}"), -3);
6077            return SzConfigTool_result {
6078                response: std::ptr::null_mut(),
6079                returnCode: -3,
6080            };
6081        }
6082    };
6083
6084    // Build params from code and JSON updates
6085    let params = crate::elements::SetElementParams {
6086        code,
6087        description: updates_config
6088            .get("description")
6089            .and_then(|v| v.as_str())
6090            .or_else(|| updates_config.get("FELEM_DESC").and_then(|v| v.as_str())),
6091        data_type: updates_config
6092            .get("dataType")
6093            .and_then(|v| v.as_str())
6094            .or_else(|| updates_config.get("DATA_TYPE").and_then(|v| v.as_str())),
6095        tokenized: updates_config
6096            .get("tokenized")
6097            .and_then(|v| v.as_str())
6098            .or_else(|| updates_config.get("TOKENIZED").and_then(|v| v.as_str())),
6099    };
6100
6101    handle_result!(crate::elements::set_element(config, params))
6102}
6103
6104/* ============================================================================
6105 * Call Operations - Expression, Comparison, Distinct (Batch 10)
6106 * ============================================================================ */
6107
6108// ===== Expression Call Operations =====
6109
6110/// Add an expression call with JSON element list
6111///
6112/// # Parameters
6113/// - element_list_json: JSON array of element definitions, e.g.:
6114///   [{"element": "NAME_LAST", "required": "Yes", "feature": "NAME"}]
6115///   or simplified: [["NAME", "NAME_LAST", "NAME"], ["NAME", "NAME_FIRST", null]]
6116#[unsafe(no_mangle)]
6117pub extern "C" fn SzConfigTool_addExpressionCall(
6118    config_json: *const c_char,
6119    ftype_code: *const c_char, // NULL or "ALL" for all features
6120    felem_code: *const c_char, // NULL or "N/A" for no element
6121    exec_order: i64,           // Negative = auto-assign
6122    efunc_code: *const c_char,
6123    element_list_json: *const c_char,  // JSON array
6124    expression_feature: *const c_char, // NULL or "N/A" for none
6125    is_virtual: *const c_char,         // "Yes", "No", "Any", "Desired"
6126) -> SzConfigTool_result {
6127    let config = unsafe {
6128        if config_json.is_null() {
6129            set_error("config_json is null".to_string(), -1);
6130            return SzConfigTool_result {
6131                response: std::ptr::null_mut(),
6132                returnCode: -1,
6133            };
6134        }
6135        match CStr::from_ptr(config_json).to_str() {
6136            Ok(s) => s,
6137            Err(e) => {
6138                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6139                return SzConfigTool_result {
6140                    response: std::ptr::null_mut(),
6141                    returnCode: -2,
6142                };
6143            }
6144        }
6145    };
6146
6147    // Handle optional ftype_code
6148    let ftype_opt = if ftype_code.is_null() {
6149        None
6150    } else {
6151        unsafe {
6152            match CStr::from_ptr(ftype_code).to_str() {
6153                Ok(s) => Some(s),
6154                Err(e) => {
6155                    set_error(format!("Invalid UTF-8 in ftype_code: {e}"), -2);
6156                    return SzConfigTool_result {
6157                        response: std::ptr::null_mut(),
6158                        returnCode: -2,
6159                    };
6160                }
6161            }
6162        }
6163    };
6164
6165    // Handle optional felem_code
6166    let felem_opt = if felem_code.is_null() {
6167        None
6168    } else {
6169        unsafe {
6170            match CStr::from_ptr(felem_code).to_str() {
6171                Ok(s) => Some(s),
6172                Err(e) => {
6173                    set_error(format!("Invalid UTF-8 in felem_code: {e}"), -2);
6174                    return SzConfigTool_result {
6175                        response: std::ptr::null_mut(),
6176                        returnCode: -2,
6177                    };
6178                }
6179            }
6180        }
6181    };
6182
6183    let efunc = unsafe {
6184        if efunc_code.is_null() {
6185            set_error("efunc_code is null".to_string(), -1);
6186            return SzConfigTool_result {
6187                response: std::ptr::null_mut(),
6188                returnCode: -1,
6189            };
6190        }
6191        match CStr::from_ptr(efunc_code).to_str() {
6192            Ok(s) => s,
6193            Err(e) => {
6194                set_error(format!("Invalid UTF-8 in efunc_code: {e}"), -2);
6195                return SzConfigTool_result {
6196                    response: std::ptr::null_mut(),
6197                    returnCode: -2,
6198                };
6199            }
6200        }
6201    };
6202
6203    let elem_list_str = unsafe {
6204        if element_list_json.is_null() {
6205            set_error("element_list_json is null".to_string(), -1);
6206            return SzConfigTool_result {
6207                response: std::ptr::null_mut(),
6208                returnCode: -1,
6209            };
6210        }
6211        match CStr::from_ptr(element_list_json).to_str() {
6212            Ok(s) => s,
6213            Err(e) => {
6214                set_error(format!("Invalid UTF-8 in element_list_json: {e}"), -2);
6215                return SzConfigTool_result {
6216                    response: std::ptr::null_mut(),
6217                    returnCode: -2,
6218                };
6219            }
6220        }
6221    };
6222
6223    // Handle optional expression_feature
6224    let expr_feat_opt = if expression_feature.is_null() {
6225        None
6226    } else {
6227        unsafe {
6228            match CStr::from_ptr(expression_feature).to_str() {
6229                Ok(s) => Some(s),
6230                Err(e) => {
6231                    set_error(format!("Invalid UTF-8 in expression_feature: {e}"), -2);
6232                    return SzConfigTool_result {
6233                        response: std::ptr::null_mut(),
6234                        returnCode: -2,
6235                    };
6236                }
6237            }
6238        }
6239    };
6240
6241    let virtual_str = unsafe {
6242        if is_virtual.is_null() {
6243            set_error("is_virtual is null".to_string(), -1);
6244            return SzConfigTool_result {
6245                response: std::ptr::null_mut(),
6246                returnCode: -1,
6247            };
6248        }
6249        match CStr::from_ptr(is_virtual).to_str() {
6250            Ok(s) => s,
6251            Err(e) => {
6252                set_error(format!("Invalid UTF-8 in is_virtual: {e}"), -2);
6253                return SzConfigTool_result {
6254                    response: std::ptr::null_mut(),
6255                    returnCode: -2,
6256                };
6257            }
6258        }
6259    };
6260
6261    // Parse element list JSON
6262    let elem_list_value: serde_json::Value = match serde_json::from_str(elem_list_str) {
6263        Ok(v) => v,
6264        Err(e) => {
6265            set_error(format!("Invalid JSON in element_list_json: {e}"), -3);
6266            return SzConfigTool_result {
6267                response: std::ptr::null_mut(),
6268                returnCode: -3,
6269            };
6270        }
6271    };
6272
6273    // Convert JSON array to Vec<(String, String, Option<String>)>
6274    let element_list: Vec<(String, String, Option<String>)> = match elem_list_value.as_array() {
6275        Some(arr) => {
6276            let mut result = Vec::new();
6277            for item in arr {
6278                // Support both array format: ["element", "required", "feature"]
6279                // and object format: {"element": "...", "required": "...", "feature": "..."}
6280                if let Some(arr_item) = item.as_array() {
6281                    if arr_item.len() >= 2 {
6282                        let element = arr_item[0].as_str().unwrap_or("").to_string();
6283                        let required = arr_item[1].as_str().unwrap_or("Yes").to_string();
6284                        let feature = if arr_item.len() > 2 {
6285                            arr_item[2].as_str().map(|s| s.to_string())
6286                        } else {
6287                            None
6288                        };
6289                        result.push((element, required, feature));
6290                    }
6291                } else if let Some(obj) = item.as_object() {
6292                    let element = obj
6293                        .get("element")
6294                        .and_then(|v| v.as_str())
6295                        .unwrap_or("")
6296                        .to_string();
6297                    let required = obj
6298                        .get("required")
6299                        .and_then(|v| v.as_str())
6300                        .unwrap_or("Yes")
6301                        .to_string();
6302                    let feature = obj
6303                        .get("feature")
6304                        .and_then(|v| v.as_str())
6305                        .map(|s| s.to_string());
6306                    result.push((element, required, feature));
6307                }
6308            }
6309            result
6310        }
6311        None => {
6312            set_error("element_list_json must be a JSON array".to_string(), -3);
6313            return SzConfigTool_result {
6314                response: std::ptr::null_mut(),
6315                returnCode: -3,
6316            };
6317        }
6318    };
6319
6320    let exec_opt = if exec_order < 0 {
6321        None
6322    } else {
6323        Some(exec_order)
6324    };
6325
6326    let call_params = crate::calls::expression::AddExpressionCallParams {
6327        efunc_code: efunc,
6328        element_list,
6329        ftype_code: ftype_opt,
6330        felem_code: felem_opt,
6331        exec_order: exec_opt,
6332        expression_feature: expr_feat_opt,
6333        is_virtual: virtual_str,
6334    };
6335
6336    match crate::calls::expression::add_expression_call(config, call_params) {
6337        Ok((modified_config, _record)) => match CString::new(modified_config) {
6338            Ok(c_str) => {
6339                clear_error();
6340                SzConfigTool_result {
6341                    response: c_str.into_raw(),
6342                    returnCode: 0,
6343                }
6344            }
6345            Err(e) => {
6346                set_error(format!("Failed to create C string: {e}"), -4);
6347                SzConfigTool_result {
6348                    response: std::ptr::null_mut(),
6349                    returnCode: -4,
6350                }
6351            }
6352        },
6353        Err(e) => {
6354            set_error(e.to_string(), -5);
6355            SzConfigTool_result {
6356                response: std::ptr::null_mut(),
6357                returnCode: -5,
6358            }
6359        }
6360    }
6361}
6362
6363/// Delete an expression call by ID
6364#[unsafe(no_mangle)]
6365pub extern "C" fn SzConfigTool_deleteExpressionCall(
6366    config_json: *const c_char,
6367    efcall_id: i64,
6368) -> SzConfigTool_result {
6369    let config = unsafe {
6370        if config_json.is_null() {
6371            set_error("config_json is null".to_string(), -1);
6372            return SzConfigTool_result {
6373                response: std::ptr::null_mut(),
6374                returnCode: -1,
6375            };
6376        }
6377        match CStr::from_ptr(config_json).to_str() {
6378            Ok(s) => s,
6379            Err(e) => {
6380                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6381                return SzConfigTool_result {
6382                    response: std::ptr::null_mut(),
6383                    returnCode: -2,
6384                };
6385            }
6386        }
6387    };
6388
6389    handle_result!(crate::calls::expression::delete_expression_call(
6390        config, efcall_id
6391    ))
6392}
6393
6394/// Get an expression call by ID
6395#[unsafe(no_mangle)]
6396pub extern "C" fn SzConfigTool_getExpressionCall(
6397    config_json: *const c_char,
6398    efcall_id: i64,
6399) -> SzConfigTool_result {
6400    let config = unsafe {
6401        if config_json.is_null() {
6402            set_error("config_json is null".to_string(), -1);
6403            return SzConfigTool_result {
6404                response: std::ptr::null_mut(),
6405                returnCode: -1,
6406            };
6407        }
6408        match CStr::from_ptr(config_json).to_str() {
6409            Ok(s) => s,
6410            Err(e) => {
6411                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6412                return SzConfigTool_result {
6413                    response: std::ptr::null_mut(),
6414                    returnCode: -2,
6415                };
6416            }
6417        }
6418    };
6419
6420    match crate::calls::expression::get_expression_call(config, efcall_id) {
6421        Ok(record) => match serde_json::to_string(&record) {
6422            Ok(json_str) => match CString::new(json_str) {
6423                Ok(c_str) => {
6424                    clear_error();
6425                    SzConfigTool_result {
6426                        response: c_str.into_raw(),
6427                        returnCode: 0,
6428                    }
6429                }
6430                Err(e) => {
6431                    set_error(format!("Failed to create C string: {e}"), -4);
6432                    SzConfigTool_result {
6433                        response: std::ptr::null_mut(),
6434                        returnCode: -4,
6435                    }
6436                }
6437            },
6438            Err(e) => {
6439                set_error(format!("Failed to serialize record: {e}"), -3);
6440                SzConfigTool_result {
6441                    response: std::ptr::null_mut(),
6442                    returnCode: -3,
6443                }
6444            }
6445        },
6446        Err(e) => {
6447            set_error(e.to_string(), -5);
6448            SzConfigTool_result {
6449                response: std::ptr::null_mut(),
6450                returnCode: -5,
6451            }
6452        }
6453    }
6454}
6455
6456/// List all expression calls
6457#[unsafe(no_mangle)]
6458pub extern "C" fn SzConfigTool_listExpressionCalls(
6459    config_json: *const c_char,
6460) -> SzConfigTool_result {
6461    let config = unsafe {
6462        if config_json.is_null() {
6463            set_error("config_json is null".to_string(), -1);
6464            return SzConfigTool_result {
6465                response: std::ptr::null_mut(),
6466                returnCode: -1,
6467            };
6468        }
6469        match CStr::from_ptr(config_json).to_str() {
6470            Ok(s) => s,
6471            Err(e) => {
6472                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6473                return SzConfigTool_result {
6474                    response: std::ptr::null_mut(),
6475                    returnCode: -2,
6476                };
6477            }
6478        }
6479    };
6480
6481    match crate::calls::expression::list_expression_calls(config) {
6482        Ok(list) => match serde_json::to_string(&list) {
6483            Ok(json_str) => match CString::new(json_str) {
6484                Ok(c_str) => {
6485                    clear_error();
6486                    SzConfigTool_result {
6487                        response: c_str.into_raw(),
6488                        returnCode: 0,
6489                    }
6490                }
6491                Err(e) => {
6492                    set_error(format!("Failed to create C string: {e}"), -4);
6493                    SzConfigTool_result {
6494                        response: std::ptr::null_mut(),
6495                        returnCode: -4,
6496                    }
6497                }
6498            },
6499            Err(e) => {
6500                set_error(format!("Failed to serialize list: {e}"), -3);
6501                SzConfigTool_result {
6502                    response: std::ptr::null_mut(),
6503                    returnCode: -3,
6504                }
6505            }
6506        },
6507        Err(e) => {
6508            set_error(e.to_string(), -5);
6509            SzConfigTool_result {
6510                response: std::ptr::null_mut(),
6511                returnCode: -5,
6512            }
6513        }
6514    }
6515}
6516
6517/// Set (update) an expression call
6518#[unsafe(no_mangle)]
6519pub extern "C" fn SzConfigTool_setExpressionCall(
6520    config_json: *const c_char,
6521    efcall_id: i64,
6522    updates_json: *const c_char,
6523) -> SzConfigTool_result {
6524    let config = unsafe {
6525        if config_json.is_null() {
6526            set_error("config_json is null".to_string(), -1);
6527            return SzConfigTool_result {
6528                response: std::ptr::null_mut(),
6529                returnCode: -1,
6530            };
6531        }
6532        match CStr::from_ptr(config_json).to_str() {
6533            Ok(s) => s,
6534            Err(e) => {
6535                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6536                return SzConfigTool_result {
6537                    response: std::ptr::null_mut(),
6538                    returnCode: -2,
6539                };
6540            }
6541        }
6542    };
6543
6544    let updates = unsafe {
6545        if updates_json.is_null() {
6546            set_error("updates_json is null".to_string(), -1);
6547            return SzConfigTool_result {
6548                response: std::ptr::null_mut(),
6549                returnCode: -1,
6550            };
6551        }
6552        match CStr::from_ptr(updates_json).to_str() {
6553            Ok(s) => s,
6554            Err(e) => {
6555                set_error(format!("Invalid UTF-8 in updates_json: {e}"), -2);
6556                return SzConfigTool_result {
6557                    response: std::ptr::null_mut(),
6558                    returnCode: -2,
6559                };
6560            }
6561        }
6562    };
6563
6564    let updates_value: serde_json::Value = match serde_json::from_str(updates) {
6565        Ok(v) => v,
6566        Err(e) => {
6567            set_error(format!("Invalid JSON in updates_json: {e}"), -3);
6568            return SzConfigTool_result {
6569                response: std::ptr::null_mut(),
6570                returnCode: -3,
6571            };
6572        }
6573    };
6574
6575    let params = crate::calls::expression::SetExpressionCallParams {
6576        efcall_id,
6577        exec_order: updates_value.get("execOrder").and_then(|v| v.as_i64()),
6578    };
6579
6580    handle_result!(crate::calls::expression::set_expression_call(
6581        config, params
6582    ))
6583}
6584
6585// ===== Comparison Call Operations =====
6586
6587/// Add a comparison call with JSON element list
6588///
6589/// # Parameters
6590/// - element_list_json: JSON array of element codes, e.g.: ["NAME_LAST", "NAME_FIRST"]
6591#[unsafe(no_mangle)]
6592pub extern "C" fn SzConfigTool_addComparisonCall(
6593    config_json: *const c_char,
6594    ftype_code: *const c_char,
6595    cfunc_code: *const c_char,
6596    element_list_json: *const c_char, // JSON array of strings
6597) -> SzConfigTool_result {
6598    let config = unsafe {
6599        if config_json.is_null() {
6600            set_error("config_json is null".to_string(), -1);
6601            return SzConfigTool_result {
6602                response: std::ptr::null_mut(),
6603                returnCode: -1,
6604            };
6605        }
6606        match CStr::from_ptr(config_json).to_str() {
6607            Ok(s) => s,
6608            Err(e) => {
6609                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6610                return SzConfigTool_result {
6611                    response: std::ptr::null_mut(),
6612                    returnCode: -2,
6613                };
6614            }
6615        }
6616    };
6617
6618    let ftype = unsafe {
6619        if ftype_code.is_null() {
6620            set_error("ftype_code is null".to_string(), -1);
6621            return SzConfigTool_result {
6622                response: std::ptr::null_mut(),
6623                returnCode: -1,
6624            };
6625        }
6626        match CStr::from_ptr(ftype_code).to_str() {
6627            Ok(s) => s,
6628            Err(e) => {
6629                set_error(format!("Invalid UTF-8 in ftype_code: {e}"), -2);
6630                return SzConfigTool_result {
6631                    response: std::ptr::null_mut(),
6632                    returnCode: -2,
6633                };
6634            }
6635        }
6636    };
6637
6638    let cfunc = unsafe {
6639        if cfunc_code.is_null() {
6640            set_error("cfunc_code is null".to_string(), -1);
6641            return SzConfigTool_result {
6642                response: std::ptr::null_mut(),
6643                returnCode: -1,
6644            };
6645        }
6646        match CStr::from_ptr(cfunc_code).to_str() {
6647            Ok(s) => s,
6648            Err(e) => {
6649                set_error(format!("Invalid UTF-8 in cfunc_code: {e}"), -2);
6650                return SzConfigTool_result {
6651                    response: std::ptr::null_mut(),
6652                    returnCode: -2,
6653                };
6654            }
6655        }
6656    };
6657
6658    let elem_list_str = unsafe {
6659        if element_list_json.is_null() {
6660            set_error("element_list_json is null".to_string(), -1);
6661            return SzConfigTool_result {
6662                response: std::ptr::null_mut(),
6663                returnCode: -1,
6664            };
6665        }
6666        match CStr::from_ptr(element_list_json).to_str() {
6667            Ok(s) => s,
6668            Err(e) => {
6669                set_error(format!("Invalid UTF-8 in element_list_json: {e}"), -2);
6670                return SzConfigTool_result {
6671                    response: std::ptr::null_mut(),
6672                    returnCode: -2,
6673                };
6674            }
6675        }
6676    };
6677
6678    // Parse element list JSON
6679    let elem_list_value: serde_json::Value = match serde_json::from_str(elem_list_str) {
6680        Ok(v) => v,
6681        Err(e) => {
6682            set_error(format!("Invalid JSON in element_list_json: {e}"), -3);
6683            return SzConfigTool_result {
6684                response: std::ptr::null_mut(),
6685                returnCode: -3,
6686            };
6687        }
6688    };
6689
6690    // Convert JSON array to Vec<String>
6691    let element_list: Vec<String> = match elem_list_value.as_array() {
6692        Some(arr) => arr
6693            .iter()
6694            .filter_map(|v| v.as_str())
6695            .map(|s| s.to_string())
6696            .collect(),
6697        None => {
6698            set_error("element_list_json must be a JSON array".to_string(), -3);
6699            return SzConfigTool_result {
6700                response: std::ptr::null_mut(),
6701                returnCode: -3,
6702            };
6703        }
6704    };
6705
6706    match crate::calls::comparison::add_comparison_call(
6707        config,
6708        crate::calls::comparison::AddComparisonCallParams {
6709            ftype_code: ftype.to_string(),
6710            cfunc_code: cfunc.to_string(),
6711            element_list,
6712        },
6713    ) {
6714        Ok((modified_config, _record)) => match CString::new(modified_config) {
6715            Ok(c_str) => {
6716                clear_error();
6717                SzConfigTool_result {
6718                    response: c_str.into_raw(),
6719                    returnCode: 0,
6720                }
6721            }
6722            Err(e) => {
6723                set_error(format!("Failed to create C string: {e}"), -4);
6724                SzConfigTool_result {
6725                    response: std::ptr::null_mut(),
6726                    returnCode: -4,
6727                }
6728            }
6729        },
6730        Err(e) => {
6731            set_error(e.to_string(), -5);
6732            SzConfigTool_result {
6733                response: std::ptr::null_mut(),
6734                returnCode: -5,
6735            }
6736        }
6737    }
6738}
6739
6740/// Delete a comparison call by ID
6741#[unsafe(no_mangle)]
6742pub extern "C" fn SzConfigTool_deleteComparisonCall(
6743    config_json: *const c_char,
6744    cfcall_id: i64,
6745) -> SzConfigTool_result {
6746    let config = unsafe {
6747        if config_json.is_null() {
6748            set_error("config_json is null".to_string(), -1);
6749            return SzConfigTool_result {
6750                response: std::ptr::null_mut(),
6751                returnCode: -1,
6752            };
6753        }
6754        match CStr::from_ptr(config_json).to_str() {
6755            Ok(s) => s,
6756            Err(e) => {
6757                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6758                return SzConfigTool_result {
6759                    response: std::ptr::null_mut(),
6760                    returnCode: -2,
6761                };
6762            }
6763        }
6764    };
6765
6766    handle_result!(crate::calls::comparison::delete_comparison_call(
6767        config, cfcall_id
6768    ))
6769}
6770
6771/// Get a comparison call by ID
6772#[unsafe(no_mangle)]
6773pub extern "C" fn SzConfigTool_getComparisonCall(
6774    config_json: *const c_char,
6775    cfcall_id: i64,
6776) -> SzConfigTool_result {
6777    let config = unsafe {
6778        if config_json.is_null() {
6779            set_error("config_json is null".to_string(), -1);
6780            return SzConfigTool_result {
6781                response: std::ptr::null_mut(),
6782                returnCode: -1,
6783            };
6784        }
6785        match CStr::from_ptr(config_json).to_str() {
6786            Ok(s) => s,
6787            Err(e) => {
6788                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6789                return SzConfigTool_result {
6790                    response: std::ptr::null_mut(),
6791                    returnCode: -2,
6792                };
6793            }
6794        }
6795    };
6796
6797    match crate::calls::comparison::get_comparison_call(config, cfcall_id) {
6798        Ok(record) => match serde_json::to_string(&record) {
6799            Ok(json_str) => match CString::new(json_str) {
6800                Ok(c_str) => {
6801                    clear_error();
6802                    SzConfigTool_result {
6803                        response: c_str.into_raw(),
6804                        returnCode: 0,
6805                    }
6806                }
6807                Err(e) => {
6808                    set_error(format!("Failed to create C string: {e}"), -4);
6809                    SzConfigTool_result {
6810                        response: std::ptr::null_mut(),
6811                        returnCode: -4,
6812                    }
6813                }
6814            },
6815            Err(e) => {
6816                set_error(format!("Failed to serialize record: {e}"), -3);
6817                SzConfigTool_result {
6818                    response: std::ptr::null_mut(),
6819                    returnCode: -3,
6820                }
6821            }
6822        },
6823        Err(e) => {
6824            set_error(e.to_string(), -5);
6825            SzConfigTool_result {
6826                response: std::ptr::null_mut(),
6827                returnCode: -5,
6828            }
6829        }
6830    }
6831}
6832
6833/// List all comparison calls
6834#[unsafe(no_mangle)]
6835pub extern "C" fn SzConfigTool_listComparisonCalls(
6836    config_json: *const c_char,
6837) -> SzConfigTool_result {
6838    let config = unsafe {
6839        if config_json.is_null() {
6840            set_error("config_json is null".to_string(), -1);
6841            return SzConfigTool_result {
6842                response: std::ptr::null_mut(),
6843                returnCode: -1,
6844            };
6845        }
6846        match CStr::from_ptr(config_json).to_str() {
6847            Ok(s) => s,
6848            Err(e) => {
6849                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6850                return SzConfigTool_result {
6851                    response: std::ptr::null_mut(),
6852                    returnCode: -2,
6853                };
6854            }
6855        }
6856    };
6857
6858    match crate::calls::comparison::list_comparison_calls(config) {
6859        Ok(list) => match serde_json::to_string(&list) {
6860            Ok(json_str) => match CString::new(json_str) {
6861                Ok(c_str) => {
6862                    clear_error();
6863                    SzConfigTool_result {
6864                        response: c_str.into_raw(),
6865                        returnCode: 0,
6866                    }
6867                }
6868                Err(e) => {
6869                    set_error(format!("Failed to create C string: {e}"), -4);
6870                    SzConfigTool_result {
6871                        response: std::ptr::null_mut(),
6872                        returnCode: -4,
6873                    }
6874                }
6875            },
6876            Err(e) => {
6877                set_error(format!("Failed to serialize list: {e}"), -3);
6878                SzConfigTool_result {
6879                    response: std::ptr::null_mut(),
6880                    returnCode: -3,
6881                }
6882            }
6883        },
6884        Err(e) => {
6885            set_error(e.to_string(), -5);
6886            SzConfigTool_result {
6887                response: std::ptr::null_mut(),
6888                returnCode: -5,
6889            }
6890        }
6891    }
6892}
6893
6894/// Set (update) a comparison call
6895#[unsafe(no_mangle)]
6896pub extern "C" fn SzConfigTool_setComparisonCall(
6897    config_json: *const c_char,
6898    cfcall_id: i64,
6899    updates_json: *const c_char,
6900) -> SzConfigTool_result {
6901    let config = unsafe {
6902        if config_json.is_null() {
6903            set_error("config_json is null".to_string(), -1);
6904            return SzConfigTool_result {
6905                response: std::ptr::null_mut(),
6906                returnCode: -1,
6907            };
6908        }
6909        match CStr::from_ptr(config_json).to_str() {
6910            Ok(s) => s,
6911            Err(e) => {
6912                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
6913                return SzConfigTool_result {
6914                    response: std::ptr::null_mut(),
6915                    returnCode: -2,
6916                };
6917            }
6918        }
6919    };
6920
6921    let updates = unsafe {
6922        if updates_json.is_null() {
6923            set_error("updates_json is null".to_string(), -1);
6924            return SzConfigTool_result {
6925                response: std::ptr::null_mut(),
6926                returnCode: -1,
6927            };
6928        }
6929        match CStr::from_ptr(updates_json).to_str() {
6930            Ok(s) => s,
6931            Err(e) => {
6932                set_error(format!("Invalid UTF-8 in updates_json: {e}"), -2);
6933                return SzConfigTool_result {
6934                    response: std::ptr::null_mut(),
6935                    returnCode: -2,
6936                };
6937            }
6938        }
6939    };
6940
6941    let updates_value: serde_json::Value = match serde_json::from_str(updates) {
6942        Ok(v) => v,
6943        Err(e) => {
6944            set_error(format!("Invalid JSON in updates_json: {e}"), -3);
6945            return SzConfigTool_result {
6946                response: std::ptr::null_mut(),
6947                returnCode: -3,
6948            };
6949        }
6950    };
6951
6952    let params = crate::calls::comparison::SetComparisonCallParams {
6953        cfcall_id,
6954        exec_order: updates_value.get("execOrder").and_then(|v| v.as_i64()),
6955    };
6956
6957    handle_result!(crate::calls::comparison::set_comparison_call(
6958        config, params
6959    ))
6960}
6961
6962// ============================================================================
6963// BATCH 11: DISTINCT CALL OPERATIONS
6964// ============================================================================
6965
6966/// Add a distinct call with JSON element list
6967///
6968/// Creates a distinct call linking a function to a feature with element list.
6969/// Note: Only one distinct call is allowed per feature.
6970///
6971/// # Parameters
6972/// - `config_json`: Configuration JSON string
6973/// - `ftype_code`: Feature type code
6974/// - `dfunc_code`: Distinct function code
6975/// - `element_list_json`: JSON array of element codes, e.g. ["NAME_LAST", "NAME_FIRST"]
6976///
6977/// # Returns
6978/// SzConfigTool_result with modified config or error
6979///
6980/// # Memory
6981/// Caller must free result.response with SzConfigTool_free()
6982#[unsafe(no_mangle)]
6983pub extern "C" fn SzConfigTool_addDistinctCall(
6984    config_json: *const c_char,
6985    ftype_code: *const c_char,
6986    dfunc_code: *const c_char,
6987    element_list_json: *const c_char,
6988) -> SzConfigTool_result {
6989    let config = unsafe {
6990        if config_json.is_null() {
6991            set_error("config_json is null".to_string(), -1);
6992            return SzConfigTool_result {
6993                response: std::ptr::null_mut(),
6994                returnCode: -1,
6995            };
6996        }
6997        match CStr::from_ptr(config_json).to_str() {
6998            Ok(s) => s,
6999            Err(e) => {
7000                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7001                return SzConfigTool_result {
7002                    response: std::ptr::null_mut(),
7003                    returnCode: -2,
7004                };
7005            }
7006        }
7007    };
7008
7009    let ftype = unsafe {
7010        if ftype_code.is_null() {
7011            set_error("ftype_code is null".to_string(), -1);
7012            return SzConfigTool_result {
7013                response: std::ptr::null_mut(),
7014                returnCode: -1,
7015            };
7016        }
7017        match CStr::from_ptr(ftype_code).to_str() {
7018            Ok(s) => s,
7019            Err(e) => {
7020                set_error(format!("Invalid UTF-8 in ftype_code: {e}"), -2);
7021                return SzConfigTool_result {
7022                    response: std::ptr::null_mut(),
7023                    returnCode: -2,
7024                };
7025            }
7026        }
7027    };
7028
7029    let dfunc = unsafe {
7030        if dfunc_code.is_null() {
7031            set_error("dfunc_code is null".to_string(), -1);
7032            return SzConfigTool_result {
7033                response: std::ptr::null_mut(),
7034                returnCode: -1,
7035            };
7036        }
7037        match CStr::from_ptr(dfunc_code).to_str() {
7038            Ok(s) => s,
7039            Err(e) => {
7040                set_error(format!("Invalid UTF-8 in dfunc_code: {e}"), -2);
7041                return SzConfigTool_result {
7042                    response: std::ptr::null_mut(),
7043                    returnCode: -2,
7044                };
7045            }
7046        }
7047    };
7048
7049    let elem_list_json = unsafe {
7050        if element_list_json.is_null() {
7051            set_error("element_list_json is null".to_string(), -1);
7052            return SzConfigTool_result {
7053                response: std::ptr::null_mut(),
7054                returnCode: -1,
7055            };
7056        }
7057        match CStr::from_ptr(element_list_json).to_str() {
7058            Ok(s) => s,
7059            Err(e) => {
7060                set_error(format!("Invalid UTF-8 in element_list_json: {e}"), -2);
7061                return SzConfigTool_result {
7062                    response: std::ptr::null_mut(),
7063                    returnCode: -2,
7064                };
7065            }
7066        }
7067    };
7068
7069    // Parse JSON array of element codes
7070    let elem_list_value: serde_json::Value = match serde_json::from_str(elem_list_json) {
7071        Ok(v) => v,
7072        Err(e) => {
7073            set_error(format!("Failed to parse element_list_json: {e}"), -3);
7074            return SzConfigTool_result {
7075                response: std::ptr::null_mut(),
7076                returnCode: -3,
7077            };
7078        }
7079    };
7080
7081    let element_list: Vec<String> = match elem_list_value.as_array() {
7082        Some(arr) => arr
7083            .iter()
7084            .filter_map(|v| v.as_str())
7085            .map(|s| s.to_string())
7086            .collect(),
7087        None => {
7088            set_error("element_list_json must be a JSON array".to_string(), -3);
7089            return SzConfigTool_result {
7090                response: std::ptr::null_mut(),
7091                returnCode: -3,
7092            };
7093        }
7094    };
7095
7096    match crate::calls::distinct::add_distinct_call(
7097        config,
7098        crate::calls::distinct::AddDistinctCallParams {
7099            ftype_code: ftype.to_string(),
7100            dfunc_code: dfunc.to_string(),
7101            element_list,
7102        },
7103    ) {
7104        Ok((modified_config, _record)) => match CString::new(modified_config) {
7105            Ok(c_str) => {
7106                clear_error();
7107                SzConfigTool_result {
7108                    response: c_str.into_raw(),
7109                    returnCode: 0,
7110                }
7111            }
7112            Err(e) => {
7113                set_error(format!("Failed to create C string: {e}"), -4);
7114                SzConfigTool_result {
7115                    response: std::ptr::null_mut(),
7116                    returnCode: -4,
7117                }
7118            }
7119        },
7120        Err(e) => {
7121            set_error(e.to_string(), -5);
7122            SzConfigTool_result {
7123                response: std::ptr::null_mut(),
7124                returnCode: -5,
7125            }
7126        }
7127    }
7128}
7129
7130/// Delete a distinct call by ID
7131///
7132/// # Parameters
7133/// - `config_json`: Configuration JSON string
7134/// - `dfcall_id`: Distinct call ID to delete
7135///
7136/// # Returns
7137/// SzConfigTool_result with modified config or error
7138///
7139/// # Memory
7140/// Caller must free result.response with SzConfigTool_free()
7141#[unsafe(no_mangle)]
7142pub extern "C" fn SzConfigTool_deleteDistinctCall(
7143    config_json: *const c_char,
7144    dfcall_id: i64,
7145) -> SzConfigTool_result {
7146    let config = unsafe {
7147        if config_json.is_null() {
7148            set_error("config_json is null".to_string(), -1);
7149            return SzConfigTool_result {
7150                response: std::ptr::null_mut(),
7151                returnCode: -1,
7152            };
7153        }
7154        match CStr::from_ptr(config_json).to_str() {
7155            Ok(s) => s,
7156            Err(e) => {
7157                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7158                return SzConfigTool_result {
7159                    response: std::ptr::null_mut(),
7160                    returnCode: -2,
7161                };
7162            }
7163        }
7164    };
7165
7166    match crate::calls::distinct::delete_distinct_call(config, dfcall_id) {
7167        Ok(modified_config) => match CString::new(modified_config) {
7168            Ok(c_str) => {
7169                clear_error();
7170                SzConfigTool_result {
7171                    response: c_str.into_raw(),
7172                    returnCode: 0,
7173                }
7174            }
7175            Err(e) => {
7176                set_error(format!("Failed to create C string: {e}"), -4);
7177                SzConfigTool_result {
7178                    response: std::ptr::null_mut(),
7179                    returnCode: -4,
7180                }
7181            }
7182        },
7183        Err(e) => {
7184            set_error(e.to_string(), -5);
7185            SzConfigTool_result {
7186                response: std::ptr::null_mut(),
7187                returnCode: -5,
7188            }
7189        }
7190    }
7191}
7192
7193/// Get a distinct call by ID
7194///
7195/// Returns JSON representing the distinct call record.
7196///
7197/// # Parameters
7198/// - `config_json`: Configuration JSON string
7199/// - `dfcall_id`: Distinct call ID
7200///
7201/// # Returns
7202/// SzConfigTool_result with JSON record or error
7203///
7204/// # Memory
7205/// Caller must free result.response with SzConfigTool_free()
7206#[unsafe(no_mangle)]
7207pub extern "C" fn SzConfigTool_getDistinctCall(
7208    config_json: *const c_char,
7209    dfcall_id: i64,
7210) -> SzConfigTool_result {
7211    let config = unsafe {
7212        if config_json.is_null() {
7213            set_error("config_json is null".to_string(), -1);
7214            return SzConfigTool_result {
7215                response: std::ptr::null_mut(),
7216                returnCode: -1,
7217            };
7218        }
7219        match CStr::from_ptr(config_json).to_str() {
7220            Ok(s) => s,
7221            Err(e) => {
7222                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7223                return SzConfigTool_result {
7224                    response: std::ptr::null_mut(),
7225                    returnCode: -2,
7226                };
7227            }
7228        }
7229    };
7230
7231    match crate::calls::distinct::get_distinct_call(config, dfcall_id) {
7232        Ok(record) => match serde_json::to_string(&record) {
7233            Ok(json_str) => match CString::new(json_str) {
7234                Ok(c_str) => {
7235                    clear_error();
7236                    SzConfigTool_result {
7237                        response: c_str.into_raw(),
7238                        returnCode: 0,
7239                    }
7240                }
7241                Err(e) => {
7242                    set_error(format!("Failed to create C string: {e}"), -4);
7243                    SzConfigTool_result {
7244                        response: std::ptr::null_mut(),
7245                        returnCode: -4,
7246                    }
7247                }
7248            },
7249            Err(e) => {
7250                set_error(format!("Failed to serialize record: {e}"), -3);
7251                SzConfigTool_result {
7252                    response: std::ptr::null_mut(),
7253                    returnCode: -3,
7254                }
7255            }
7256        },
7257        Err(e) => {
7258            set_error(e.to_string(), -5);
7259            SzConfigTool_result {
7260                response: std::ptr::null_mut(),
7261                returnCode: -5,
7262            }
7263        }
7264    }
7265}
7266
7267/// List all distinct calls
7268///
7269/// Returns JSON array of distinct calls with resolved names.
7270///
7271/// # Parameters
7272/// - `config_json`: Configuration JSON string
7273///
7274/// # Returns
7275/// SzConfigTool_result with JSON array or error
7276///
7277/// # Memory
7278/// Caller must free result.response with SzConfigTool_free()
7279#[unsafe(no_mangle)]
7280pub extern "C" fn SzConfigTool_listDistinctCalls(
7281    config_json: *const c_char,
7282) -> SzConfigTool_result {
7283    let config = unsafe {
7284        if config_json.is_null() {
7285            set_error("config_json is null".to_string(), -1);
7286            return SzConfigTool_result {
7287                response: std::ptr::null_mut(),
7288                returnCode: -1,
7289            };
7290        }
7291        match CStr::from_ptr(config_json).to_str() {
7292            Ok(s) => s,
7293            Err(e) => {
7294                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7295                return SzConfigTool_result {
7296                    response: std::ptr::null_mut(),
7297                    returnCode: -2,
7298                };
7299            }
7300        }
7301    };
7302
7303    match crate::calls::distinct::list_distinct_calls(config) {
7304        Ok(list) => match serde_json::to_string(&list) {
7305            Ok(json_str) => match CString::new(json_str) {
7306                Ok(c_str) => {
7307                    clear_error();
7308                    SzConfigTool_result {
7309                        response: c_str.into_raw(),
7310                        returnCode: 0,
7311                    }
7312                }
7313                Err(e) => {
7314                    set_error(format!("Failed to create C string: {e}"), -4);
7315                    SzConfigTool_result {
7316                        response: std::ptr::null_mut(),
7317                        returnCode: -4,
7318                    }
7319                }
7320            },
7321            Err(e) => {
7322                set_error(format!("Failed to serialize list: {e}"), -3);
7323                SzConfigTool_result {
7324                    response: std::ptr::null_mut(),
7325                    returnCode: -3,
7326                }
7327            }
7328        },
7329        Err(e) => {
7330            set_error(e.to_string(), -5);
7331            SzConfigTool_result {
7332                response: std::ptr::null_mut(),
7333                returnCode: -5,
7334            }
7335        }
7336    }
7337}
7338
7339/// Set (update) a distinct call
7340///
7341/// Note: This is a stub function - not implemented in Python version.
7342///
7343/// # Parameters
7344/// - `config_json`: Configuration JSON string
7345/// - `dfcall_id`: Distinct call ID to update
7346/// - `updates_json`: JSON object with fields to update
7347///
7348/// # Returns
7349/// SzConfigTool_result with modified config or error
7350///
7351/// # Memory
7352/// Caller must free result.response with SzConfigTool_free()
7353#[unsafe(no_mangle)]
7354pub extern "C" fn SzConfigTool_setDistinctCall(
7355    config_json: *const c_char,
7356    dfcall_id: i64,
7357    updates_json: *const c_char,
7358) -> SzConfigTool_result {
7359    let config = unsafe {
7360        if config_json.is_null() {
7361            set_error("config_json is null".to_string(), -1);
7362            return SzConfigTool_result {
7363                response: std::ptr::null_mut(),
7364                returnCode: -1,
7365            };
7366        }
7367        match CStr::from_ptr(config_json).to_str() {
7368            Ok(s) => s,
7369            Err(e) => {
7370                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7371                return SzConfigTool_result {
7372                    response: std::ptr::null_mut(),
7373                    returnCode: -2,
7374                };
7375            }
7376        }
7377    };
7378
7379    let updates = unsafe {
7380        if updates_json.is_null() {
7381            set_error("updates_json is null".to_string(), -1);
7382            return SzConfigTool_result {
7383                response: std::ptr::null_mut(),
7384                returnCode: -1,
7385            };
7386        }
7387        match CStr::from_ptr(updates_json).to_str() {
7388            Ok(s) => s,
7389            Err(e) => {
7390                set_error(format!("Invalid UTF-8 in updates_json: {e}"), -2);
7391                return SzConfigTool_result {
7392                    response: std::ptr::null_mut(),
7393                    returnCode: -2,
7394                };
7395            }
7396        }
7397    };
7398
7399    let updates_value: serde_json::Value = match serde_json::from_str(updates) {
7400        Ok(v) => v,
7401        Err(e) => {
7402            set_error(format!("Failed to parse updates_json: {e}"), -3);
7403            return SzConfigTool_result {
7404                response: std::ptr::null_mut(),
7405                returnCode: -3,
7406            };
7407        }
7408    };
7409
7410    let params = crate::calls::distinct::SetDistinctCallParams {
7411        dfcall_id,
7412        exec_order: updates_value.get("execOrder").and_then(|v| v.as_i64()),
7413    };
7414
7415    match crate::calls::distinct::set_distinct_call(config, params) {
7416        Ok(modified_config) => match CString::new(modified_config) {
7417            Ok(c_str) => {
7418                clear_error();
7419                SzConfigTool_result {
7420                    response: c_str.into_raw(),
7421                    returnCode: 0,
7422                }
7423            }
7424            Err(e) => {
7425                set_error(format!("Failed to create C string: {e}"), -4);
7426                SzConfigTool_result {
7427                    response: std::ptr::null_mut(),
7428                    returnCode: -4,
7429                }
7430            }
7431        },
7432        Err(e) => {
7433            set_error(e.to_string(), -5);
7434            SzConfigTool_result {
7435                response: std::ptr::null_mut(),
7436                returnCode: -5,
7437            }
7438        }
7439    }
7440}
7441
7442// ============================================================================
7443// BATCH 12: MATCHING & DISTINCT FUNCTION OPERATIONS
7444// ============================================================================
7445
7446// --- MATCHING FUNCTIONS (Placeholders) ---
7447
7448/// Add a matching function (placeholder - not implemented)
7449#[unsafe(no_mangle)]
7450pub extern "C" fn SzConfigTool_addMatchingFunction(
7451    config_json: *const c_char,
7452    rtype_code: *const c_char,
7453    matching_func: *const c_char,
7454) -> SzConfigTool_result {
7455    let config = unsafe {
7456        if config_json.is_null() {
7457            set_error("config_json is null".to_string(), -1);
7458            return SzConfigTool_result {
7459                response: std::ptr::null_mut(),
7460                returnCode: -1,
7461            };
7462        }
7463        match CStr::from_ptr(config_json).to_str() {
7464            Ok(s) => s,
7465            Err(e) => {
7466                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7467                return SzConfigTool_result {
7468                    response: std::ptr::null_mut(),
7469                    returnCode: -2,
7470                };
7471            }
7472        }
7473    };
7474
7475    let rtype = unsafe {
7476        if rtype_code.is_null() {
7477            set_error("rtype_code is null".to_string(), -1);
7478            return SzConfigTool_result {
7479                response: std::ptr::null_mut(),
7480                returnCode: -1,
7481            };
7482        }
7483        match CStr::from_ptr(rtype_code).to_str() {
7484            Ok(s) => s,
7485            Err(e) => {
7486                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
7487                return SzConfigTool_result {
7488                    response: std::ptr::null_mut(),
7489                    returnCode: -2,
7490                };
7491            }
7492        }
7493    };
7494
7495    let matching = unsafe {
7496        if matching_func.is_null() {
7497            set_error("matching_func is null".to_string(), -1);
7498            return SzConfigTool_result {
7499                response: std::ptr::null_mut(),
7500                returnCode: -1,
7501            };
7502        }
7503        match CStr::from_ptr(matching_func).to_str() {
7504            Ok(s) => s,
7505            Err(e) => {
7506                set_error(format!("Invalid UTF-8 in matching_func: {e}"), -2);
7507                return SzConfigTool_result {
7508                    response: std::ptr::null_mut(),
7509                    returnCode: -2,
7510                };
7511            }
7512        }
7513    };
7514
7515    match crate::functions::matching::add_matching_function(config, rtype, matching) {
7516        Ok((modified_config, _record)) => match CString::new(modified_config) {
7517            Ok(c_str) => {
7518                clear_error();
7519                SzConfigTool_result {
7520                    response: c_str.into_raw(),
7521                    returnCode: 0,
7522                }
7523            }
7524            Err(e) => {
7525                set_error(format!("Failed to create C string: {e}"), -4);
7526                SzConfigTool_result {
7527                    response: std::ptr::null_mut(),
7528                    returnCode: -4,
7529                }
7530            }
7531        },
7532        Err(e) => {
7533            set_error(e.to_string(), -5);
7534            SzConfigTool_result {
7535                response: std::ptr::null_mut(),
7536                returnCode: -5,
7537            }
7538        }
7539    }
7540}
7541
7542/// Delete a matching function (placeholder - not implemented)
7543#[unsafe(no_mangle)]
7544pub extern "C" fn SzConfigTool_deleteMatchingFunction(
7545    config_json: *const c_char,
7546    rtype_code: *const c_char,
7547) -> SzConfigTool_result {
7548    let config = unsafe {
7549        if config_json.is_null() {
7550            set_error("config_json is null".to_string(), -1);
7551            return SzConfigTool_result {
7552                response: std::ptr::null_mut(),
7553                returnCode: -1,
7554            };
7555        }
7556        match CStr::from_ptr(config_json).to_str() {
7557            Ok(s) => s,
7558            Err(e) => {
7559                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7560                return SzConfigTool_result {
7561                    response: std::ptr::null_mut(),
7562                    returnCode: -2,
7563                };
7564            }
7565        }
7566    };
7567
7568    let rtype = unsafe {
7569        if rtype_code.is_null() {
7570            set_error("rtype_code is null".to_string(), -1);
7571            return SzConfigTool_result {
7572                response: std::ptr::null_mut(),
7573                returnCode: -1,
7574            };
7575        }
7576        match CStr::from_ptr(rtype_code).to_str() {
7577            Ok(s) => s,
7578            Err(e) => {
7579                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
7580                return SzConfigTool_result {
7581                    response: std::ptr::null_mut(),
7582                    returnCode: -2,
7583                };
7584            }
7585        }
7586    };
7587
7588    match crate::functions::matching::delete_matching_function(config, rtype) {
7589        Ok((modified_config, _record)) => match CString::new(modified_config) {
7590            Ok(c_str) => {
7591                clear_error();
7592                SzConfigTool_result {
7593                    response: c_str.into_raw(),
7594                    returnCode: 0,
7595                }
7596            }
7597            Err(e) => {
7598                set_error(format!("Failed to create C string: {e}"), -4);
7599                SzConfigTool_result {
7600                    response: std::ptr::null_mut(),
7601                    returnCode: -4,
7602                }
7603            }
7604        },
7605        Err(e) => {
7606            set_error(e.to_string(), -5);
7607            SzConfigTool_result {
7608                response: std::ptr::null_mut(),
7609                returnCode: -5,
7610            }
7611        }
7612    }
7613}
7614
7615/// Get a matching function (placeholder - not implemented)
7616#[unsafe(no_mangle)]
7617pub extern "C" fn SzConfigTool_getMatchingFunction(
7618    config_json: *const c_char,
7619    rtype_code: *const c_char,
7620) -> SzConfigTool_result {
7621    let config = unsafe {
7622        if config_json.is_null() {
7623            set_error("config_json is null".to_string(), -1);
7624            return SzConfigTool_result {
7625                response: std::ptr::null_mut(),
7626                returnCode: -1,
7627            };
7628        }
7629        match CStr::from_ptr(config_json).to_str() {
7630            Ok(s) => s,
7631            Err(e) => {
7632                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7633                return SzConfigTool_result {
7634                    response: std::ptr::null_mut(),
7635                    returnCode: -2,
7636                };
7637            }
7638        }
7639    };
7640
7641    let rtype = unsafe {
7642        if rtype_code.is_null() {
7643            set_error("rtype_code is null".to_string(), -1);
7644            return SzConfigTool_result {
7645                response: std::ptr::null_mut(),
7646                returnCode: -1,
7647            };
7648        }
7649        match CStr::from_ptr(rtype_code).to_str() {
7650            Ok(s) => s,
7651            Err(e) => {
7652                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
7653                return SzConfigTool_result {
7654                    response: std::ptr::null_mut(),
7655                    returnCode: -2,
7656                };
7657            }
7658        }
7659    };
7660
7661    match crate::functions::matching::get_matching_function(config, rtype) {
7662        Ok(record) => match serde_json::to_string(&record) {
7663            Ok(json_str) => match CString::new(json_str) {
7664                Ok(c_str) => {
7665                    clear_error();
7666                    SzConfigTool_result {
7667                        response: c_str.into_raw(),
7668                        returnCode: 0,
7669                    }
7670                }
7671                Err(e) => {
7672                    set_error(format!("Failed to create C string: {e}"), -4);
7673                    SzConfigTool_result {
7674                        response: std::ptr::null_mut(),
7675                        returnCode: -4,
7676                    }
7677                }
7678            },
7679            Err(e) => {
7680                set_error(format!("Failed to serialize record: {e}"), -3);
7681                SzConfigTool_result {
7682                    response: std::ptr::null_mut(),
7683                    returnCode: -3,
7684                }
7685            }
7686        },
7687        Err(e) => {
7688            set_error(e.to_string(), -5);
7689            SzConfigTool_result {
7690                response: std::ptr::null_mut(),
7691                returnCode: -5,
7692            }
7693        }
7694    }
7695}
7696
7697/// List all matching functions (placeholder - not implemented)
7698#[unsafe(no_mangle)]
7699pub extern "C" fn SzConfigTool_listMatchingFunctions(
7700    config_json: *const c_char,
7701) -> SzConfigTool_result {
7702    let config = unsafe {
7703        if config_json.is_null() {
7704            set_error("config_json is null".to_string(), -1);
7705            return SzConfigTool_result {
7706                response: std::ptr::null_mut(),
7707                returnCode: -1,
7708            };
7709        }
7710        match CStr::from_ptr(config_json).to_str() {
7711            Ok(s) => s,
7712            Err(e) => {
7713                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7714                return SzConfigTool_result {
7715                    response: std::ptr::null_mut(),
7716                    returnCode: -2,
7717                };
7718            }
7719        }
7720    };
7721
7722    match crate::functions::matching::list_matching_functions(config) {
7723        Ok(list) => match serde_json::to_string(&list) {
7724            Ok(json_str) => match CString::new(json_str) {
7725                Ok(c_str) => {
7726                    clear_error();
7727                    SzConfigTool_result {
7728                        response: c_str.into_raw(),
7729                        returnCode: 0,
7730                    }
7731                }
7732                Err(e) => {
7733                    set_error(format!("Failed to create C string: {e}"), -4);
7734                    SzConfigTool_result {
7735                        response: std::ptr::null_mut(),
7736                        returnCode: -4,
7737                    }
7738                }
7739            },
7740            Err(e) => {
7741                set_error(format!("Failed to serialize list: {e}"), -3);
7742                SzConfigTool_result {
7743                    response: std::ptr::null_mut(),
7744                    returnCode: -3,
7745                }
7746            }
7747        },
7748        Err(e) => {
7749            set_error(e.to_string(), -5);
7750            SzConfigTool_result {
7751                response: std::ptr::null_mut(),
7752                returnCode: -5,
7753            }
7754        }
7755    }
7756}
7757
7758/// Set (update) a matching function (placeholder - not implemented)
7759#[unsafe(no_mangle)]
7760pub extern "C" fn SzConfigTool_setMatchingFunction(
7761    config_json: *const c_char,
7762    rtype_code: *const c_char,
7763    matching_func: *const c_char, // NULL allowed
7764) -> SzConfigTool_result {
7765    let config = unsafe {
7766        if config_json.is_null() {
7767            set_error("config_json is null".to_string(), -1);
7768            return SzConfigTool_result {
7769                response: std::ptr::null_mut(),
7770                returnCode: -1,
7771            };
7772        }
7773        match CStr::from_ptr(config_json).to_str() {
7774            Ok(s) => s,
7775            Err(e) => {
7776                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7777                return SzConfigTool_result {
7778                    response: std::ptr::null_mut(),
7779                    returnCode: -2,
7780                };
7781            }
7782        }
7783    };
7784
7785    let rtype = unsafe {
7786        if rtype_code.is_null() {
7787            set_error("rtype_code is null".to_string(), -1);
7788            return SzConfigTool_result {
7789                response: std::ptr::null_mut(),
7790                returnCode: -1,
7791            };
7792        }
7793        match CStr::from_ptr(rtype_code).to_str() {
7794            Ok(s) => s,
7795            Err(e) => {
7796                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
7797                return SzConfigTool_result {
7798                    response: std::ptr::null_mut(),
7799                    returnCode: -2,
7800                };
7801            }
7802        }
7803    };
7804
7805    let matching_opt = if matching_func.is_null() {
7806        None
7807    } else {
7808        unsafe {
7809            match CStr::from_ptr(matching_func).to_str() {
7810                Ok(s) => Some(s),
7811                Err(e) => {
7812                    set_error(format!("Invalid UTF-8 in matching_func: {e}"), -2);
7813                    return SzConfigTool_result {
7814                        response: std::ptr::null_mut(),
7815                        returnCode: -2,
7816                    };
7817                }
7818            }
7819        }
7820    };
7821
7822    match crate::functions::matching::set_matching_function(config, rtype, matching_opt) {
7823        Ok((modified_config, _record)) => match CString::new(modified_config) {
7824            Ok(c_str) => {
7825                clear_error();
7826                SzConfigTool_result {
7827                    response: c_str.into_raw(),
7828                    returnCode: 0,
7829                }
7830            }
7831            Err(e) => {
7832                set_error(format!("Failed to create C string: {e}"), -4);
7833                SzConfigTool_result {
7834                    response: std::ptr::null_mut(),
7835                    returnCode: -4,
7836                }
7837            }
7838        },
7839        Err(e) => {
7840            set_error(e.to_string(), -5);
7841            SzConfigTool_result {
7842                response: std::ptr::null_mut(),
7843                returnCode: -5,
7844            }
7845        }
7846    }
7847}
7848
7849// --- DISTINCT FUNCTIONS (Fully Implemented) ---
7850
7851/// Add a distinct function
7852#[unsafe(no_mangle)]
7853pub extern "C" fn SzConfigTool_addDistinctFunction(
7854    config_json: *const c_char,
7855    dfunc_code: *const c_char,
7856    connect_str: *const c_char,
7857    dfunc_desc: *const c_char, // NULL allowed
7858    language: *const c_char,   // NULL allowed
7859) -> SzConfigTool_result {
7860    let config = unsafe {
7861        if config_json.is_null() {
7862            set_error("config_json is null".to_string(), -1);
7863            return SzConfigTool_result {
7864                response: std::ptr::null_mut(),
7865                returnCode: -1,
7866            };
7867        }
7868        match CStr::from_ptr(config_json).to_str() {
7869            Ok(s) => s,
7870            Err(e) => {
7871                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
7872                return SzConfigTool_result {
7873                    response: std::ptr::null_mut(),
7874                    returnCode: -2,
7875                };
7876            }
7877        }
7878    };
7879
7880    let dfunc = unsafe {
7881        if dfunc_code.is_null() {
7882            set_error("dfunc_code is null".to_string(), -1);
7883            return SzConfigTool_result {
7884                response: std::ptr::null_mut(),
7885                returnCode: -1,
7886            };
7887        }
7888        match CStr::from_ptr(dfunc_code).to_str() {
7889            Ok(s) => s,
7890            Err(e) => {
7891                set_error(format!("Invalid UTF-8 in dfunc_code: {e}"), -2);
7892                return SzConfigTool_result {
7893                    response: std::ptr::null_mut(),
7894                    returnCode: -2,
7895                };
7896            }
7897        }
7898    };
7899
7900    let connect = unsafe {
7901        if connect_str.is_null() {
7902            set_error("connect_str is null".to_string(), -1);
7903            return SzConfigTool_result {
7904                response: std::ptr::null_mut(),
7905                returnCode: -1,
7906            };
7907        }
7908        match CStr::from_ptr(connect_str).to_str() {
7909            Ok(s) => s,
7910            Err(e) => {
7911                set_error(format!("Invalid UTF-8 in connect_str: {e}"), -2);
7912                return SzConfigTool_result {
7913                    response: std::ptr::null_mut(),
7914                    returnCode: -2,
7915                };
7916            }
7917        }
7918    };
7919
7920    let desc_opt = if dfunc_desc.is_null() {
7921        None
7922    } else {
7923        unsafe {
7924            match CStr::from_ptr(dfunc_desc).to_str() {
7925                Ok(s) => Some(s),
7926                Err(e) => {
7927                    set_error(format!("Invalid UTF-8 in dfunc_desc: {e}"), -2);
7928                    return SzConfigTool_result {
7929                        response: std::ptr::null_mut(),
7930                        returnCode: -2,
7931                    };
7932                }
7933            }
7934        }
7935    };
7936
7937    let lang_opt = if language.is_null() {
7938        None
7939    } else {
7940        unsafe {
7941            match CStr::from_ptr(language).to_str() {
7942                Ok(s) => Some(s),
7943                Err(e) => {
7944                    set_error(format!("Invalid UTF-8 in language: {e}"), -2);
7945                    return SzConfigTool_result {
7946                        response: std::ptr::null_mut(),
7947                        returnCode: -2,
7948                    };
7949                }
7950            }
7951        }
7952    };
7953
7954    match crate::functions::distinct::add_distinct_function(
7955        config,
7956        dfunc,
7957        crate::functions::distinct::AddDistinctFunctionParams {
7958            connect_str: connect,
7959            description: desc_opt,
7960            language: lang_opt,
7961        },
7962    ) {
7963        Ok((modified_config, _record)) => match CString::new(modified_config) {
7964            Ok(c_str) => {
7965                clear_error();
7966                SzConfigTool_result {
7967                    response: c_str.into_raw(),
7968                    returnCode: 0,
7969                }
7970            }
7971            Err(e) => {
7972                set_error(format!("Failed to create C string: {e}"), -4);
7973                SzConfigTool_result {
7974                    response: std::ptr::null_mut(),
7975                    returnCode: -4,
7976                }
7977            }
7978        },
7979        Err(e) => {
7980            set_error(e.to_string(), -5);
7981            SzConfigTool_result {
7982                response: std::ptr::null_mut(),
7983                returnCode: -5,
7984            }
7985        }
7986    }
7987}
7988
7989/// Delete a distinct function by code
7990#[unsafe(no_mangle)]
7991pub extern "C" fn SzConfigTool_deleteDistinctFunction(
7992    config_json: *const c_char,
7993    dfunc_code: *const c_char,
7994) -> SzConfigTool_result {
7995    let config = unsafe {
7996        if config_json.is_null() {
7997            set_error("config_json is null".to_string(), -1);
7998            return SzConfigTool_result {
7999                response: std::ptr::null_mut(),
8000                returnCode: -1,
8001            };
8002        }
8003        match CStr::from_ptr(config_json).to_str() {
8004            Ok(s) => s,
8005            Err(e) => {
8006                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8007                return SzConfigTool_result {
8008                    response: std::ptr::null_mut(),
8009                    returnCode: -2,
8010                };
8011            }
8012        }
8013    };
8014
8015    let dfunc = unsafe {
8016        if dfunc_code.is_null() {
8017            set_error("dfunc_code is null".to_string(), -1);
8018            return SzConfigTool_result {
8019                response: std::ptr::null_mut(),
8020                returnCode: -1,
8021            };
8022        }
8023        match CStr::from_ptr(dfunc_code).to_str() {
8024            Ok(s) => s,
8025            Err(e) => {
8026                set_error(format!("Invalid UTF-8 in dfunc_code: {e}"), -2);
8027                return SzConfigTool_result {
8028                    response: std::ptr::null_mut(),
8029                    returnCode: -2,
8030                };
8031            }
8032        }
8033    };
8034
8035    match crate::functions::distinct::delete_distinct_function(config, dfunc) {
8036        Ok((modified_config, _record)) => match CString::new(modified_config) {
8037            Ok(c_str) => {
8038                clear_error();
8039                SzConfigTool_result {
8040                    response: c_str.into_raw(),
8041                    returnCode: 0,
8042                }
8043            }
8044            Err(e) => {
8045                set_error(format!("Failed to create C string: {e}"), -4);
8046                SzConfigTool_result {
8047                    response: std::ptr::null_mut(),
8048                    returnCode: -4,
8049                }
8050            }
8051        },
8052        Err(e) => {
8053            set_error(e.to_string(), -5);
8054            SzConfigTool_result {
8055                response: std::ptr::null_mut(),
8056                returnCode: -5,
8057            }
8058        }
8059    }
8060}
8061
8062/// Get a distinct function by code
8063#[unsafe(no_mangle)]
8064pub extern "C" fn SzConfigTool_getDistinctFunction(
8065    config_json: *const c_char,
8066    dfunc_code: *const c_char,
8067) -> SzConfigTool_result {
8068    let config = unsafe {
8069        if config_json.is_null() {
8070            set_error("config_json is null".to_string(), -1);
8071            return SzConfigTool_result {
8072                response: std::ptr::null_mut(),
8073                returnCode: -1,
8074            };
8075        }
8076        match CStr::from_ptr(config_json).to_str() {
8077            Ok(s) => s,
8078            Err(e) => {
8079                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8080                return SzConfigTool_result {
8081                    response: std::ptr::null_mut(),
8082                    returnCode: -2,
8083                };
8084            }
8085        }
8086    };
8087
8088    let dfunc = unsafe {
8089        if dfunc_code.is_null() {
8090            set_error("dfunc_code is null".to_string(), -1);
8091            return SzConfigTool_result {
8092                response: std::ptr::null_mut(),
8093                returnCode: -1,
8094            };
8095        }
8096        match CStr::from_ptr(dfunc_code).to_str() {
8097            Ok(s) => s,
8098            Err(e) => {
8099                set_error(format!("Invalid UTF-8 in dfunc_code: {e}"), -2);
8100                return SzConfigTool_result {
8101                    response: std::ptr::null_mut(),
8102                    returnCode: -2,
8103                };
8104            }
8105        }
8106    };
8107
8108    match crate::functions::distinct::get_distinct_function(config, dfunc) {
8109        Ok(record) => match serde_json::to_string(&record) {
8110            Ok(json_str) => match CString::new(json_str) {
8111                Ok(c_str) => {
8112                    clear_error();
8113                    SzConfigTool_result {
8114                        response: c_str.into_raw(),
8115                        returnCode: 0,
8116                    }
8117                }
8118                Err(e) => {
8119                    set_error(format!("Failed to create C string: {e}"), -4);
8120                    SzConfigTool_result {
8121                        response: std::ptr::null_mut(),
8122                        returnCode: -4,
8123                    }
8124                }
8125            },
8126            Err(e) => {
8127                set_error(format!("Failed to serialize record: {e}"), -3);
8128                SzConfigTool_result {
8129                    response: std::ptr::null_mut(),
8130                    returnCode: -3,
8131                }
8132            }
8133        },
8134        Err(e) => {
8135            set_error(e.to_string(), -5);
8136            SzConfigTool_result {
8137                response: std::ptr::null_mut(),
8138                returnCode: -5,
8139            }
8140        }
8141    }
8142}
8143
8144/// List all distinct functions
8145#[unsafe(no_mangle)]
8146pub extern "C" fn SzConfigTool_listDistinctFunctions(
8147    config_json: *const c_char,
8148) -> SzConfigTool_result {
8149    let config = unsafe {
8150        if config_json.is_null() {
8151            set_error("config_json is null".to_string(), -1);
8152            return SzConfigTool_result {
8153                response: std::ptr::null_mut(),
8154                returnCode: -1,
8155            };
8156        }
8157        match CStr::from_ptr(config_json).to_str() {
8158            Ok(s) => s,
8159            Err(e) => {
8160                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8161                return SzConfigTool_result {
8162                    response: std::ptr::null_mut(),
8163                    returnCode: -2,
8164                };
8165            }
8166        }
8167    };
8168
8169    match crate::functions::distinct::list_distinct_functions(config) {
8170        Ok(list) => match serde_json::to_string(&list) {
8171            Ok(json_str) => match CString::new(json_str) {
8172                Ok(c_str) => {
8173                    clear_error();
8174                    SzConfigTool_result {
8175                        response: c_str.into_raw(),
8176                        returnCode: 0,
8177                    }
8178                }
8179                Err(e) => {
8180                    set_error(format!("Failed to create C string: {e}"), -4);
8181                    SzConfigTool_result {
8182                        response: std::ptr::null_mut(),
8183                        returnCode: -4,
8184                    }
8185                }
8186            },
8187            Err(e) => {
8188                set_error(format!("Failed to serialize list: {e}"), -3);
8189                SzConfigTool_result {
8190                    response: std::ptr::null_mut(),
8191                    returnCode: -3,
8192                }
8193            }
8194        },
8195        Err(e) => {
8196            set_error(e.to_string(), -5);
8197            SzConfigTool_result {
8198                response: std::ptr::null_mut(),
8199                returnCode: -5,
8200            }
8201        }
8202    }
8203}
8204
8205/// Set (update) a distinct function
8206#[unsafe(no_mangle)]
8207pub extern "C" fn SzConfigTool_setDistinctFunction(
8208    config_json: *const c_char,
8209    dfunc_code: *const c_char,
8210    connect_str: *const c_char, // NULL allowed
8211    dfunc_desc: *const c_char,  // NULL allowed
8212    language: *const c_char,    // NULL allowed
8213) -> SzConfigTool_result {
8214    let config = unsafe {
8215        if config_json.is_null() {
8216            set_error("config_json is null".to_string(), -1);
8217            return SzConfigTool_result {
8218                response: std::ptr::null_mut(),
8219                returnCode: -1,
8220            };
8221        }
8222        match CStr::from_ptr(config_json).to_str() {
8223            Ok(s) => s,
8224            Err(e) => {
8225                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8226                return SzConfigTool_result {
8227                    response: std::ptr::null_mut(),
8228                    returnCode: -2,
8229                };
8230            }
8231        }
8232    };
8233
8234    let dfunc = unsafe {
8235        if dfunc_code.is_null() {
8236            set_error("dfunc_code is null".to_string(), -1);
8237            return SzConfigTool_result {
8238                response: std::ptr::null_mut(),
8239                returnCode: -1,
8240            };
8241        }
8242        match CStr::from_ptr(dfunc_code).to_str() {
8243            Ok(s) => s,
8244            Err(e) => {
8245                set_error(format!("Invalid UTF-8 in dfunc_code: {e}"), -2);
8246                return SzConfigTool_result {
8247                    response: std::ptr::null_mut(),
8248                    returnCode: -2,
8249                };
8250            }
8251        }
8252    };
8253
8254    let connect_opt = if connect_str.is_null() {
8255        None
8256    } else {
8257        unsafe {
8258            match CStr::from_ptr(connect_str).to_str() {
8259                Ok(s) => Some(s),
8260                Err(e) => {
8261                    set_error(format!("Invalid UTF-8 in connect_str: {e}"), -2);
8262                    return SzConfigTool_result {
8263                        response: std::ptr::null_mut(),
8264                        returnCode: -2,
8265                    };
8266                }
8267            }
8268        }
8269    };
8270
8271    let desc_opt = if dfunc_desc.is_null() {
8272        None
8273    } else {
8274        unsafe {
8275            match CStr::from_ptr(dfunc_desc).to_str() {
8276                Ok(s) => Some(s),
8277                Err(e) => {
8278                    set_error(format!("Invalid UTF-8 in dfunc_desc: {e}"), -2);
8279                    return SzConfigTool_result {
8280                        response: std::ptr::null_mut(),
8281                        returnCode: -2,
8282                    };
8283                }
8284            }
8285        }
8286    };
8287
8288    let lang_opt = if language.is_null() {
8289        None
8290    } else {
8291        unsafe {
8292            match CStr::from_ptr(language).to_str() {
8293                Ok(s) => Some(s),
8294                Err(e) => {
8295                    set_error(format!("Invalid UTF-8 in language: {e}"), -2);
8296                    return SzConfigTool_result {
8297                        response: std::ptr::null_mut(),
8298                        returnCode: -2,
8299                    };
8300                }
8301            }
8302        }
8303    };
8304
8305    match crate::functions::distinct::set_distinct_function(
8306        config,
8307        dfunc,
8308        crate::functions::distinct::SetDistinctFunctionParams {
8309            connect_str: connect_opt,
8310            description: desc_opt,
8311            language: lang_opt,
8312        },
8313    ) {
8314        Ok((modified_config, _record)) => match CString::new(modified_config) {
8315            Ok(c_str) => {
8316                clear_error();
8317                SzConfigTool_result {
8318                    response: c_str.into_raw(),
8319                    returnCode: 0,
8320                }
8321            }
8322            Err(e) => {
8323                set_error(format!("Failed to create C string: {e}"), -4);
8324                SzConfigTool_result {
8325                    response: std::ptr::null_mut(),
8326                    returnCode: -4,
8327                }
8328            }
8329        },
8330        Err(e) => {
8331            set_error(e.to_string(), -5);
8332            SzConfigTool_result {
8333                response: std::ptr::null_mut(),
8334                returnCode: -5,
8335            }
8336        }
8337    }
8338}
8339
8340// ============================================================================
8341// BATCH 13: CANDIDATE & VALIDATION FUNCTION OPERATIONS (Placeholders)
8342// ============================================================================
8343
8344// --- CANDIDATE FUNCTIONS ---
8345
8346/// Add a candidate function (placeholder - not implemented)
8347#[unsafe(no_mangle)]
8348pub extern "C" fn SzConfigTool_addCandidateFunction(
8349    config_json: *const c_char,
8350    rtype_code: *const c_char,
8351    candidate_func: *const c_char,
8352) -> SzConfigTool_result {
8353    let config = unsafe {
8354        if config_json.is_null() {
8355            set_error("config_json is null".to_string(), -1);
8356            return SzConfigTool_result {
8357                response: std::ptr::null_mut(),
8358                returnCode: -1,
8359            };
8360        }
8361        match CStr::from_ptr(config_json).to_str() {
8362            Ok(s) => s,
8363            Err(e) => {
8364                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8365                return SzConfigTool_result {
8366                    response: std::ptr::null_mut(),
8367                    returnCode: -2,
8368                };
8369            }
8370        }
8371    };
8372
8373    let rtype = unsafe {
8374        if rtype_code.is_null() {
8375            set_error("rtype_code is null".to_string(), -1);
8376            return SzConfigTool_result {
8377                response: std::ptr::null_mut(),
8378                returnCode: -1,
8379            };
8380        }
8381        match CStr::from_ptr(rtype_code).to_str() {
8382            Ok(s) => s,
8383            Err(e) => {
8384                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
8385                return SzConfigTool_result {
8386                    response: std::ptr::null_mut(),
8387                    returnCode: -2,
8388                };
8389            }
8390        }
8391    };
8392
8393    let candidate = unsafe {
8394        if candidate_func.is_null() {
8395            set_error("candidate_func is null".to_string(), -1);
8396            return SzConfigTool_result {
8397                response: std::ptr::null_mut(),
8398                returnCode: -1,
8399            };
8400        }
8401        match CStr::from_ptr(candidate_func).to_str() {
8402            Ok(s) => s,
8403            Err(e) => {
8404                set_error(format!("Invalid UTF-8 in candidate_func: {e}"), -2);
8405                return SzConfigTool_result {
8406                    response: std::ptr::null_mut(),
8407                    returnCode: -2,
8408                };
8409            }
8410        }
8411    };
8412
8413    match crate::functions::candidate::add_candidate_function(config, rtype, candidate) {
8414        Ok((modified_config, _record)) => match CString::new(modified_config) {
8415            Ok(c_str) => {
8416                clear_error();
8417                SzConfigTool_result {
8418                    response: c_str.into_raw(),
8419                    returnCode: 0,
8420                }
8421            }
8422            Err(e) => {
8423                set_error(format!("Failed to create C string: {e}"), -4);
8424                SzConfigTool_result {
8425                    response: std::ptr::null_mut(),
8426                    returnCode: -4,
8427                }
8428            }
8429        },
8430        Err(e) => {
8431            set_error(e.to_string(), -5);
8432            SzConfigTool_result {
8433                response: std::ptr::null_mut(),
8434                returnCode: -5,
8435            }
8436        }
8437    }
8438}
8439
8440/// Delete a candidate function (placeholder - not implemented)
8441#[unsafe(no_mangle)]
8442pub extern "C" fn SzConfigTool_deleteCandidateFunction(
8443    config_json: *const c_char,
8444    rtype_code: *const c_char,
8445) -> SzConfigTool_result {
8446    let config = unsafe {
8447        if config_json.is_null() {
8448            set_error("config_json is null".to_string(), -1);
8449            return SzConfigTool_result {
8450                response: std::ptr::null_mut(),
8451                returnCode: -1,
8452            };
8453        }
8454        match CStr::from_ptr(config_json).to_str() {
8455            Ok(s) => s,
8456            Err(e) => {
8457                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8458                return SzConfigTool_result {
8459                    response: std::ptr::null_mut(),
8460                    returnCode: -2,
8461                };
8462            }
8463        }
8464    };
8465
8466    let rtype = unsafe {
8467        if rtype_code.is_null() {
8468            set_error("rtype_code is null".to_string(), -1);
8469            return SzConfigTool_result {
8470                response: std::ptr::null_mut(),
8471                returnCode: -1,
8472            };
8473        }
8474        match CStr::from_ptr(rtype_code).to_str() {
8475            Ok(s) => s,
8476            Err(e) => {
8477                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
8478                return SzConfigTool_result {
8479                    response: std::ptr::null_mut(),
8480                    returnCode: -2,
8481                };
8482            }
8483        }
8484    };
8485
8486    match crate::functions::candidate::delete_candidate_function(config, rtype) {
8487        Ok((modified_config, _record)) => match CString::new(modified_config) {
8488            Ok(c_str) => {
8489                clear_error();
8490                SzConfigTool_result {
8491                    response: c_str.into_raw(),
8492                    returnCode: 0,
8493                }
8494            }
8495            Err(e) => {
8496                set_error(format!("Failed to create C string: {e}"), -4);
8497                SzConfigTool_result {
8498                    response: std::ptr::null_mut(),
8499                    returnCode: -4,
8500                }
8501            }
8502        },
8503        Err(e) => {
8504            set_error(e.to_string(), -5);
8505            SzConfigTool_result {
8506                response: std::ptr::null_mut(),
8507                returnCode: -5,
8508            }
8509        }
8510    }
8511}
8512
8513/// Get a candidate function (placeholder - not implemented)
8514#[unsafe(no_mangle)]
8515pub extern "C" fn SzConfigTool_getCandidateFunction(
8516    config_json: *const c_char,
8517    rtype_code: *const c_char,
8518) -> SzConfigTool_result {
8519    let config = unsafe {
8520        if config_json.is_null() {
8521            set_error("config_json is null".to_string(), -1);
8522            return SzConfigTool_result {
8523                response: std::ptr::null_mut(),
8524                returnCode: -1,
8525            };
8526        }
8527        match CStr::from_ptr(config_json).to_str() {
8528            Ok(s) => s,
8529            Err(e) => {
8530                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8531                return SzConfigTool_result {
8532                    response: std::ptr::null_mut(),
8533                    returnCode: -2,
8534                };
8535            }
8536        }
8537    };
8538
8539    let rtype = unsafe {
8540        if rtype_code.is_null() {
8541            set_error("rtype_code is null".to_string(), -1);
8542            return SzConfigTool_result {
8543                response: std::ptr::null_mut(),
8544                returnCode: -1,
8545            };
8546        }
8547        match CStr::from_ptr(rtype_code).to_str() {
8548            Ok(s) => s,
8549            Err(e) => {
8550                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
8551                return SzConfigTool_result {
8552                    response: std::ptr::null_mut(),
8553                    returnCode: -2,
8554                };
8555            }
8556        }
8557    };
8558
8559    match crate::functions::candidate::get_candidate_function(config, rtype) {
8560        Ok(record) => match serde_json::to_string(&record) {
8561            Ok(json_str) => match CString::new(json_str) {
8562                Ok(c_str) => {
8563                    clear_error();
8564                    SzConfigTool_result {
8565                        response: c_str.into_raw(),
8566                        returnCode: 0,
8567                    }
8568                }
8569                Err(e) => {
8570                    set_error(format!("Failed to create C string: {e}"), -4);
8571                    SzConfigTool_result {
8572                        response: std::ptr::null_mut(),
8573                        returnCode: -4,
8574                    }
8575                }
8576            },
8577            Err(e) => {
8578                set_error(format!("Failed to serialize record: {e}"), -3);
8579                SzConfigTool_result {
8580                    response: std::ptr::null_mut(),
8581                    returnCode: -3,
8582                }
8583            }
8584        },
8585        Err(e) => {
8586            set_error(e.to_string(), -5);
8587            SzConfigTool_result {
8588                response: std::ptr::null_mut(),
8589                returnCode: -5,
8590            }
8591        }
8592    }
8593}
8594
8595/// List all candidate functions (placeholder - not implemented)
8596#[unsafe(no_mangle)]
8597pub extern "C" fn SzConfigTool_listCandidateFunctions(
8598    config_json: *const c_char,
8599) -> SzConfigTool_result {
8600    let config = unsafe {
8601        if config_json.is_null() {
8602            set_error("config_json is null".to_string(), -1);
8603            return SzConfigTool_result {
8604                response: std::ptr::null_mut(),
8605                returnCode: -1,
8606            };
8607        }
8608        match CStr::from_ptr(config_json).to_str() {
8609            Ok(s) => s,
8610            Err(e) => {
8611                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8612                return SzConfigTool_result {
8613                    response: std::ptr::null_mut(),
8614                    returnCode: -2,
8615                };
8616            }
8617        }
8618    };
8619
8620    match crate::functions::candidate::list_candidate_functions(config) {
8621        Ok(list) => match serde_json::to_string(&list) {
8622            Ok(json_str) => match CString::new(json_str) {
8623                Ok(c_str) => {
8624                    clear_error();
8625                    SzConfigTool_result {
8626                        response: c_str.into_raw(),
8627                        returnCode: 0,
8628                    }
8629                }
8630                Err(e) => {
8631                    set_error(format!("Failed to create C string: {e}"), -4);
8632                    SzConfigTool_result {
8633                        response: std::ptr::null_mut(),
8634                        returnCode: -4,
8635                    }
8636                }
8637            },
8638            Err(e) => {
8639                set_error(format!("Failed to serialize list: {e}"), -3);
8640                SzConfigTool_result {
8641                    response: std::ptr::null_mut(),
8642                    returnCode: -3,
8643                }
8644            }
8645        },
8646        Err(e) => {
8647            set_error(e.to_string(), -5);
8648            SzConfigTool_result {
8649                response: std::ptr::null_mut(),
8650                returnCode: -5,
8651            }
8652        }
8653    }
8654}
8655
8656/// Set (update) a candidate function (placeholder - not implemented)
8657#[unsafe(no_mangle)]
8658pub extern "C" fn SzConfigTool_setCandidateFunction(
8659    config_json: *const c_char,
8660    rtype_code: *const c_char,
8661    candidate_func: *const c_char, // NULL allowed
8662) -> SzConfigTool_result {
8663    let config = unsafe {
8664        if config_json.is_null() {
8665            set_error("config_json is null".to_string(), -1);
8666            return SzConfigTool_result {
8667                response: std::ptr::null_mut(),
8668                returnCode: -1,
8669            };
8670        }
8671        match CStr::from_ptr(config_json).to_str() {
8672            Ok(s) => s,
8673            Err(e) => {
8674                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8675                return SzConfigTool_result {
8676                    response: std::ptr::null_mut(),
8677                    returnCode: -2,
8678                };
8679            }
8680        }
8681    };
8682
8683    let rtype = unsafe {
8684        if rtype_code.is_null() {
8685            set_error("rtype_code is null".to_string(), -1);
8686            return SzConfigTool_result {
8687                response: std::ptr::null_mut(),
8688                returnCode: -1,
8689            };
8690        }
8691        match CStr::from_ptr(rtype_code).to_str() {
8692            Ok(s) => s,
8693            Err(e) => {
8694                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
8695                return SzConfigTool_result {
8696                    response: std::ptr::null_mut(),
8697                    returnCode: -2,
8698                };
8699            }
8700        }
8701    };
8702
8703    let candidate_opt = if candidate_func.is_null() {
8704        None
8705    } else {
8706        unsafe {
8707            match CStr::from_ptr(candidate_func).to_str() {
8708                Ok(s) => Some(s),
8709                Err(e) => {
8710                    set_error(format!("Invalid UTF-8 in candidate_func: {e}"), -2);
8711                    return SzConfigTool_result {
8712                        response: std::ptr::null_mut(),
8713                        returnCode: -2,
8714                    };
8715                }
8716            }
8717        }
8718    };
8719
8720    match crate::functions::candidate::set_candidate_function(config, rtype, candidate_opt) {
8721        Ok((modified_config, _record)) => match CString::new(modified_config) {
8722            Ok(c_str) => {
8723                clear_error();
8724                SzConfigTool_result {
8725                    response: c_str.into_raw(),
8726                    returnCode: 0,
8727                }
8728            }
8729            Err(e) => {
8730                set_error(format!("Failed to create C string: {e}"), -4);
8731                SzConfigTool_result {
8732                    response: std::ptr::null_mut(),
8733                    returnCode: -4,
8734                }
8735            }
8736        },
8737        Err(e) => {
8738            set_error(e.to_string(), -5);
8739            SzConfigTool_result {
8740                response: std::ptr::null_mut(),
8741                returnCode: -5,
8742            }
8743        }
8744    }
8745}
8746
8747// --- VALIDATION FUNCTIONS ---
8748
8749/// Add a validation function (placeholder - not implemented)
8750#[unsafe(no_mangle)]
8751pub extern "C" fn SzConfigTool_addValidationFunction(
8752    config_json: *const c_char,
8753    attr_code: *const c_char,
8754    validation_func: *const c_char,
8755) -> SzConfigTool_result {
8756    let config = unsafe {
8757        if config_json.is_null() {
8758            set_error("config_json is null".to_string(), -1);
8759            return SzConfigTool_result {
8760                response: std::ptr::null_mut(),
8761                returnCode: -1,
8762            };
8763        }
8764        match CStr::from_ptr(config_json).to_str() {
8765            Ok(s) => s,
8766            Err(e) => {
8767                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8768                return SzConfigTool_result {
8769                    response: std::ptr::null_mut(),
8770                    returnCode: -2,
8771                };
8772            }
8773        }
8774    };
8775
8776    let attr = unsafe {
8777        if attr_code.is_null() {
8778            set_error("attr_code is null".to_string(), -1);
8779            return SzConfigTool_result {
8780                response: std::ptr::null_mut(),
8781                returnCode: -1,
8782            };
8783        }
8784        match CStr::from_ptr(attr_code).to_str() {
8785            Ok(s) => s,
8786            Err(e) => {
8787                set_error(format!("Invalid UTF-8 in attr_code: {e}"), -2);
8788                return SzConfigTool_result {
8789                    response: std::ptr::null_mut(),
8790                    returnCode: -2,
8791                };
8792            }
8793        }
8794    };
8795
8796    let validation = unsafe {
8797        if validation_func.is_null() {
8798            set_error("validation_func is null".to_string(), -1);
8799            return SzConfigTool_result {
8800                response: std::ptr::null_mut(),
8801                returnCode: -1,
8802            };
8803        }
8804        match CStr::from_ptr(validation_func).to_str() {
8805            Ok(s) => s,
8806            Err(e) => {
8807                set_error(format!("Invalid UTF-8 in validation_func: {e}"), -2);
8808                return SzConfigTool_result {
8809                    response: std::ptr::null_mut(),
8810                    returnCode: -2,
8811                };
8812            }
8813        }
8814    };
8815
8816    match crate::functions::validation::add_validation_function(config, attr, validation) {
8817        Ok((modified_config, _record)) => match CString::new(modified_config) {
8818            Ok(c_str) => {
8819                clear_error();
8820                SzConfigTool_result {
8821                    response: c_str.into_raw(),
8822                    returnCode: 0,
8823                }
8824            }
8825            Err(e) => {
8826                set_error(format!("Failed to create C string: {e}"), -4);
8827                SzConfigTool_result {
8828                    response: std::ptr::null_mut(),
8829                    returnCode: -4,
8830                }
8831            }
8832        },
8833        Err(e) => {
8834            set_error(e.to_string(), -5);
8835            SzConfigTool_result {
8836                response: std::ptr::null_mut(),
8837                returnCode: -5,
8838            }
8839        }
8840    }
8841}
8842
8843/// Delete a validation function (placeholder - not implemented)
8844#[unsafe(no_mangle)]
8845pub extern "C" fn SzConfigTool_deleteValidationFunction(
8846    config_json: *const c_char,
8847    attr_code: *const c_char,
8848) -> SzConfigTool_result {
8849    let config = unsafe {
8850        if config_json.is_null() {
8851            set_error("config_json is null".to_string(), -1);
8852            return SzConfigTool_result {
8853                response: std::ptr::null_mut(),
8854                returnCode: -1,
8855            };
8856        }
8857        match CStr::from_ptr(config_json).to_str() {
8858            Ok(s) => s,
8859            Err(e) => {
8860                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8861                return SzConfigTool_result {
8862                    response: std::ptr::null_mut(),
8863                    returnCode: -2,
8864                };
8865            }
8866        }
8867    };
8868
8869    let attr = unsafe {
8870        if attr_code.is_null() {
8871            set_error("attr_code is null".to_string(), -1);
8872            return SzConfigTool_result {
8873                response: std::ptr::null_mut(),
8874                returnCode: -1,
8875            };
8876        }
8877        match CStr::from_ptr(attr_code).to_str() {
8878            Ok(s) => s,
8879            Err(e) => {
8880                set_error(format!("Invalid UTF-8 in attr_code: {e}"), -2);
8881                return SzConfigTool_result {
8882                    response: std::ptr::null_mut(),
8883                    returnCode: -2,
8884                };
8885            }
8886        }
8887    };
8888
8889    match crate::functions::validation::delete_validation_function(config, attr) {
8890        Ok((modified_config, _record)) => match CString::new(modified_config) {
8891            Ok(c_str) => {
8892                clear_error();
8893                SzConfigTool_result {
8894                    response: c_str.into_raw(),
8895                    returnCode: 0,
8896                }
8897            }
8898            Err(e) => {
8899                set_error(format!("Failed to create C string: {e}"), -4);
8900                SzConfigTool_result {
8901                    response: std::ptr::null_mut(),
8902                    returnCode: -4,
8903                }
8904            }
8905        },
8906        Err(e) => {
8907            set_error(e.to_string(), -5);
8908            SzConfigTool_result {
8909                response: std::ptr::null_mut(),
8910                returnCode: -5,
8911            }
8912        }
8913    }
8914}
8915
8916/// Get a validation function (placeholder - not implemented)
8917#[unsafe(no_mangle)]
8918pub extern "C" fn SzConfigTool_getValidationFunction(
8919    config_json: *const c_char,
8920    attr_code: *const c_char,
8921) -> SzConfigTool_result {
8922    let config = unsafe {
8923        if config_json.is_null() {
8924            set_error("config_json is null".to_string(), -1);
8925            return SzConfigTool_result {
8926                response: std::ptr::null_mut(),
8927                returnCode: -1,
8928            };
8929        }
8930        match CStr::from_ptr(config_json).to_str() {
8931            Ok(s) => s,
8932            Err(e) => {
8933                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
8934                return SzConfigTool_result {
8935                    response: std::ptr::null_mut(),
8936                    returnCode: -2,
8937                };
8938            }
8939        }
8940    };
8941
8942    let attr = unsafe {
8943        if attr_code.is_null() {
8944            set_error("attr_code is null".to_string(), -1);
8945            return SzConfigTool_result {
8946                response: std::ptr::null_mut(),
8947                returnCode: -1,
8948            };
8949        }
8950        match CStr::from_ptr(attr_code).to_str() {
8951            Ok(s) => s,
8952            Err(e) => {
8953                set_error(format!("Invalid UTF-8 in attr_code: {e}"), -2);
8954                return SzConfigTool_result {
8955                    response: std::ptr::null_mut(),
8956                    returnCode: -2,
8957                };
8958            }
8959        }
8960    };
8961
8962    match crate::functions::validation::get_validation_function(config, attr) {
8963        Ok(record) => match serde_json::to_string(&record) {
8964            Ok(json_str) => match CString::new(json_str) {
8965                Ok(c_str) => {
8966                    clear_error();
8967                    SzConfigTool_result {
8968                        response: c_str.into_raw(),
8969                        returnCode: 0,
8970                    }
8971                }
8972                Err(e) => {
8973                    set_error(format!("Failed to create C string: {e}"), -4);
8974                    SzConfigTool_result {
8975                        response: std::ptr::null_mut(),
8976                        returnCode: -4,
8977                    }
8978                }
8979            },
8980            Err(e) => {
8981                set_error(format!("Failed to serialize record: {e}"), -3);
8982                SzConfigTool_result {
8983                    response: std::ptr::null_mut(),
8984                    returnCode: -3,
8985                }
8986            }
8987        },
8988        Err(e) => {
8989            set_error(e.to_string(), -5);
8990            SzConfigTool_result {
8991                response: std::ptr::null_mut(),
8992                returnCode: -5,
8993            }
8994        }
8995    }
8996}
8997
8998/// List all validation functions (placeholder - not implemented)
8999#[unsafe(no_mangle)]
9000pub extern "C" fn SzConfigTool_listValidationFunctions(
9001    config_json: *const c_char,
9002) -> SzConfigTool_result {
9003    let config = unsafe {
9004        if config_json.is_null() {
9005            set_error("config_json is null".to_string(), -1);
9006            return SzConfigTool_result {
9007                response: std::ptr::null_mut(),
9008                returnCode: -1,
9009            };
9010        }
9011        match CStr::from_ptr(config_json).to_str() {
9012            Ok(s) => s,
9013            Err(e) => {
9014                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
9015                return SzConfigTool_result {
9016                    response: std::ptr::null_mut(),
9017                    returnCode: -2,
9018                };
9019            }
9020        }
9021    };
9022
9023    match crate::functions::validation::list_validation_functions(config) {
9024        Ok(list) => match serde_json::to_string(&list) {
9025            Ok(json_str) => match CString::new(json_str) {
9026                Ok(c_str) => {
9027                    clear_error();
9028                    SzConfigTool_result {
9029                        response: c_str.into_raw(),
9030                        returnCode: 0,
9031                    }
9032                }
9033                Err(e) => {
9034                    set_error(format!("Failed to create C string: {e}"), -4);
9035                    SzConfigTool_result {
9036                        response: std::ptr::null_mut(),
9037                        returnCode: -4,
9038                    }
9039                }
9040            },
9041            Err(e) => {
9042                set_error(format!("Failed to serialize list: {e}"), -3);
9043                SzConfigTool_result {
9044                    response: std::ptr::null_mut(),
9045                    returnCode: -3,
9046                }
9047            }
9048        },
9049        Err(e) => {
9050            set_error(e.to_string(), -5);
9051            SzConfigTool_result {
9052                response: std::ptr::null_mut(),
9053                returnCode: -5,
9054            }
9055        }
9056    }
9057}
9058
9059/// Set (update) a validation function (placeholder - not implemented)
9060#[unsafe(no_mangle)]
9061pub extern "C" fn SzConfigTool_setValidationFunction(
9062    config_json: *const c_char,
9063    attr_code: *const c_char,
9064    validation_func: *const c_char, // NULL allowed
9065) -> SzConfigTool_result {
9066    let config = unsafe {
9067        if config_json.is_null() {
9068            set_error("config_json is null".to_string(), -1);
9069            return SzConfigTool_result {
9070                response: std::ptr::null_mut(),
9071                returnCode: -1,
9072            };
9073        }
9074        match CStr::from_ptr(config_json).to_str() {
9075            Ok(s) => s,
9076            Err(e) => {
9077                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
9078                return SzConfigTool_result {
9079                    response: std::ptr::null_mut(),
9080                    returnCode: -2,
9081                };
9082            }
9083        }
9084    };
9085
9086    let attr = unsafe {
9087        if attr_code.is_null() {
9088            set_error("attr_code is null".to_string(), -1);
9089            return SzConfigTool_result {
9090                response: std::ptr::null_mut(),
9091                returnCode: -1,
9092            };
9093        }
9094        match CStr::from_ptr(attr_code).to_str() {
9095            Ok(s) => s,
9096            Err(e) => {
9097                set_error(format!("Invalid UTF-8 in attr_code: {e}"), -2);
9098                return SzConfigTool_result {
9099                    response: std::ptr::null_mut(),
9100                    returnCode: -2,
9101                };
9102            }
9103        }
9104    };
9105
9106    let validation_opt = if validation_func.is_null() {
9107        None
9108    } else {
9109        unsafe {
9110            match CStr::from_ptr(validation_func).to_str() {
9111                Ok(s) => Some(s),
9112                Err(e) => {
9113                    set_error(format!("Invalid UTF-8 in validation_func: {e}"), -2);
9114                    return SzConfigTool_result {
9115                        response: std::ptr::null_mut(),
9116                        returnCode: -2,
9117                    };
9118                }
9119            }
9120        }
9121    };
9122
9123    match crate::functions::validation::set_validation_function(config, attr, validation_opt) {
9124        Ok((modified_config, _record)) => match CString::new(modified_config) {
9125            Ok(c_str) => {
9126                clear_error();
9127                SzConfigTool_result {
9128                    response: c_str.into_raw(),
9129                    returnCode: 0,
9130                }
9131            }
9132            Err(e) => {
9133                set_error(format!("Failed to create C string: {e}"), -4);
9134                SzConfigTool_result {
9135                    response: std::ptr::null_mut(),
9136                    returnCode: -4,
9137                }
9138            }
9139        },
9140        Err(e) => {
9141            set_error(e.to_string(), -5);
9142            SzConfigTool_result {
9143                response: std::ptr::null_mut(),
9144                returnCode: -5,
9145            }
9146        }
9147    }
9148}
9149
9150// ============================================================================
9151// BATCH 14: SCORING FUNCTION OPERATIONS (Placeholders) - FINAL BATCH!
9152// ============================================================================
9153
9154/// Add a scoring function (placeholder - not implemented)
9155#[unsafe(no_mangle)]
9156pub extern "C" fn SzConfigTool_addScoringFunction(
9157    config_json: *const c_char,
9158    rtype_code: *const c_char,
9159    scoring_func: *const c_char,
9160) -> SzConfigTool_result {
9161    let config = unsafe {
9162        if config_json.is_null() {
9163            set_error("config_json is null".to_string(), -1);
9164            return SzConfigTool_result {
9165                response: std::ptr::null_mut(),
9166                returnCode: -1,
9167            };
9168        }
9169        match CStr::from_ptr(config_json).to_str() {
9170            Ok(s) => s,
9171            Err(e) => {
9172                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
9173                return SzConfigTool_result {
9174                    response: std::ptr::null_mut(),
9175                    returnCode: -2,
9176                };
9177            }
9178        }
9179    };
9180
9181    let rtype = unsafe {
9182        if rtype_code.is_null() {
9183            set_error("rtype_code is null".to_string(), -1);
9184            return SzConfigTool_result {
9185                response: std::ptr::null_mut(),
9186                returnCode: -1,
9187            };
9188        }
9189        match CStr::from_ptr(rtype_code).to_str() {
9190            Ok(s) => s,
9191            Err(e) => {
9192                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
9193                return SzConfigTool_result {
9194                    response: std::ptr::null_mut(),
9195                    returnCode: -2,
9196                };
9197            }
9198        }
9199    };
9200
9201    let scoring = unsafe {
9202        if scoring_func.is_null() {
9203            set_error("scoring_func is null".to_string(), -1);
9204            return SzConfigTool_result {
9205                response: std::ptr::null_mut(),
9206                returnCode: -1,
9207            };
9208        }
9209        match CStr::from_ptr(scoring_func).to_str() {
9210            Ok(s) => s,
9211            Err(e) => {
9212                set_error(format!("Invalid UTF-8 in scoring_func: {e}"), -2);
9213                return SzConfigTool_result {
9214                    response: std::ptr::null_mut(),
9215                    returnCode: -2,
9216                };
9217            }
9218        }
9219    };
9220
9221    match crate::functions::scoring::add_scoring_function(config, rtype, scoring) {
9222        Ok((modified_config, _record)) => match CString::new(modified_config) {
9223            Ok(c_str) => {
9224                clear_error();
9225                SzConfigTool_result {
9226                    response: c_str.into_raw(),
9227                    returnCode: 0,
9228                }
9229            }
9230            Err(e) => {
9231                set_error(format!("Failed to create C string: {e}"), -4);
9232                SzConfigTool_result {
9233                    response: std::ptr::null_mut(),
9234                    returnCode: -4,
9235                }
9236            }
9237        },
9238        Err(e) => {
9239            set_error(e.to_string(), -5);
9240            SzConfigTool_result {
9241                response: std::ptr::null_mut(),
9242                returnCode: -5,
9243            }
9244        }
9245    }
9246}
9247
9248/// Delete a scoring function (placeholder - not implemented)
9249#[unsafe(no_mangle)]
9250pub extern "C" fn SzConfigTool_deleteScoringFunction(
9251    config_json: *const c_char,
9252    rtype_code: *const c_char,
9253) -> SzConfigTool_result {
9254    let config = unsafe {
9255        if config_json.is_null() {
9256            set_error("config_json is null".to_string(), -1);
9257            return SzConfigTool_result {
9258                response: std::ptr::null_mut(),
9259                returnCode: -1,
9260            };
9261        }
9262        match CStr::from_ptr(config_json).to_str() {
9263            Ok(s) => s,
9264            Err(e) => {
9265                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
9266                return SzConfigTool_result {
9267                    response: std::ptr::null_mut(),
9268                    returnCode: -2,
9269                };
9270            }
9271        }
9272    };
9273
9274    let rtype = unsafe {
9275        if rtype_code.is_null() {
9276            set_error("rtype_code is null".to_string(), -1);
9277            return SzConfigTool_result {
9278                response: std::ptr::null_mut(),
9279                returnCode: -1,
9280            };
9281        }
9282        match CStr::from_ptr(rtype_code).to_str() {
9283            Ok(s) => s,
9284            Err(e) => {
9285                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
9286                return SzConfigTool_result {
9287                    response: std::ptr::null_mut(),
9288                    returnCode: -2,
9289                };
9290            }
9291        }
9292    };
9293
9294    match crate::functions::scoring::delete_scoring_function(config, rtype) {
9295        Ok((modified_config, _record)) => match CString::new(modified_config) {
9296            Ok(c_str) => {
9297                clear_error();
9298                SzConfigTool_result {
9299                    response: c_str.into_raw(),
9300                    returnCode: 0,
9301                }
9302            }
9303            Err(e) => {
9304                set_error(format!("Failed to create C string: {e}"), -4);
9305                SzConfigTool_result {
9306                    response: std::ptr::null_mut(),
9307                    returnCode: -4,
9308                }
9309            }
9310        },
9311        Err(e) => {
9312            set_error(e.to_string(), -5);
9313            SzConfigTool_result {
9314                response: std::ptr::null_mut(),
9315                returnCode: -5,
9316            }
9317        }
9318    }
9319}
9320
9321/// Get a scoring function (placeholder - not implemented)
9322#[unsafe(no_mangle)]
9323pub extern "C" fn SzConfigTool_getScoringFunction(
9324    config_json: *const c_char,
9325    rtype_code: *const c_char,
9326) -> SzConfigTool_result {
9327    let config = unsafe {
9328        if config_json.is_null() {
9329            set_error("config_json is null".to_string(), -1);
9330            return SzConfigTool_result {
9331                response: std::ptr::null_mut(),
9332                returnCode: -1,
9333            };
9334        }
9335        match CStr::from_ptr(config_json).to_str() {
9336            Ok(s) => s,
9337            Err(e) => {
9338                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
9339                return SzConfigTool_result {
9340                    response: std::ptr::null_mut(),
9341                    returnCode: -2,
9342                };
9343            }
9344        }
9345    };
9346
9347    let rtype = unsafe {
9348        if rtype_code.is_null() {
9349            set_error("rtype_code is null".to_string(), -1);
9350            return SzConfigTool_result {
9351                response: std::ptr::null_mut(),
9352                returnCode: -1,
9353            };
9354        }
9355        match CStr::from_ptr(rtype_code).to_str() {
9356            Ok(s) => s,
9357            Err(e) => {
9358                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
9359                return SzConfigTool_result {
9360                    response: std::ptr::null_mut(),
9361                    returnCode: -2,
9362                };
9363            }
9364        }
9365    };
9366
9367    match crate::functions::scoring::get_scoring_function(config, rtype) {
9368        Ok(record) => match serde_json::to_string(&record) {
9369            Ok(json_str) => match CString::new(json_str) {
9370                Ok(c_str) => {
9371                    clear_error();
9372                    SzConfigTool_result {
9373                        response: c_str.into_raw(),
9374                        returnCode: 0,
9375                    }
9376                }
9377                Err(e) => {
9378                    set_error(format!("Failed to create C string: {e}"), -4);
9379                    SzConfigTool_result {
9380                        response: std::ptr::null_mut(),
9381                        returnCode: -4,
9382                    }
9383                }
9384            },
9385            Err(e) => {
9386                set_error(format!("Failed to serialize record: {e}"), -3);
9387                SzConfigTool_result {
9388                    response: std::ptr::null_mut(),
9389                    returnCode: -3,
9390                }
9391            }
9392        },
9393        Err(e) => {
9394            set_error(e.to_string(), -5);
9395            SzConfigTool_result {
9396                response: std::ptr::null_mut(),
9397                returnCode: -5,
9398            }
9399        }
9400    }
9401}
9402
9403/// List all scoring functions (placeholder - not implemented)
9404#[unsafe(no_mangle)]
9405pub extern "C" fn SzConfigTool_listScoringFunctions(
9406    config_json: *const c_char,
9407) -> SzConfigTool_result {
9408    let config = unsafe {
9409        if config_json.is_null() {
9410            set_error("config_json is null".to_string(), -1);
9411            return SzConfigTool_result {
9412                response: std::ptr::null_mut(),
9413                returnCode: -1,
9414            };
9415        }
9416        match CStr::from_ptr(config_json).to_str() {
9417            Ok(s) => s,
9418            Err(e) => {
9419                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
9420                return SzConfigTool_result {
9421                    response: std::ptr::null_mut(),
9422                    returnCode: -2,
9423                };
9424            }
9425        }
9426    };
9427
9428    match crate::functions::scoring::list_scoring_functions(config) {
9429        Ok(list) => match serde_json::to_string(&list) {
9430            Ok(json_str) => match CString::new(json_str) {
9431                Ok(c_str) => {
9432                    clear_error();
9433                    SzConfigTool_result {
9434                        response: c_str.into_raw(),
9435                        returnCode: 0,
9436                    }
9437                }
9438                Err(e) => {
9439                    set_error(format!("Failed to create C string: {e}"), -4);
9440                    SzConfigTool_result {
9441                        response: std::ptr::null_mut(),
9442                        returnCode: -4,
9443                    }
9444                }
9445            },
9446            Err(e) => {
9447                set_error(format!("Failed to serialize list: {e}"), -3);
9448                SzConfigTool_result {
9449                    response: std::ptr::null_mut(),
9450                    returnCode: -3,
9451                }
9452            }
9453        },
9454        Err(e) => {
9455            set_error(e.to_string(), -5);
9456            SzConfigTool_result {
9457                response: std::ptr::null_mut(),
9458                returnCode: -5,
9459            }
9460        }
9461    }
9462}
9463
9464/// Set (update) a scoring function (placeholder - not implemented)
9465#[unsafe(no_mangle)]
9466pub extern "C" fn SzConfigTool_setScoringFunction(
9467    config_json: *const c_char,
9468    rtype_code: *const c_char,
9469    scoring_func: *const c_char, // NULL allowed
9470) -> SzConfigTool_result {
9471    let config = unsafe {
9472        if config_json.is_null() {
9473            set_error("config_json is null".to_string(), -1);
9474            return SzConfigTool_result {
9475                response: std::ptr::null_mut(),
9476                returnCode: -1,
9477            };
9478        }
9479        match CStr::from_ptr(config_json).to_str() {
9480            Ok(s) => s,
9481            Err(e) => {
9482                set_error(format!("Invalid UTF-8 in config_json: {e}"), -2);
9483                return SzConfigTool_result {
9484                    response: std::ptr::null_mut(),
9485                    returnCode: -2,
9486                };
9487            }
9488        }
9489    };
9490
9491    let rtype = unsafe {
9492        if rtype_code.is_null() {
9493            set_error("rtype_code is null".to_string(), -1);
9494            return SzConfigTool_result {
9495                response: std::ptr::null_mut(),
9496                returnCode: -1,
9497            };
9498        }
9499        match CStr::from_ptr(rtype_code).to_str() {
9500            Ok(s) => s,
9501            Err(e) => {
9502                set_error(format!("Invalid UTF-8 in rtype_code: {e}"), -2);
9503                return SzConfigTool_result {
9504                    response: std::ptr::null_mut(),
9505                    returnCode: -2,
9506                };
9507            }
9508        }
9509    };
9510
9511    let scoring_opt = if scoring_func.is_null() {
9512        None
9513    } else {
9514        unsafe {
9515            match CStr::from_ptr(scoring_func).to_str() {
9516                Ok(s) => Some(s),
9517                Err(e) => {
9518                    set_error(format!("Invalid UTF-8 in scoring_func: {e}"), -2);
9519                    return SzConfigTool_result {
9520                        response: std::ptr::null_mut(),
9521                        returnCode: -2,
9522                    };
9523                }
9524            }
9525        }
9526    };
9527
9528    match crate::functions::scoring::set_scoring_function(config, rtype, scoring_opt) {
9529        Ok((modified_config, _record)) => match CString::new(modified_config) {
9530            Ok(c_str) => {
9531                clear_error();
9532                SzConfigTool_result {
9533                    response: c_str.into_raw(),
9534                    returnCode: 0,
9535                }
9536            }
9537            Err(e) => {
9538                set_error(format!("Failed to create C string: {e}"), -4);
9539                SzConfigTool_result {
9540                    response: std::ptr::null_mut(),
9541                    returnCode: -4,
9542                }
9543            }
9544        },
9545        Err(e) => {
9546            set_error(e.to_string(), -5);
9547            SzConfigTool_result {
9548                response: std::ptr::null_mut(),
9549                returnCode: -5,
9550            }
9551        }
9552    }
9553}