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,
19 Debug,
20 Clone,
21 Eq,
22 PartialEq,
23 Hash,
24 rkyv::Serialize,
25 rkyv::Deserialize,
26 rkyv::Archive,
27 rkyv::Portable,
28 rkyv::bytecheck::CheckBytes,
29)]
30#[bytecheck(crate = rkyv::bytecheck)]
31#[rkyv(as = Type)]
32#[repr(u8)]
33pub enum Type {
34 I32,
36 I64,
38 F32,
40 F64,
42 V128,
44 ExternRef, FuncRef,
48}
49
50impl Type {
51 pub fn is_num(self) -> bool {
54 matches!(self, Self::I32 | Self::I64 | Self::F32 | Self::F64 | Self::V128)
55 }
56
57 pub fn is_ref(self) -> bool {
59 matches!(self, Self::ExternRef | Self::FuncRef)
60 }
61}
62
63impl fmt::Display for Type {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 write!(f, "{:?}", self)
66 }
67}
68
69#[derive(
70 Copy, Clone, Debug, Eq, PartialEq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
71)]
72pub struct V128(pub(crate) [u8; 16]);
74
75impl V128 {
76 pub fn bytes(&self) -> &[u8; 16] {
78 &self.0
79 }
80 pub fn iter(&self) -> impl Iterator<Item = &u8> {
82 self.0.iter()
83 }
84
85 pub fn to_vec(self) -> Vec<u8> {
87 self.0.to_vec()
88 }
89
90 pub fn as_slice(&self) -> &[u8] {
92 &self.0[..]
93 }
94}
95
96impl From<[u8; 16]> for V128 {
97 fn from(array: [u8; 16]) -> Self {
98 Self(array)
99 }
100}
101
102impl From<&[u8]> for V128 {
103 fn from(slice: &[u8]) -> Self {
104 assert_eq!(slice.len(), 16);
105 let mut buffer = [0; 16];
106 buffer.copy_from_slice(slice);
107 Self(buffer)
108 }
109}
110
111#[derive(Debug, Clone, PartialEq, Eq, Hash)]
119pub enum ExternType {
120 Function(FunctionType),
122 Global(GlobalType),
124 Table(TableType),
126 Memory(MemoryType),
128}
129
130macro_rules! accessors {
131 ($(($variant:ident($ty:ty) $get:ident $unwrap:ident))*) => ($(
132 pub fn $get(&self) -> Option<&$ty> {
135 if let Self::$variant(e) = self {
136 Some(e)
137 } else {
138 None
139 }
140 }
141
142 pub fn $unwrap(&self) -> &$ty {
149 self.$get().expect(concat!("expected ", stringify!($ty)))
150 }
151 )*)
152}
153
154impl ExternType {
155 accessors! {
156 (Function(FunctionType) func unwrap_func)
157 (Global(GlobalType) global unwrap_global)
158 (Table(TableType) table unwrap_table)
159 (Memory(MemoryType) memory unwrap_memory)
160 }
161}
162
163#[derive(Debug, Clone, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)]
170pub struct FunctionType {
171 params: Arc<[Type]>,
173 results: Arc<[Type]>,
175}
176
177impl FunctionType {
178 pub fn new<Params, Returns>(params: Params, returns: Returns) -> Self
180 where
181 Params: Into<Arc<[Type]>>,
182 Returns: Into<Arc<[Type]>>,
183 {
184 Self { params: params.into(), results: returns.into() }
185 }
186
187 pub fn params(&self) -> &[Type] {
189 &self.params
190 }
191
192 pub fn results(&self) -> &[Type] {
194 &self.results
195 }
196}
197
198impl fmt::Display for FunctionType {
199 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200 let params = self.params.iter().map(|p| format!("{:?}", p)).collect::<Vec<_>>().join(", ");
201 let results =
202 self.results.iter().map(|p| format!("{:?}", p)).collect::<Vec<_>>().join(", ");
203 write!(f, "[{}] -> [{}]", params, results)
204 }
205}
206
207macro_rules! implement_from_pair_to_functiontype {
210 ($($N:literal,$M:literal)+) => {
211 $(
212 impl From<([Type; $N], [Type; $M])> for FunctionType {
213 fn from(pair: ([Type; $N], [Type; $M])) -> Self {
214 Self::new(&pair.0[..], &pair.1[..])
215 }
216 }
217 )+
218 }
219}
220
221implement_from_pair_to_functiontype! {
222 0,0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9
223 1,0 1,1 1,2 1,3 1,4 1,5 1,6 1,7 1,8 1,9
224 2,0 2,1 2,2 2,3 2,4 2,5 2,6 2,7 2,8 2,9
225 3,0 3,1 3,2 3,3 3,4 3,5 3,6 3,7 3,8 3,9
226 4,0 4,1 4,2 4,3 4,4 4,5 4,6 4,7 4,8 4,9
227 5,0 5,1 5,2 5,3 5,4 5,5 5,6 5,7 5,8 5,9
228 6,0 6,1 6,2 6,3 6,4 6,5 6,6 6,7 6,8 6,9
229 7,0 7,1 7,2 7,3 7,4 7,5 7,6 7,7 7,8 7,9
230 8,0 8,1 8,2 8,3 8,4 8,5 8,6 8,7 8,8 8,9
231 9,0 9,1 9,2 9,3 9,4 9,5 9,6 9,7 9,8 9,9
232}
233
234impl From<&Self> for FunctionType {
235 fn from(as_ref: &Self) -> Self {
236 as_ref.clone()
237 }
238}
239
240pub struct FunctionTypeRef<'a> {
242 params: &'a [Type],
244 results: &'a [Type],
246}
247
248impl<'a> FunctionTypeRef<'a> {
249 pub fn new(params: &'a [Type], results: &'a [Type]) -> Self {
251 Self { params, results }
252 }
253
254 pub fn params(&self) -> &[Type] {
256 self.params
257 }
258
259 pub fn results(&self) -> &[Type] {
261 self.results
262 }
263}
264
265impl<'a> From<&'a FunctionType> for FunctionTypeRef<'a> {
266 fn from(FunctionType { params, results }: &'a FunctionType) -> Self {
267 Self { params, results }
268 }
269}
270
271impl<'a> From<&'a ArchivedFunctionType> for FunctionTypeRef<'a> {
272 fn from(ArchivedFunctionType { params, results }: &'a ArchivedFunctionType) -> Self {
273 Self { params: &**params, results: &**results }
274 }
275}
276
277#[derive(
279 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
280)]
281pub enum Mutability {
282 Const,
284 Var,
286}
287
288impl Mutability {
289 pub fn is_mutable(self) -> bool {
291 match self {
292 Self::Const => false,
293 Self::Var => true,
294 }
295 }
296}
297
298#[derive(
300 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
301)]
302pub struct GlobalType {
303 pub ty: Type,
305 pub mutability: Mutability,
307}
308
309impl GlobalType {
317 pub fn new(ty: Type, mutability: Mutability) -> Self {
328 Self { ty, mutability }
329 }
330}
331
332impl fmt::Display for GlobalType {
333 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
334 let mutability = match self.mutability {
335 Mutability::Const => "constant",
336 Mutability::Var => "mutable",
337 };
338 write!(f, "{} ({})", self.ty, mutability)
339 }
340}
341
342#[derive(Debug, Clone, Copy, PartialEq, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)]
344pub enum GlobalInit {
345 I32Const(i32),
347 I64Const(i64),
349 F32Const(f32),
351 F64Const(f64),
353 V128Const(V128),
355 GetGlobal(GlobalIndex),
357 RefNullConst,
362 RefFunc(FunctionIndex),
364}
365
366impl Eq for GlobalInit {}
367
368impl GlobalInit {
369 pub fn from_value<T: WasmValueType>(value: Value<T>) -> Self {
371 match value {
372 Value::I32(i) => Self::I32Const(i),
373 Value::I64(i) => Self::I64Const(i),
374 Value::F32(f) => Self::F32Const(f),
375 Value::F64(f) => Self::F64Const(f),
376 _ => unimplemented!("GlobalInit from_value for {:?}", value),
377 }
378 }
379 pub fn to_value<T: WasmValueType>(&self) -> Value<T> {
381 match self {
382 Self::I32Const(i) => Value::I32(*i),
383 Self::I64Const(i) => Value::I64(*i),
384 Self::F32Const(f) => Value::F32(*f),
385 Self::F64Const(f) => Value::F64(*f),
386 _ => unimplemented!("GlobalInit to_value for {:?}", self),
387 }
388 }
389}
390
391#[derive(
399 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
400)]
401pub struct TableType {
402 pub ty: Type,
404 pub minimum: u32,
406 pub maximum: Option<u32>,
408}
409
410impl TableType {
411 pub fn new(ty: Type, minimum: u32, maximum: Option<u32>) -> Self {
414 Self { ty, minimum, maximum }
415 }
416}
417
418impl fmt::Display for TableType {
419 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
420 if let Some(maximum) = self.maximum {
421 write!(f, "{} ({}..{})", self.ty, self.minimum, maximum)
422 } else {
423 write!(f, "{} ({}..)", self.ty, self.minimum)
424 }
425 }
426}
427
428#[derive(
435 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
436)]
437pub struct MemoryType {
438 pub minimum: Pages,
440 pub maximum: Option<Pages>,
442 pub shared: bool,
444}
445
446impl MemoryType {
447 pub fn new<IntoPages>(minimum: IntoPages, maximum: Option<IntoPages>, shared: bool) -> Self
450 where
451 IntoPages: Into<Pages>,
452 {
453 Self { minimum: minimum.into(), maximum: maximum.map(Into::into), shared }
454 }
455}
456
457impl fmt::Display for MemoryType {
458 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
459 let shared = if self.shared { "shared" } else { "not shared" };
460 if let Some(maximum) = self.maximum {
461 write!(f, "{} ({:?}..{:?})", shared, self.minimum, maximum)
462 } else {
463 write!(f, "{} ({:?}..)", shared, self.minimum)
464 }
465 }
466}
467
468#[derive(Debug, Clone, PartialEq, Eq, Hash)]
477pub struct Import<S = String, T = ExternType> {
478 module: S,
479 name: S,
480 index: u32,
481 ty: T,
482}
483
484impl<S: AsRef<str>, T> Import<S, T> {
485 pub fn new(module: S, name: S, index: u32, ty: T) -> Self {
488 Self { module, name, index, ty }
489 }
490
491 pub fn module(&self) -> &str {
493 self.module.as_ref()
494 }
495
496 pub fn name(&self) -> &str {
499 self.name.as_ref()
500 }
501
502 pub fn index(&self) -> u32 {
504 self.index
505 }
506
507 pub fn ty(&self) -> &T {
509 &self.ty
510 }
511}
512
513#[derive(Debug, Clone, PartialEq, Eq, Hash)]
525pub struct ExportType<T = ExternType> {
526 name: String,
527 ty: T,
528}
529
530impl<T> ExportType<T> {
531 pub fn new(name: &str, ty: T) -> Self {
534 Self { name: name.to_string(), ty }
535 }
536
537 pub fn name(&self) -> &str {
539 &self.name
540 }
541
542 pub fn ty(&self) -> &T {
544 &self.ty
545 }
546}
547
548#[repr(C)]
551#[derive(Debug, Clone, PartialEq, Eq)]
552pub struct FastGasCounter {
553 pub burnt_gas: u64,
560 pub gas_limit: u64,
562}
563
564impl FastGasCounter {
565 pub fn new(limit: u64) -> Self {
567 Self { burnt_gas: 0, gas_limit: limit }
568 }
569 pub fn burnt(&self) -> u64 {
571 self.burnt_gas
572 }
573}
574
575impl fmt::Display for FastGasCounter {
576 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
577 write!(f, "burnt: {} limit: {} ", self.burnt(), self.gas_limit,)
578 }
579}
580
581#[derive(Clone)]
583pub struct InstanceConfig {
584 pub gas_counter: *mut FastGasCounter,
586 default_gas_counter: Option<Rc<UnsafeCell<FastGasCounter>>>,
587 pub stack_limit: u32,
589}
590
591impl InstanceConfig {
592 pub fn with_stack_limit(stack_limit: u32) -> Self {
594 let result = Rc::new(UnsafeCell::new(FastGasCounter { burnt_gas: 0, gas_limit: u64::MAX }));
595 Self { gas_counter: result.get(), default_gas_counter: Some(result), stack_limit }
596 }
597
598 pub unsafe fn with_counter(mut self, gas_counter: *mut FastGasCounter) -> Self {
602 self.gas_counter = gas_counter;
603 self.default_gas_counter = None;
604 self
605 }
606}
607
608#[cfg(test)]
609mod tests {
610 use super::*;
611
612 const VOID_TO_VOID: ([Type; 0], [Type; 0]) = ([], []);
613 const I32_I32_TO_VOID: ([Type; 2], [Type; 0]) = ([Type::I32, Type::I32], []);
614 const V128_I64_TO_I32: ([Type; 2], [Type; 1]) = ([Type::V128, Type::I64], [Type::I32]);
615 const NINE_V128_TO_NINE_I32: ([Type; 9], [Type; 9]) = ([Type::V128; 9], [Type::I32; 9]);
616
617 #[test]
618 fn convert_tuple_to_functiontype() {
619 let ty: FunctionType = VOID_TO_VOID.into();
620 assert_eq!(ty.params().len(), 0);
621 assert_eq!(ty.results().len(), 0);
622
623 let ty: FunctionType = I32_I32_TO_VOID.into();
624 assert_eq!(ty.params().len(), 2);
625 assert_eq!(ty.params()[0], Type::I32);
626 assert_eq!(ty.params()[1], Type::I32);
627 assert_eq!(ty.results().len(), 0);
628
629 let ty: FunctionType = V128_I64_TO_I32.into();
630 assert_eq!(ty.params().len(), 2);
631 assert_eq!(ty.params()[0], Type::V128);
632 assert_eq!(ty.params()[1], Type::I64);
633 assert_eq!(ty.results().len(), 1);
634 assert_eq!(ty.results()[0], Type::I32);
635
636 let ty: FunctionType = NINE_V128_TO_NINE_I32.into();
637 assert_eq!(ty.params().len(), 9);
638 assert_eq!(ty.results().len(), 9);
639 }
640}