1use itertools::Itertools;
4use wasmer_types::{FunctionType, LocalFunctionIndex, Type};
5
6#[derive(Debug, Clone)]
9pub enum CompiledKind {
10 Local(LocalFunctionIndex, String),
12 FunctionCallTrampoline(FunctionType),
14 DynamicFunctionTrampoline(FunctionType),
16 Module,
18}
19
20pub fn types_to_signature(types: &[Type]) -> String {
23 let tokens = types
24 .iter()
25 .map(|ty| match ty {
26 Type::I32 => "i",
27 Type::I64 => "I",
28 Type::F32 => "f",
29 Type::F64 => "F",
30 Type::V128 => "v",
31 Type::ExternRef => "e",
32 Type::FuncRef => "r",
33 Type::ExceptionRef => "x",
34 })
35 .collect_vec();
36 tokens
38 .chunk_by(|a, b| a == b)
39 .map(|chunk| {
40 if chunk.len() >= 8 {
41 format!("{}x{}", chunk.len(), chunk[0])
42 } else {
43 chunk.to_owned().join("")
44 }
45 })
46 .join("")
47}
48
49fn sanitize_filename(name: &str) -> String {
51 name.chars()
52 .map(|c| {
53 if c.is_alphanumeric() || c == '_' || c == '-' {
54 c
55 } else {
56 '_'
57 }
58 })
59 .collect()
60}
61
62pub fn function_kind_to_filename(kind: &CompiledKind, suffix: &str) -> String {
65 match kind {
66 CompiledKind::Local(local_func_index, name) => {
67 let mut name = sanitize_filename(name);
68
69 const PATH_LIMIT: usize = 255;
71
72 if name.len() + suffix.len() > PATH_LIMIT {
73 let id_string = local_func_index.as_u32().to_string();
74 name.truncate(PATH_LIMIT - id_string.len() - suffix.len() - 1);
75 name.push('_');
76 name.push_str(&id_string);
77 name.push_str(suffix);
78 } else {
79 name.push_str(suffix);
80 }
81
82 debug_assert!(name.len() <= PATH_LIMIT);
83 name
84 }
85 CompiledKind::FunctionCallTrampoline(func_type) => format!(
86 "trampoline_call_{}_{}",
87 types_to_signature(func_type.params()),
88 types_to_signature(func_type.results())
89 ),
90 CompiledKind::DynamicFunctionTrampoline(func_type) => format!(
91 "trampoline_dynamic_{}_{}",
92 types_to_signature(func_type.params()),
93 types_to_signature(func_type.results())
94 ),
95 CompiledKind::Module => "module".into(),
96 }
97}