use crate::dispatch::{Item, ItemKind};
use crate::lang::plugin::PLUGIN_DEFAULT_EMISSION;
use crate::output::{FileType, Output};
use crate::pass::output::dotnet::interop::{raw, service};
use crate::pass::{OutputResult, PassInfo, model, output};
use interoptopus_backends::template::Context;
use std::collections::HashMap;
#[derive(Default)]
pub struct Config {}
pub struct Pass {
info: PassInfo,
trampolines: HashMap<Output, Vec<String>>,
}
impl Pass {
#[must_use]
pub fn new(_: Config) -> Self {
Self { info: PassInfo { name: file!() }, trampolines: HashMap::default() }
}
pub fn process(
&mut self,
_pass_meta: &mut crate::pass::PassMeta,
output_master: &output::common::master::Pass,
trampoline_model: &model::dotnet::trampoline::Pass,
raw_pass: &raw::Pass,
service_pass: &service::Pass,
meta_info: &crate::pass::meta::dotnet::info::Pass,
) -> OutputResult {
let templates = output_master.templates();
for file in output_master.outputs_of(FileType::Csharp) {
let emission = PLUGIN_DEFAULT_EMISSION;
let Some(fe) = emission.file_emission() else {
self.trampolines.insert(file.clone(), Vec::new());
continue;
};
if !output_master.item_belongs_to(Item { kind: ItemKind::PluginInterface, emission: fe.clone() }, file) {
self.trampolines.insert(file.clone(), Vec::new());
continue;
}
let mut methods = Vec::new();
for entry in trampoline_model.entries() {
if let Some(m) = raw_pass.get(entry.fn_id) {
methods.push(m.to_string());
} else if let Some(m) = service_pass.get(entry.fn_id) {
methods.push(m.to_string());
}
}
if !methods.is_empty() {
let ctx = Context::new();
let register = templates.render("dotnet/interop/register_trampoline.cs", &ctx)?;
methods.insert(0, register.trim_end().to_string());
let mut query_ctx = Context::new();
query_ctx.insert("guard_hash", &meta_info.api_hash_hex_literal());
let query = templates.render("dotnet/interop/query_trampoline.cs", &query_ctx)?;
methods.insert(1, query.trim_end().to_string());
}
self.trampolines.insert(file.clone(), methods);
}
Ok(())
}
#[must_use]
pub fn trampolines_for(&self, output: &Output) -> Option<&[String]> {
self.trampolines.get(output).map(Vec::as_slice)
}
}