use alef_backend_zig::ZigBackend;
use alef_core::backend::Backend;
use alef_core::config::{ResolvedCrateConfig, new_config::NewAlefConfig};
use alef_core::ir::{
ApiSurface, CoreWrapper, EnumDef, EnumVariant, ErrorDef, ErrorVariant, FieldDef, FunctionDef, ParamDef,
PrimitiveType, TypeDef, TypeRef,
};
fn make_field(name: &str, ty: TypeRef, optional: bool) -> FieldDef {
FieldDef {
name: name.to_string(),
ty,
optional,
default: None,
doc: String::new(),
sanitized: false,
is_boxed: false,
type_rust_path: None,
cfg: None,
typed_default: None,
core_wrapper: CoreWrapper::None,
vec_inner_core_wrapper: CoreWrapper::None,
newtype_wrapper: None,
serde_rename: None,
}
}
fn make_param(name: &str, ty: TypeRef) -> ParamDef {
ParamDef {
name: name.to_string(),
ty,
optional: false,
default: None,
sanitized: false,
typed_default: None,
is_ref: false,
is_mut: false,
newtype_wrapper: None,
original_type: None,
}
}
fn make_basic_api() -> ApiSurface {
ApiSurface {
crate_name: "demo".into(),
version: "0.1.0".into(),
types: vec![TypeDef {
name: "Config".to_string(),
rust_path: "demo::Config".to_string(),
original_rust_path: String::new(),
fields: vec![
make_field("value", TypeRef::Primitive(PrimitiveType::I32), false),
make_field("label", TypeRef::String, false),
make_field("tag", TypeRef::Optional(Box::new(TypeRef::String)), true),
],
methods: vec![],
is_opaque: false,
is_clone: true,
is_copy: false,
doc: "A demo configuration struct.".to_string(),
cfg: None,
is_trait: false,
has_default: false,
has_stripped_cfg_fields: false,
is_return_type: false,
serde_rename_all: None,
has_serde: false,
super_traits: vec![],
}],
functions: vec![FunctionDef {
name: "process".into(),
rust_path: "demo::process".into(),
original_rust_path: String::new(),
params: vec![
make_param("input", TypeRef::String),
make_param("count", TypeRef::Primitive(PrimitiveType::U32)),
],
return_type: TypeRef::String,
is_async: false,
error_type: Some("DemoError".to_string()),
doc: "Process input and return a result.".to_string(),
cfg: None,
sanitized: false,
return_sanitized: false,
returns_ref: false,
returns_cow: false,
return_newtype_wrapper: None,
}],
enums: vec![EnumDef {
name: "Status".to_string(),
rust_path: "demo::Status".to_string(),
original_rust_path: String::new(),
variants: vec![
EnumVariant {
name: "Active".to_string(),
fields: vec![],
is_tuple: false,
doc: "Active state.".to_string(),
is_default: false,
serde_rename: None,
},
EnumVariant {
name: "Inactive".to_string(),
fields: vec![],
is_tuple: false,
doc: "Inactive state.".to_string(),
is_default: false,
serde_rename: None,
},
],
doc: "Processing status.".to_string(),
cfg: None,
is_copy: false,
has_serde: false,
serde_tag: None,
serde_untagged: false,
serde_rename_all: None,
}],
errors: vec![ErrorDef {
name: "DemoError".to_string(),
rust_path: "demo::DemoError".to_string(),
original_rust_path: String::new(),
variants: vec![
ErrorVariant {
name: "InvalidInput".to_string(),
message_template: Some("invalid input provided".to_string()),
fields: vec![],
has_source: false,
has_from: false,
is_unit: true,
doc: "Input validation failed.".to_string(),
},
ErrorVariant {
name: "ProcessingFailed".to_string(),
message_template: Some("processing failed".to_string()),
fields: vec![],
has_source: false,
has_from: false,
is_unit: true,
doc: "Processing encountered an error.".to_string(),
},
],
doc: "Errors emitted by demo operations.".to_string(),
}],
}
}
fn make_basic_config() -> ResolvedCrateConfig {
let toml = r#"
[workspace]
languages = ["zig"]
[[crates]]
name = "demo"
sources = ["src/lib.rs"]
"#;
let cfg: NewAlefConfig = toml::from_str(toml).expect("test config must parse");
cfg.resolve().expect("test config must resolve").remove(0)
}
#[test]
fn snapshot_basic_struct_function_enum_error() {
let api = make_basic_api();
let config = make_basic_config();
let files = ZigBackend.generate_bindings(&api, &config).unwrap();
for file in &files {
insta::assert_snapshot!(
format!("snapshot_basic__{}", file.path.display().to_string().replace('/', "__")),
&file.content
);
}
}