pub mod all;
pub mod raw;
pub mod service;
use crate::lang::FunctionId;
use crate::lang::TypeId;
use crate::lang::functions::{Argument, Function};
use crate::lang::plugin::interface::{Method, ResultKind};
use crate::lang::types::kind::Primitive;
use crate::lang::types::kind::{TypeKind, TypePattern};
use crate::pass::{model, output};
use std::collections::HashMap;
pub(super) fn split_result_kinds<'a, I>(methods: I, types: &'a model::common::types::all::Pass) -> (HashMap<FunctionId, &'a str>, HashMap<FunctionId, &'a str>)
where
I: IntoIterator<Item = &'a Method>,
{
let mut try_wraps = HashMap::new();
let mut passthrough_wraps = HashMap::new();
for m in methods {
match m.result {
Some(ResultKind::Try(id)) => {
if let Some(t) = types.get(id) {
try_wraps.insert(m.base, t.name.as_str());
}
}
Some(ResultKind::Passthrough(id)) => {
if let Some(t) = types.get(id) {
passthrough_wraps.insert(m.base, t.name.as_str());
}
}
None => {}
}
}
(try_wraps, passthrough_wraps)
}
pub(super) fn unmanaged_args(
func: &Function,
unmanaged_names: &output::common::conversion::unmanaged_names::Pass,
unmanaged_conversion: &output::common::conversion::unmanaged_conversion::Pass,
) -> (String, String) {
let args: Vec<String> = func
.signature
.arguments
.iter()
.filter_map(|arg| {
let ty_name = unmanaged_names.name(arg.ty)?;
Some(format!("{ty_name} {}", arg.name))
})
.collect();
let forward: Vec<String> = func
.signature
.arguments
.iter()
.map(|a| format!("{}{}", a.name, unmanaged_conversion.to_managed_suffix(a.ty)))
.collect();
(args.join(", "), forward.join(", "))
}
pub(super) fn unmanaged_args_except_last(
func: &Function,
unmanaged_names: &output::common::conversion::unmanaged_names::Pass,
unmanaged_conversion: &output::common::conversion::unmanaged_conversion::Pass,
) -> (String, String) {
let n = func.signature.arguments.len().saturating_sub(1);
let args: Vec<String> = func
.signature
.arguments
.iter()
.filter_map(|arg| {
let ty_name = unmanaged_names.name(arg.ty)?;
Some(format!("{ty_name} {}", arg.name))
})
.collect();
let forward: Vec<String> = func
.signature
.arguments
.iter()
.take(n)
.map(|a| format!("{}{}", a.name, unmanaged_conversion.to_managed_suffix(a.ty)))
.collect();
(args.join(", "), forward.join(", "))
}
pub(super) fn rval_unmanaged_name<'a>(func: &Function, rval_type: &'a str, unmanaged_names: &'a output::common::conversion::unmanaged_names::Pass) -> &'a str {
unmanaged_names.name(func.signature.rval).map_or(rval_type, String::as_str)
}
pub(super) fn async_callback_inner(func: &Function, types: &model::common::types::all::Pass) -> Option<TypeId> {
let last = func.signature.arguments.last()?;
async_callback_inner_from_args(std::slice::from_ref(last), types)
}
fn async_callback_inner_from_args(args: &[Argument], types: &model::common::types::all::Pass) -> Option<TypeId> {
let last = args.last()?;
let ty = types.get(last.ty)?;
match &ty.kind {
TypeKind::TypePattern(TypePattern::AsyncCallback(inner)) => Some(*inner),
_ => None,
}
}
pub(super) fn async_continuation(
inner_id: TypeId,
types: &model::common::types::all::Pass,
unmanaged_conversion: &output::common::conversion::unmanaged_conversion::Pass,
has_result_passthrough: bool,
) -> String {
let is_void = matches!(types.get(inner_id).map(|t| &t.kind), Some(TypeKind::Primitive(Primitive::Void)));
let success = if is_void {
"cb.UnsafeComplete()".to_string()
} else {
let suffix = unmanaged_conversion.to_unmanaged_suffix(inner_id);
format!("cb.UnsafeComplete(t.Result{suffix})")
};
if has_result_passthrough {
format!("ContinueWith(t => {{ if (t.IsCanceled) cb.UnsafeCompleteCancelled(); else {success}; }})")
} else {
format!("ContinueWith(t => {{ if (t.IsCanceled || t.IsFaulted) cb.UnsafeCompleteCancelled(); else {success}; }})")
}
}