use crate::backends::pyo3::type_map::Pyo3Mapper;
pub(super) fn variant_wrapper_constructor_body(typ: &crate::core::ir::TypeDef, mapper: &Pyo3Mapper) -> Option<String> {
use crate::codegen::type_mapper::TypeMapper as _;
let ctor = typ.methods.iter().find(|m| m.name == "new" && m.receiver.is_none())?;
let map_fn = |t: &crate::core::ir::TypeRef| mapper.map_type(t);
let sig_params = crate::codegen::shared::function_params(&ctor.params, &map_fn);
let call_args = ctor
.params
.iter()
.map(|p| p.name.as_str())
.collect::<Vec<_>>()
.join(", ");
let body = if call_args.is_empty() {
"Self::new()".to_string()
} else {
format!("Self::new({call_args})")
};
Some(format!(
" #[new]\n pub fn py_new({sig_params}) -> Self {{\n {body}\n }}\n"
))
}
pub(super) fn should_emit_default_impl(
typ: &crate::core::ir::TypeDef,
impl_block: &str,
default_required: &ahash::AHashSet<&str>,
) -> bool {
if impl_block.contains("impl Default") {
return false;
}
typ.has_default || default_required.contains(typ.name.as_str())
}
fn has_no_arg_static_new(typ: &crate::core::ir::TypeDef) -> bool {
typ.methods
.iter()
.any(|m| m.name == "new" && m.params.is_empty() && m.receiver.is_none())
}
pub(super) fn emit_default_impl(typ: &crate::core::ir::TypeDef) -> String {
let body = if has_no_arg_static_new(typ) {
"Self::new()".to_string()
} else {
"Self { inner: Default::default() }".to_string()
};
format!(
"impl Default for {} {{\n fn default() -> Self {{\n {body}\n }}\n}}\n",
typ.name
)
}
pub(super) fn emit_inner_default_impl(type_name: &str) -> String {
format!(
"impl Default for {type_name} {{\n fn default() -> Self {{\n Self {{ inner: Default::default() }}\n }}\n}}\n"
)
}
pub(super) fn inject_into_impl_block(impl_block: &str, body: &str) -> String {
let trimmed = impl_block.trim_end();
let Some(close_idx) = trimmed.rfind('}') else {
return impl_block.to_string();
};
let (head, tail) = trimmed.split_at(close_idx);
let head_trimmed = head.trim_end();
format!("{head_trimmed}\n\n{body}{tail}\n")
}