use decy_core::transpile;
fn has_reference_params(code: &str, param_names: &[&str]) -> bool {
for name in param_names {
let has_param = code.contains(&format!("{}:", name));
let has_ref = code.contains("&i32")
|| code.contains("&mut i32")
|| code.contains("&'a i32")
|| code.contains("&'a mut i32");
if has_param && has_ref {
return true;
}
}
false
}
#[test]
fn test_two_output_params_become_tuple() {
let c_code = r#"
void get_dims(int *width, int *height) {
*width = 1920;
*height = 1080;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
let has_refs = has_reference_params(&rust_code, &["width", "height"]);
let has_tuple = rust_code.contains("(i32, i32)");
assert!(
has_refs || has_tuple,
"DECY-180: Should have reference params or tuple return!\nGot: {}",
rust_code
);
}
#[test]
fn test_three_output_params_become_tuple() {
let c_code = r#"
void get_color(int *r, int *g, int *b) {
*r = 255;
*g = 128;
*b = 64;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
let has_refs = has_reference_params(&rust_code, &["r", "g", "b"]);
let has_tuple = rust_code.contains("(i32, i32, i32)");
assert!(
has_refs || has_tuple,
"DECY-180: Should have reference params or 3-tuple!\nGot: {}",
rust_code
);
}
#[test]
fn test_mixed_input_output_params() {
let c_code = r#"
void scale(int factor, int *x, int *y) {
*x = factor * 10;
*y = factor * 20;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("factor"),
"Input param 'factor' should remain!\nGot: {}",
rust_code
);
let has_refs = has_reference_params(&rust_code, &["x", "y"]);
let has_tuple = rust_code.contains("(i32, i32)");
assert!(
has_refs || has_tuple,
"DECY-180: Output params should be refs or tuple return!\nGot: {}",
rust_code
);
}
#[test]
fn test_single_output_with_inputs_still_works() {
let c_code = r#"
void get_sum(int a, int b, int *result) {
*result = a + b;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
let has_ref = has_reference_params(&rust_code, &["result"]);
let has_return = rust_code.contains("-> i32") && !rust_code.contains("(i32)");
assert!(
has_ref || has_return,
"DECY-180: Should have reference param or direct return!\nGot: {}",
rust_code
);
}
#[test]
fn test_fallible_with_multiple_outputs() {
let c_code = r#"
int get_point(int *x, int *y) {
if (x == 0 || y == 0) return -1;
*x = 10;
*y = 20;
return 0;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
let has_refs = has_reference_params(&rust_code, &["x", "y"]);
let has_result_tuple = rust_code.contains("Result<(i32, i32)");
assert!(
has_refs || has_result_tuple,
"DECY-180: Should have reference params or Result<tuple>!\nGot: {}",
rust_code
);
}
#[test]
fn test_input_output_not_in_tuple() {
let c_code = r#"
void process(int *counter, int *result) {
*counter = *counter + 1;
*result = *counter * 10;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
let has_refs = has_reference_params(&rust_code, &["counter", "result"]);
assert!(
has_refs || rust_code.contains("&mut"),
"DECY-180: Params should be transformed to references!\nGot: {}",
rust_code
);
}
#[test]
fn test_same_types_in_tuple() {
let c_code = r#"
void get_info(int *count, int *total) {
*count = 5;
*total = 100;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
let has_refs = has_reference_params(&rust_code, &["count", "total"]);
let has_tuple = rust_code.contains("(i32, i32)") || rust_code.contains("(i32,i32)");
assert!(
has_refs || has_tuple,
"DECY-180: Should have reference params or tuple!\nGot: {}",
rust_code
);
}
#[test]
fn test_output_name_triggers_tuple() {
let c_code = r#"
void get_results(int *result1, int *result2) {
*result1 = 100;
*result2 = 200;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
let has_refs = has_reference_params(&rust_code, &["result1", "result2"]);
let has_tuple = rust_code.contains("(i32, i32)");
assert!(
has_refs || has_tuple,
"DECY-180: Should have reference params or tuple!\nGot: {}",
rust_code
);
}