1use crate::indexes::{FunctionIndex, GlobalIndex};
2use crate::lib::std::fmt;
3use crate::lib::std::format;
4use crate::lib::std::string::{String, ToString};
5use crate::lib::std::vec::Vec;
6use crate::units::Pages;
7use crate::values::{Value, WasmValueType};
8use std::cell::UnsafeCell;
9use std::rc::Rc;
10use std::sync::Arc;
11
12#[derive(
18 Copy, Debug, Clone, Eq, PartialEq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
19)]
20#[archive(as = "Self")]
21pub enum Type {
22 I32,
24 I64,
26 F32,
28 F64,
30 V128,
32 ExternRef, FuncRef,
36}
37
38impl Type {
39 pub fn is_num(self) -> bool {
42 matches!(self, Self::I32 | Self::I64 | Self::F32 | Self::F64 | Self::V128)
43 }
44
45 pub fn is_ref(self) -> bool {
47 matches!(self, Self::ExternRef | Self::FuncRef)
48 }
49}
50
51impl fmt::Display for Type {
52 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53 write!(f, "{:?}", self)
54 }
55}
56
57#[derive(
58 Copy, Clone, Debug, Eq, PartialEq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
59)]
60#[archive(as = "Self")]
61pub struct V128(pub(crate) [u8; 16]);
63
64impl V128 {
65 pub fn bytes(&self) -> &[u8; 16] {
67 &self.0
68 }
69 pub fn iter(&self) -> impl Iterator<Item = &u8> {
71 self.0.iter()
72 }
73
74 pub fn to_vec(self) -> Vec<u8> {
76 self.0.to_vec()
77 }
78
79 pub fn as_slice(&self) -> &[u8] {
81 &self.0[..]
82 }
83}
84
85impl From<[u8; 16]> for V128 {
86 fn from(array: [u8; 16]) -> Self {
87 Self(array)
88 }
89}
90
91impl From<&[u8]> for V128 {
92 fn from(slice: &[u8]) -> Self {
93 assert_eq!(slice.len(), 16);
94 let mut buffer = [0; 16];
95 buffer.copy_from_slice(slice);
96 Self(buffer)
97 }
98}
99
100#[derive(Debug, Clone, PartialEq, Eq, Hash)]
108pub enum ExternType {
109 Function(FunctionType),
111 Global(GlobalType),
113 Table(TableType),
115 Memory(MemoryType),
117}
118
119macro_rules! accessors {
120 ($(($variant:ident($ty:ty) $get:ident $unwrap:ident))*) => ($(
121 pub fn $get(&self) -> Option<&$ty> {
124 if let Self::$variant(e) = self {
125 Some(e)
126 } else {
127 None
128 }
129 }
130
131 pub fn $unwrap(&self) -> &$ty {
138 self.$get().expect(concat!("expected ", stringify!($ty)))
139 }
140 )*)
141}
142
143impl ExternType {
144 accessors! {
145 (Function(FunctionType) func unwrap_func)
146 (Global(GlobalType) global unwrap_global)
147 (Table(TableType) table unwrap_table)
148 (Memory(MemoryType) memory unwrap_memory)
149 }
150}
151
152#[derive(Debug, Clone, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)]
159pub struct FunctionType {
160 params: Arc<[Type]>,
162 results: Arc<[Type]>,
164}
165
166impl FunctionType {
167 pub fn new<Params, Returns>(params: Params, returns: Returns) -> Self
169 where
170 Params: Into<Arc<[Type]>>,
171 Returns: Into<Arc<[Type]>>,
172 {
173 Self { params: params.into(), results: returns.into() }
174 }
175
176 pub fn params(&self) -> &[Type] {
178 &self.params
179 }
180
181 pub fn results(&self) -> &[Type] {
183 &self.results
184 }
185}
186
187impl fmt::Display for FunctionType {
188 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
189 let params = self.params.iter().map(|p| format!("{:?}", p)).collect::<Vec<_>>().join(", ");
190 let results =
191 self.results.iter().map(|p| format!("{:?}", p)).collect::<Vec<_>>().join(", ");
192 write!(f, "[{}] -> [{}]", params, results)
193 }
194}
195
196macro_rules! implement_from_pair_to_functiontype {
199 ($($N:literal,$M:literal)+) => {
200 $(
201 impl From<([Type; $N], [Type; $M])> for FunctionType {
202 fn from(pair: ([Type; $N], [Type; $M])) -> Self {
203 Self::new(&pair.0[..], &pair.1[..])
204 }
205 }
206 )+
207 }
208}
209
210implement_from_pair_to_functiontype! {
211 0,0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9
212 1,0 1,1 1,2 1,3 1,4 1,5 1,6 1,7 1,8 1,9
213 2,0 2,1 2,2 2,3 2,4 2,5 2,6 2,7 2,8 2,9
214 3,0 3,1 3,2 3,3 3,4 3,5 3,6 3,7 3,8 3,9
215 4,0 4,1 4,2 4,3 4,4 4,5 4,6 4,7 4,8 4,9
216 5,0 5,1 5,2 5,3 5,4 5,5 5,6 5,7 5,8 5,9
217 6,0 6,1 6,2 6,3 6,4 6,5 6,6 6,7 6,8 6,9
218 7,0 7,1 7,2 7,3 7,4 7,5 7,6 7,7 7,8 7,9
219 8,0 8,1 8,2 8,3 8,4 8,5 8,6 8,7 8,8 8,9
220 9,0 9,1 9,2 9,3 9,4 9,5 9,6 9,7 9,8 9,9
221}
222
223impl From<&Self> for FunctionType {
224 fn from(as_ref: &Self) -> Self {
225 as_ref.clone()
226 }
227}
228
229pub struct FunctionTypeRef<'a> {
231 params: &'a [Type],
233 results: &'a [Type],
235}
236
237impl<'a> FunctionTypeRef<'a> {
238 pub fn new(params: &'a [Type], results: &'a [Type]) -> Self {
240 Self { params, results }
241 }
242
243 pub fn params(&self) -> &[Type] {
245 self.params
246 }
247
248 pub fn results(&self) -> &[Type] {
250 self.results
251 }
252}
253
254impl<'a> From<&'a FunctionType> for FunctionTypeRef<'a> {
255 fn from(FunctionType { params, results }: &'a FunctionType) -> Self {
256 Self { params, results }
257 }
258}
259
260impl<'a> From<&'a ArchivedFunctionType> for FunctionTypeRef<'a> {
261 fn from(ArchivedFunctionType { params, results }: &'a ArchivedFunctionType) -> Self {
262 Self { params: &**params, results: &**results }
263 }
264}
265
266#[derive(
268 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
269)]
270#[archive(as = "Self")]
271pub enum Mutability {
272 Const,
274 Var,
276}
277
278impl Mutability {
279 pub fn is_mutable(self) -> bool {
281 match self {
282 Self::Const => false,
283 Self::Var => true,
284 }
285 }
286}
287
288#[derive(
290 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
291)]
292#[archive(as = "Self")]
293pub struct GlobalType {
294 pub ty: Type,
296 pub mutability: Mutability,
298}
299
300impl GlobalType {
308 pub fn new(ty: Type, mutability: Mutability) -> Self {
319 Self { ty, mutability }
320 }
321}
322
323impl fmt::Display for GlobalType {
324 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
325 let mutability = match self.mutability {
326 Mutability::Const => "constant",
327 Mutability::Var => "mutable",
328 };
329 write!(f, "{} ({})", self.ty, mutability)
330 }
331}
332
333#[derive(Debug, Clone, Copy, PartialEq, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)]
335#[archive(as = "Self")]
336pub enum GlobalInit {
337 I32Const(i32),
339 I64Const(i64),
341 F32Const(f32),
343 F64Const(f64),
345 V128Const(V128),
347 GetGlobal(GlobalIndex),
349 RefNullConst,
354 RefFunc(FunctionIndex),
356}
357
358impl Eq for GlobalInit {}
359
360impl GlobalInit {
361 pub fn from_value<T: WasmValueType>(value: Value<T>) -> Self {
363 match value {
364 Value::I32(i) => Self::I32Const(i),
365 Value::I64(i) => Self::I64Const(i),
366 Value::F32(f) => Self::F32Const(f),
367 Value::F64(f) => Self::F64Const(f),
368 _ => unimplemented!("GlobalInit from_value for {:?}", value),
369 }
370 }
371 pub fn to_value<T: WasmValueType>(&self) -> Value<T> {
373 match self {
374 Self::I32Const(i) => Value::I32(*i),
375 Self::I64Const(i) => Value::I64(*i),
376 Self::F32Const(f) => Value::F32(*f),
377 Self::F64Const(f) => Value::F64(*f),
378 _ => unimplemented!("GlobalInit to_value for {:?}", self),
379 }
380 }
381}
382
383#[derive(
391 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
392)]
393pub struct TableType {
394 pub ty: Type,
396 pub minimum: u32,
398 pub maximum: Option<u32>,
400}
401
402impl TableType {
403 pub fn new(ty: Type, minimum: u32, maximum: Option<u32>) -> Self {
406 Self { ty, minimum, maximum }
407 }
408}
409
410impl fmt::Display for TableType {
411 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
412 if let Some(maximum) = self.maximum {
413 write!(f, "{} ({}..{})", self.ty, self.minimum, maximum)
414 } else {
415 write!(f, "{} ({}..)", self.ty, self.minimum)
416 }
417 }
418}
419
420#[derive(
427 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
428)]
429pub struct MemoryType {
430 pub minimum: Pages,
432 pub maximum: Option<Pages>,
434 pub shared: bool,
436}
437
438impl MemoryType {
439 pub fn new<IntoPages>(minimum: IntoPages, maximum: Option<IntoPages>, shared: bool) -> Self
442 where
443 IntoPages: Into<Pages>,
444 {
445 Self { minimum: minimum.into(), maximum: maximum.map(Into::into), shared }
446 }
447}
448
449impl fmt::Display for MemoryType {
450 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
451 let shared = if self.shared { "shared" } else { "not shared" };
452 if let Some(maximum) = self.maximum {
453 write!(f, "{} ({:?}..{:?})", shared, self.minimum, maximum)
454 } else {
455 write!(f, "{} ({:?}..)", shared, self.minimum)
456 }
457 }
458}
459
460#[derive(Debug, Clone, PartialEq, Eq, Hash)]
469pub struct Import<S = String, T = ExternType> {
470 module: S,
471 name: S,
472 index: u32,
473 ty: T,
474}
475
476impl<S: AsRef<str>, T> Import<S, T> {
477 pub fn new(module: S, name: S, index: u32, ty: T) -> Self {
480 Self { module, name, index, ty }
481 }
482
483 pub fn module(&self) -> &str {
485 self.module.as_ref()
486 }
487
488 pub fn name(&self) -> &str {
491 self.name.as_ref()
492 }
493
494 pub fn index(&self) -> u32 {
496 self.index
497 }
498
499 pub fn ty(&self) -> &T {
501 &self.ty
502 }
503}
504
505#[derive(Debug, Clone, PartialEq, Eq, Hash)]
517pub struct ExportType<T = ExternType> {
518 name: String,
519 ty: T,
520}
521
522impl<T> ExportType<T> {
523 pub fn new(name: &str, ty: T) -> Self {
526 Self { name: name.to_string(), ty }
527 }
528
529 pub fn name(&self) -> &str {
531 &self.name
532 }
533
534 pub fn ty(&self) -> &T {
536 &self.ty
537 }
538}
539
540#[repr(C)]
544#[derive(Debug, Clone, PartialEq, Eq)]
545pub struct FastGasCounter {
546 pub burnt_gas: u64,
554 pub gas_limit: u64,
556}
557
558impl FastGasCounter {
559 pub fn new(limit: u64) -> Self {
561 Self { burnt_gas: 0, gas_limit: limit }
562 }
563 pub fn burnt(&self) -> u64 {
565 self.burnt_gas
566 }
567}
568
569impl fmt::Display for FastGasCounter {
570 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
571 write!(f, "burnt: {} limit: {} ", self.burnt(), self.gas_limit,)
572 }
573}
574
575#[derive(Clone)]
577pub struct InstanceConfig {
578 pub gas_counter: *mut FastGasCounter,
580 default_gas_counter: Option<Rc<UnsafeCell<FastGasCounter>>>,
581 pub stack_limit: u32,
583}
584
585impl InstanceConfig {
586 pub fn with_stack_limit(stack_limit: u32) -> Self {
588 let result = Rc::new(UnsafeCell::new(FastGasCounter { burnt_gas: 0, gas_limit: u64::MAX }));
589 Self { gas_counter: result.get(), default_gas_counter: Some(result), stack_limit }
590 }
591
592 pub unsafe fn with_counter(mut self, gas_counter: *mut FastGasCounter) -> Self {
596 self.gas_counter = gas_counter;
597 self.default_gas_counter = None;
598 self
599 }
600}
601
602#[cfg(test)]
603mod tests {
604 use super::*;
605
606 const VOID_TO_VOID: ([Type; 0], [Type; 0]) = ([], []);
607 const I32_I32_TO_VOID: ([Type; 2], [Type; 0]) = ([Type::I32, Type::I32], []);
608 const V128_I64_TO_I32: ([Type; 2], [Type; 1]) = ([Type::V128, Type::I64], [Type::I32]);
609 const NINE_V128_TO_NINE_I32: ([Type; 9], [Type; 9]) = ([Type::V128; 9], [Type::I32; 9]);
610
611 #[test]
612 fn convert_tuple_to_functiontype() {
613 let ty: FunctionType = VOID_TO_VOID.into();
614 assert_eq!(ty.params().len(), 0);
615 assert_eq!(ty.results().len(), 0);
616
617 let ty: FunctionType = I32_I32_TO_VOID.into();
618 assert_eq!(ty.params().len(), 2);
619 assert_eq!(ty.params()[0], Type::I32);
620 assert_eq!(ty.params()[1], Type::I32);
621 assert_eq!(ty.results().len(), 0);
622
623 let ty: FunctionType = V128_I64_TO_I32.into();
624 assert_eq!(ty.params().len(), 2);
625 assert_eq!(ty.params()[0], Type::V128);
626 assert_eq!(ty.params()[1], Type::I64);
627 assert_eq!(ty.results().len(), 1);
628 assert_eq!(ty.results()[0], Type::I32);
629
630 let ty: FunctionType = NINE_V128_TO_NINE_I32.into();
631 assert_eq!(ty.params().len(), 9);
632 assert_eq!(ty.results().len(), 9);
633 }
634}