1use indexmap::IndexMap;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6pub enum WasmType {
7 I32,
9 I64,
11 F32,
13 F64,
15 Ptr,
17 Void,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct HostFunctionDef {
24 pub name: String,
26 pub params: Vec<WasmType>,
28 pub return_type: WasmType,
30}
31
32impl HostFunctionDef {
33 pub fn new(name: impl Into<String>, params: Vec<WasmType>, return_type: WasmType) -> Self {
34 Self {
35 name: name.into(),
36 params,
37 return_type,
38 }
39 }
40}
41
42#[derive(Debug, Clone, Default)]
45pub struct HostFunctionRegistry {
46 functions: IndexMap<String, HostFunctionDef>,
47}
48
49impl HostFunctionRegistry {
50 pub fn with_standard_functions() -> Self {
52 let mut registry = Self::default();
53
54 registry.register(HostFunctionDef::new(
56 "hstringEquals",
57 vec![WasmType::Ptr, WasmType::Ptr],
58 WasmType::I32,
59 ));
60
61 registry.register(HostFunctionDef::new(
63 "hlistContainsString",
64 vec![WasmType::Ptr, WasmType::Ptr],
65 WasmType::I32,
66 ));
67 registry.register(HostFunctionDef::new("hnewList", vec![], WasmType::Ptr));
68
69 registry.register(HostFunctionDef::new(
70 "hgetItem",
71 vec![WasmType::Ptr, WasmType::I32],
72 WasmType::Ptr,
73 ));
74
75 registry.register(HostFunctionDef::new(
76 "hsize",
77 vec![WasmType::Ptr],
78 WasmType::I32,
79 ));
80
81 registry.register(HostFunctionDef::new(
82 "happend",
83 vec![WasmType::Ptr, WasmType::Ptr],
84 WasmType::Void,
85 ));
86
87 registry.register(HostFunctionDef::new(
88 "hsetItem",
89 vec![WasmType::Ptr, WasmType::I32, WasmType::Ptr],
90 WasmType::Void,
91 ));
92
93 registry.register(HostFunctionDef::new(
94 "hinsert",
95 vec![WasmType::Ptr, WasmType::I32, WasmType::Ptr],
96 WasmType::Void,
97 ));
98
99 registry.register(HostFunctionDef::new(
100 "hremove",
101 vec![WasmType::Ptr, WasmType::I32],
102 WasmType::Void,
103 ));
104
105 registry.register(HostFunctionDef::new(
107 "hparseSchedule",
108 vec![WasmType::I32, WasmType::Ptr], WasmType::Ptr,
110 ));
111
112 registry.register(HostFunctionDef::new(
113 "hscheduleString",
114 vec![WasmType::Ptr],
115 WasmType::Ptr,
116 ));
117
118 registry.register(HostFunctionDef::new(
120 "hround",
121 vec![WasmType::F32],
122 WasmType::I32,
123 ));
124
125 registry.register(HostFunctionDef::new(
127 "hsin",
128 vec![WasmType::F64],
129 WasmType::F64,
130 ));
131 registry.register(HostFunctionDef::new(
132 "hcos",
133 vec![WasmType::F64],
134 WasmType::F64,
135 ));
136 registry.register(HostFunctionDef::new(
137 "hasin",
138 vec![WasmType::F64],
139 WasmType::F64,
140 ));
141 registry.register(HostFunctionDef::new(
142 "hacos",
143 vec![WasmType::F64],
144 WasmType::F64,
145 ));
146 registry.register(HostFunctionDef::new(
147 "hatan",
148 vec![WasmType::F64],
149 WasmType::F64,
150 ));
151 registry.register(HostFunctionDef::new(
152 "hatan2",
153 vec![WasmType::F64, WasmType::F64],
154 WasmType::F64,
155 ));
156
157 registry.register(HostFunctionDef::new(
166 "hprecomputed0",
167 vec![WasmType::I32, WasmType::Ptr],
168 WasmType::I32,
169 ));
170
171 registry.register(HostFunctionDef::new(
174 "hprecomputed1",
175 vec![WasmType::I32, WasmType::Ptr, WasmType::Ptr],
176 WasmType::I32,
177 ));
178
179 registry.register(HostFunctionDef::new(
182 "hprecomputed2",
183 vec![WasmType::I32, WasmType::Ptr, WasmType::Ptr, WasmType::Ptr],
184 WasmType::I32,
185 ));
186
187 registry
188 }
189
190 pub fn new() -> Self {
192 Self::default()
193 }
194
195 pub fn register(&mut self, def: HostFunctionDef) {
197 self.functions.insert(def.name.clone(), def);
198 }
199
200 pub fn lookup(&self, name: &str) -> Option<&HostFunctionDef> {
202 self.functions.get(name)
203 }
204
205 pub fn function_names(&self) -> Vec<&str> {
207 self.functions.keys().map(|s| s.as_str()).collect()
208 }
209
210 pub fn len(&self) -> usize {
212 self.functions.len()
213 }
214
215 pub fn is_empty(&self) -> bool {
217 self.functions.is_empty()
218 }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224
225 #[test]
226 fn test_empty_registry() {
227 let registry = HostFunctionRegistry::new();
228 assert_eq!(registry.len(), 0);
229 assert!(registry.is_empty());
230 }
231
232 #[test]
233 fn test_register_function() {
234 let mut registry = HostFunctionRegistry::new();
235 let func = HostFunctionDef::new(
236 "test_func",
237 vec![WasmType::I32, WasmType::Ptr],
238 WasmType::I32,
239 );
240
241 registry.register(func.clone());
242 assert_eq!(registry.len(), 1);
243
244 let looked_up = registry.lookup("test_func");
245 assert!(looked_up.is_some());
246 assert_eq!(looked_up.unwrap(), &func);
247 }
248
249 #[test]
250 fn test_lookup_nonexistent() {
251 let registry = HostFunctionRegistry::new();
252 assert!(registry.lookup("nonexistent").is_none());
253 }
254
255 #[test]
256 fn test_standard_functions() {
257 let registry = HostFunctionRegistry::with_standard_functions();
258
259 assert!(registry.len() > 0);
261
262 assert!(registry.lookup("hstringEquals").is_some());
264 assert!(registry.lookup("hnewList").is_some());
265 assert!(registry.lookup("hgetItem").is_some());
266 assert!(registry.lookup("hsize").is_some());
267 assert!(registry.lookup("happend").is_some());
268 assert!(registry.lookup("hparseSchedule").is_some());
269 assert!(registry.lookup("hscheduleString").is_some());
270 assert!(registry.lookup("hround").is_some());
271 }
272
273 #[test]
274 fn test_hstring_equals_signature() {
275 let registry = HostFunctionRegistry::with_standard_functions();
276 let func = registry.lookup("hstringEquals").unwrap();
277
278 assert_eq!(func.name, "hstringEquals");
279 assert_eq!(func.params, vec![WasmType::Ptr, WasmType::Ptr]);
280 assert_eq!(func.return_type, WasmType::I32);
281 }
282
283 #[test]
284 fn test_function_names() {
285 let mut registry = HostFunctionRegistry::new();
286 registry.register(HostFunctionDef::new("func1", vec![], WasmType::Void));
287 registry.register(HostFunctionDef::new("func2", vec![], WasmType::Void));
288
289 let names = registry.function_names();
290 assert_eq!(names.len(), 2);
291 assert!(names.contains(&"func1"));
292 assert!(names.contains(&"func2"));
293 }
294
295 #[test]
296 fn test_wasm_type_serialization() {
297 let wasm_type = WasmType::I32;
298 let json = serde_json::to_string(&wasm_type).unwrap();
299 let deserialized: WasmType = serde_json::from_str(&json).unwrap();
300 assert_eq!(wasm_type, deserialized);
301 }
302}