use crate::lang::types::kind::TypeKind;
use crate::lang::types::kind::wire::WireOnly;
use crate::output::{FileType, Output};
use crate::pass::output::common::wire::WireCodeGen;
use crate::pass::{OutputResult, PassInfo, model, output};
use interoptopus::inventory::Types as RsTypes;
use interoptopus_backends::template::Context;
use std::collections::HashMap;
#[derive(Default)]
pub struct Config {}
pub struct Pass {
info: PassInfo,
helper_classes: HashMap<Output, Vec<String>>,
}
impl Pass {
#[must_use]
pub fn new(_: Config) -> Self {
Self { info: PassInfo { name: file!() }, helper_classes: HashMap::default() }
}
pub fn process(
&mut self,
_pass_meta: &mut crate::pass::PassMeta,
output_master: &output::common::master::Pass,
types: &model::common::types::all::Pass,
id_map: &model::common::id_map::Pass,
rs_types: &RsTypes,
wire_types: &output::common::wire::wire_type::Pass,
) -> OutputResult {
let templates = output_master.templates();
let codegen = WireCodeGen { rs_types };
let mut all_helpers = Vec::new();
for (type_id, ty) in types.iter() {
let TypeKind::WireOnly(WireOnly::Composite(composite)) = &ty.kind else {
continue;
};
if wire_types.rendered_inner_type(*type_id) {
continue;
}
let field_decls: Vec<String> = composite
.fields
.iter()
.map(|f| {
let field_type_name = resolve_field_type_name(f.ty, types, id_map, &codegen);
format!("public {field_type_name} {};", f.name)
})
.collect();
let mut ctx = Context::new();
ctx.insert("class_name", &ty.name);
ctx.insert("field_decls", &field_decls);
let result = templates.render("common/wire/wire_helper_class.cs", &ctx)?;
all_helpers.push(result);
}
all_helpers.sort();
let mut first = true;
for file in output_master.outputs_of(FileType::Csharp) {
if first {
self.helper_classes.insert(file.clone(), all_helpers.clone());
first = false;
} else {
self.helper_classes.insert(file.clone(), Vec::new());
}
}
Ok(())
}
#[must_use]
pub fn helper_classes_for(&self, output: &Output) -> Option<&[String]> {
self.helper_classes.get(output).map(std::vec::Vec::as_slice)
}
}
fn resolve_field_type_name(
cs_ty: crate::lang::TypeId,
types: &model::common::types::all::Pass,
id_map: &model::common::id_map::Pass,
codegen: &WireCodeGen<'_>,
) -> String {
if let Some(t) = types.get(cs_ty) {
return t.name.clone();
}
for rs_id in codegen.rs_types.keys() {
if id_map.ty(*rs_id) == Some(cs_ty) {
return codegen.cs_type_name(*rs_id);
}
}
"object".to_string()
}