use std::collections::HashSet;
use crate::core::ir::{DefaultValue, FieldDef, TypeDef, TypeRef};
use super::shared::{constructor_fields, default_value_for_field_in_type, use_unwrap_or_default};
fn defers_to_field_type_default(field: &FieldDef) -> bool {
if matches!(&field.ty, TypeRef::Named(_)) {
return true;
}
matches!(&field.typed_default, Some(DefaultValue::EnumVariant(_)))
&& matches!(&field.ty, TypeRef::String | TypeRef::Char)
}
pub fn gen_rustler_kwargs_constructor_with_exclude(
typ: &TypeDef,
_type_mapper: &dyn Fn(&TypeRef) -> String,
exclude_fields: &HashSet<String>,
) -> String {
let fields: Vec<_> = constructor_fields(typ)
.filter(|f| !exclude_fields.contains(&f.name))
.map(|field| {
let assignment = if field.optional {
format!("opts.get(\"{}\").and_then(|t| t.decode().ok()),", field.name)
} else if use_unwrap_or_default(field) {
format!(
"opts.get(\"{}\").and_then(|t| t.decode().ok()).unwrap_or_default(),",
field.name
)
} else {
if defers_to_field_type_default(field) {
format!(
"opts.get(\"{}\").and_then(|t| t.decode().ok()).unwrap_or_default(),",
field.name
)
} else {
format!(
"opts.get(\"{}\").and_then(|t| t.decode().ok()).unwrap_or({}),",
field.name,
default_value_for_field_in_type(field, "rust", typ)
)
}
};
minijinja::context! {
name => crate::codegen::naming::internal_rust_identifier(&field.name),
assignment => assignment,
}
})
.collect();
crate::codegen::template_env::render(
"config_gen/rustler_kwargs_constructor.jinja",
minijinja::context! {
fields => fields,
},
)
}
pub fn gen_rustler_kwargs_constructor(typ: &TypeDef, _type_mapper: &dyn Fn(&TypeRef) -> String) -> String {
let fields: Vec<_> = constructor_fields(typ)
.map(|field| {
let assignment = if field.optional {
format!("opts.get(\"{}\").and_then(|t| t.decode().ok()),", field.name)
} else if use_unwrap_or_default(field) {
format!(
"opts.get(\"{}\").and_then(|t| t.decode().ok()).unwrap_or_default(),",
field.name
)
} else {
if defers_to_field_type_default(field) {
format!(
"opts.get(\"{}\").and_then(|t| t.decode().ok()).unwrap_or_default(),",
field.name
)
} else {
format!(
"opts.get(\"{}\").and_then(|t| t.decode().ok()).unwrap_or({}),",
field.name,
default_value_for_field_in_type(field, "rust", typ)
)
}
};
minijinja::context! {
name => crate::codegen::naming::internal_rust_identifier(&field.name),
assignment => assignment,
}
})
.collect();
crate::codegen::template_env::render(
"config_gen/rustler_kwargs_constructor.jinja",
minijinja::context! {
fields => fields,
},
)
}