use std::collections::HashSet;
use crate::core::ir::TypeDef;
use crate::e2e::codegen::call_ir::{CallIr, resolve_declared_result_type};
use crate::e2e::config::CallConfig;
pub(super) fn json_struct_type_names(type_defs: &[TypeDef]) -> HashSet<String> {
crate::backends::zig::gen_bindings::zig_struct_names(type_defs)
}
pub(super) fn ir_says_json_struct(call: &CallConfig, lang: &str, ir: CallIr<'_>, type_defs: &[TypeDef]) -> bool {
resolve_declared_result_type(call, lang, ir).is_some_and(|name| json_struct_type_names(type_defs).contains(&name))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::ir::{FunctionDef, TypeRef};
fn json_type(name: &str) -> TypeDef {
TypeDef {
name: name.to_string(),
has_serde: true,
..TypeDef::default()
}
}
fn opaque_handle_type(name: &str) -> TypeDef {
TypeDef {
name: name.to_string(),
is_opaque: true,
..TypeDef::default()
}
}
#[test]
fn a_serde_struct_type_is_a_json_struct_name() {
let type_defs = vec![json_type("Response")];
assert_eq!(
json_struct_type_names(&type_defs),
["Response".to_string()].into_iter().collect()
);
}
#[test]
fn an_opaque_handle_type_is_not_a_json_struct_name() {
let type_defs = vec![opaque_handle_type("Tree")];
assert!(json_struct_type_names(&type_defs).is_empty());
}
#[test]
fn a_non_serde_plain_struct_type_is_not_a_json_struct_name() {
let type_defs = vec![TypeDef {
name: "Config".to_string(),
has_serde: false,
is_opaque: false,
..TypeDef::default()
}];
assert!(json_struct_type_names(&type_defs).is_empty());
}
#[test]
fn a_free_function_returning_a_serde_struct_is_detected_from_the_ir() {
let type_defs = vec![json_type("Response")];
let functions = vec![FunctionDef {
name: "process".to_string(),
return_type: TypeRef::Named("Response".to_string()),
..FunctionDef::default()
}];
let ir = CallIr {
functions: &functions,
type_defs: &type_defs,
};
let call = CallConfig {
function: "process".to_string(),
..CallConfig::default()
};
assert!(ir_says_json_struct(&call, "zig", ir, &type_defs));
}
#[test]
fn a_free_function_returning_an_opaque_handle_is_not_detected_as_json_struct() {
let type_defs = vec![opaque_handle_type("Tree")];
let functions = vec![FunctionDef {
name: "parse".to_string(),
return_type: TypeRef::Named("Tree".to_string()),
..FunctionDef::default()
}];
let ir = CallIr {
functions: &functions,
type_defs: &type_defs,
};
let call = CallConfig {
function: "parse".to_string(),
..CallConfig::default()
};
assert!(!ir_says_json_struct(&call, "zig", ir, &type_defs));
}
#[test]
fn an_absent_ir_is_not_detected_as_json_struct() {
let type_defs = vec![json_type("Response")];
let call = CallConfig {
function: "process".to_string(),
..CallConfig::default()
};
assert!(!ir_says_json_struct(&call, "zig", CallIr::default(), &type_defs));
}
}