submilli_engine/runtime/
gc_singleton.rs1use crate::runtime::host::fatal_host_error;
7
8use wasmtime::{
9 ArrayType, Engine, FieldType, Finality, FuncType, RecGroupBuilder, StructType, ValType,
10};
11
12pub(crate) fn singleton_struct(
13 engine: &Engine,
14 finality: Finality,
15 supertype: Option<StructType>,
16 fields: Vec<FieldType>,
17) -> wasmtime::Result<StructType> {
18 let mut builder = RecGroupBuilder::new(engine);
19 let id = builder.declare_struct();
20 let mut def = builder.define_struct(id);
21 def.finality(finality);
22 if let Some(supertype) = supertype {
23 def.supertype(supertype);
24 }
25 for field in fields {
26 def.field(field);
27 }
28 def.finish();
29 Ok(builder
32 .build()
33 .map_err(fatal_host_error)?
34 .get_struct(id)
35 .expect("declared singleton struct retains its kind"))
36}
37
38pub(crate) fn singleton_array(
39 engine: &Engine,
40 finality: Finality,
41 field: FieldType,
42) -> wasmtime::Result<ArrayType> {
43 let mut builder = RecGroupBuilder::new(engine);
44 let id = builder.declare_array();
45 let mut def = builder.define_array(id);
46 def.finality(finality);
47 def.element(field);
48 def.finish();
49 Ok(builder
52 .build()
53 .map_err(fatal_host_error)?
54 .get_array(id)
55 .expect("declared singleton array retains its kind"))
56}
57
58pub(crate) fn singleton_func(
61 engine: &Engine,
62 params: Vec<ValType>,
63 results: Vec<ValType>,
64) -> wasmtime::Result<FuncType> {
65 let mut builder = RecGroupBuilder::new(engine);
66 let id = builder.declare_func();
67 let mut def = builder.define_func(id);
68 def.finality(Finality::NonFinal);
69 for param in params {
70 def.param(param);
71 }
72 for result in results {
73 def.result(result);
74 }
75 def.finish();
76 Ok(builder
79 .build()
80 .map_err(fatal_host_error)?
81 .get_func(id)
82 .expect("declared singleton func retains its kind"))
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use crate::runtime::host::FatalHostError;
89
90 #[test]
91 fn invalid_singleton_layout_is_fatal_and_does_not_break_next_build() {
92 let engine = crate::RuntimeConfig::default().engine().unwrap();
93 let parent = singleton_struct(&engine, Finality::Final, None, vec![]).unwrap();
94 let error =
95 singleton_struct(&engine, Finality::NonFinal, Some(parent), vec![]).unwrap_err();
96 assert!(error.is::<FatalHostError>(), "{error:#}");
97 singleton_struct(&engine, Finality::NonFinal, None, vec![]).unwrap();
98 singleton_array(
99 &engine,
100 Finality::Final,
101 FieldType::new(wasmtime::Mutability::Var, wasmtime::StorageType::I16),
102 )
103 .unwrap();
104 singleton_func(&engine, vec![ValType::I32], vec![]).unwrap();
105 }
106}