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!(
43 self,
44 Self::I32 | Self::I64 | Self::F32 | Self::F64 | Self::V128
45 )
46 }
47
48 pub fn is_ref(self) -> bool {
50 matches!(self, Self::ExternRef | Self::FuncRef)
51 }
52}
53
54impl fmt::Display for Type {
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56 write!(f, "{:?}", self)
57 }
58}
59
60#[derive(
61 Copy, Clone, Debug, Eq, PartialEq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
62)]
63#[archive(as = "Self")]
64pub struct V128(pub(crate) [u8; 16]);
66
67impl V128 {
68 pub fn bytes(&self) -> &[u8; 16] {
70 &self.0
71 }
72 pub fn iter(&self) -> impl Iterator<Item = &u8> {
74 self.0.iter()
75 }
76
77 pub fn to_vec(self) -> Vec<u8> {
79 self.0.to_vec()
80 }
81
82 pub fn as_slice(&self) -> &[u8] {
84 &self.0[..]
85 }
86}
87
88impl From<[u8; 16]> for V128 {
89 fn from(array: [u8; 16]) -> Self {
90 Self(array)
91 }
92}
93
94impl From<&[u8]> for V128 {
95 fn from(slice: &[u8]) -> Self {
96 assert_eq!(slice.len(), 16);
97 let mut buffer = [0; 16];
98 buffer.copy_from_slice(slice);
99 Self(buffer)
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq, Hash)]
111pub enum ExternType {
112 Function(FunctionType),
114 Global(GlobalType),
116 Table(TableType),
118 Memory(MemoryType),
120}
121
122macro_rules! accessors {
123 ($(($variant:ident($ty:ty) $get:ident $unwrap:ident))*) => ($(
124 pub fn $get(&self) -> Option<&$ty> {
127 if let Self::$variant(e) = self {
128 Some(e)
129 } else {
130 None
131 }
132 }
133
134 pub fn $unwrap(&self) -> &$ty {
141 self.$get().expect(concat!("expected ", stringify!($ty)))
142 }
143 )*)
144}
145
146impl ExternType {
147 accessors! {
148 (Function(FunctionType) func unwrap_func)
149 (Global(GlobalType) global unwrap_global)
150 (Table(TableType) table unwrap_table)
151 (Memory(MemoryType) memory unwrap_memory)
152 }
153}
154
155#[derive(Debug, Clone, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)]
162pub struct FunctionType {
163 params: Arc<[Type]>,
165 results: Arc<[Type]>,
167}
168
169impl FunctionType {
170 pub fn new<Params, Returns>(params: Params, returns: Returns) -> Self
172 where
173 Params: Into<Arc<[Type]>>,
174 Returns: Into<Arc<[Type]>>,
175 {
176 Self {
177 params: params.into(),
178 results: returns.into(),
179 }
180 }
181
182 pub fn params(&self) -> &[Type] {
184 &self.params
185 }
186
187 pub fn results(&self) -> &[Type] {
189 &self.results
190 }
191}
192
193impl fmt::Display for FunctionType {
194 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
195 let params = self
196 .params
197 .iter()
198 .map(|p| format!("{:?}", p))
199 .collect::<Vec<_>>()
200 .join(", ");
201 let results = self
202 .results
203 .iter()
204 .map(|p| format!("{:?}", p))
205 .collect::<Vec<_>>()
206 .join(", ");
207 write!(f, "[{}] -> [{}]", params, results)
208 }
209}
210
211macro_rules! implement_from_pair_to_functiontype {
214 ($($N:literal,$M:literal)+) => {
215 $(
216 impl From<([Type; $N], [Type; $M])> for FunctionType {
217 fn from(pair: ([Type; $N], [Type; $M])) -> Self {
218 Self::new(&pair.0[..], &pair.1[..])
219 }
220 }
221 )+
222 }
223}
224
225implement_from_pair_to_functiontype! {
226 0,0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9
227 1,0 1,1 1,2 1,3 1,4 1,5 1,6 1,7 1,8 1,9
228 2,0 2,1 2,2 2,3 2,4 2,5 2,6 2,7 2,8 2,9
229 3,0 3,1 3,2 3,3 3,4 3,5 3,6 3,7 3,8 3,9
230 4,0 4,1 4,2 4,3 4,4 4,5 4,6 4,7 4,8 4,9
231 5,0 5,1 5,2 5,3 5,4 5,5 5,6 5,7 5,8 5,9
232 6,0 6,1 6,2 6,3 6,4 6,5 6,6 6,7 6,8 6,9
233 7,0 7,1 7,2 7,3 7,4 7,5 7,6 7,7 7,8 7,9
234 8,0 8,1 8,2 8,3 8,4 8,5 8,6 8,7 8,8 8,9
235 9,0 9,1 9,2 9,3 9,4 9,5 9,6 9,7 9,8 9,9
236}
237
238impl From<&FunctionType> for FunctionType {
239 fn from(as_ref: &FunctionType) -> Self {
240 as_ref.clone()
241 }
242}
243
244pub struct FunctionTypeRef<'a> {
246 params: &'a [Type],
248 results: &'a [Type],
250}
251
252impl<'a> FunctionTypeRef<'a> {
253 pub fn new(params: &'a [Type], results: &'a [Type]) -> Self {
255 Self { params, results }
256 }
257
258 pub fn params(&self) -> &[Type] {
260 self.params
261 }
262
263 pub fn results(&self) -> &[Type] {
265 self.results
266 }
267}
268
269impl<'a> From<&'a FunctionType> for FunctionTypeRef<'a> {
270 fn from(FunctionType { params, results }: &'a FunctionType) -> Self {
271 Self { params, results }
272 }
273}
274
275impl<'a> From<&'a ArchivedFunctionType> for FunctionTypeRef<'a> {
276 fn from(ArchivedFunctionType { params, results }: &'a ArchivedFunctionType) -> Self {
277 Self {
278 params: &**params,
279 results: &**results,
280 }
281 }
282}
283
284#[derive(
286 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
287)]
288#[archive(as = "Self")]
289pub enum Mutability {
290 Const,
292 Var,
294}
295
296impl Mutability {
297 pub fn is_mutable(self) -> bool {
299 match self {
300 Self::Const => false,
301 Self::Var => true,
302 }
303 }
304}
305
306#[derive(
308 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
309)]
310#[archive(as = "Self")]
311pub struct GlobalType {
312 pub ty: Type,
314 pub mutability: Mutability,
316}
317
318impl GlobalType {
326 pub fn new(ty: Type, mutability: Mutability) -> Self {
337 Self { ty, mutability }
338 }
339}
340
341impl fmt::Display for GlobalType {
342 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
343 let mutability = match self.mutability {
344 Mutability::Const => "constant",
345 Mutability::Var => "mutable",
346 };
347 write!(f, "{} ({})", self.ty, mutability)
348 }
349}
350
351#[derive(Debug, Clone, Copy, PartialEq, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)]
353#[archive(as = "Self")]
354pub enum GlobalInit {
355 I32Const(i32),
357 I64Const(i64),
359 F32Const(f32),
361 F64Const(f64),
363 V128Const(V128),
365 GetGlobal(GlobalIndex),
367 RefNullConst,
372 RefFunc(FunctionIndex),
374}
375
376impl Eq for GlobalInit {}
377
378impl GlobalInit {
379 pub fn from_value<T: WasmValueType>(value: Value<T>) -> Self {
381 match value {
382 Value::I32(i) => Self::I32Const(i),
383 Value::I64(i) => Self::I64Const(i),
384 Value::F32(f) => Self::F32Const(f),
385 Value::F64(f) => Self::F64Const(f),
386 _ => unimplemented!("GlobalInit from_value for {:?}", value),
387 }
388 }
389 pub fn to_value<T: WasmValueType>(&self) -> Value<T> {
391 match self {
392 Self::I32Const(i) => Value::I32(*i),
393 Self::I64Const(i) => Value::I64(*i),
394 Self::F32Const(f) => Value::F32(*f),
395 Self::F64Const(f) => Value::F64(*f),
396 _ => unimplemented!("GlobalInit to_value for {:?}", self),
397 }
398 }
399}
400
401#[derive(
409 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
410)]
411pub struct TableType {
412 pub ty: Type,
414 pub minimum: u32,
416 pub maximum: Option<u32>,
418}
419
420impl TableType {
421 pub fn new(ty: Type, minimum: u32, maximum: Option<u32>) -> Self {
424 Self {
425 ty,
426 minimum,
427 maximum,
428 }
429 }
430}
431
432impl fmt::Display for TableType {
433 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
434 if let Some(maximum) = self.maximum {
435 write!(f, "{} ({}..{})", self.ty, self.minimum, maximum)
436 } else {
437 write!(f, "{} ({}..)", self.ty, self.minimum)
438 }
439 }
440}
441
442#[derive(
449 Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
450)]
451pub struct MemoryType {
452 pub minimum: Pages,
454 pub maximum: Option<Pages>,
456 pub shared: bool,
458}
459
460impl MemoryType {
461 pub fn new<IntoPages>(minimum: IntoPages, maximum: Option<IntoPages>, shared: bool) -> Self
464 where
465 IntoPages: Into<Pages>,
466 {
467 Self {
468 minimum: minimum.into(),
469 maximum: maximum.map(Into::into),
470 shared,
471 }
472 }
473}
474
475impl fmt::Display for MemoryType {
476 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
477 let shared = if self.shared { "shared" } else { "not shared" };
478 if let Some(maximum) = self.maximum {
479 write!(f, "{} ({:?}..{:?})", shared, self.minimum, maximum)
480 } else {
481 write!(f, "{} ({:?}..)", shared, self.minimum)
482 }
483 }
484}
485
486#[derive(Debug, Clone, PartialEq, Eq, Hash)]
495pub struct Import<S = String, T = ExternType> {
496 module: S,
497 name: S,
498 index: u32,
499 ty: T,
500}
501
502impl<S: AsRef<str>, T> Import<S, T> {
503 pub fn new(module: S, name: S, index: u32, ty: T) -> Self {
506 Self {
507 module,
508 name,
509 index,
510 ty,
511 }
512 }
513
514 pub fn module(&self) -> &str {
516 self.module.as_ref()
517 }
518
519 pub fn name(&self) -> &str {
522 self.name.as_ref()
523 }
524
525 pub fn index(&self) -> u32 {
527 self.index
528 }
529
530 pub fn ty(&self) -> &T {
532 &self.ty
533 }
534}
535
536#[derive(Debug, Clone, PartialEq, Eq, Hash)]
548pub struct ExportType<T = ExternType> {
549 name: String,
550 ty: T,
551}
552
553impl<T> ExportType<T> {
554 pub fn new(name: &str, ty: T) -> Self {
557 Self {
558 name: name.to_string(),
559 ty,
560 }
561 }
562
563 pub fn name(&self) -> &str {
565 &self.name
566 }
567
568 pub fn ty(&self) -> &T {
570 &self.ty
571 }
572}
573
574#[repr(C)]
576#[derive(Debug, Clone, PartialEq, Eq)]
577pub struct FastGasCounter {
578 pub burnt_gas: u64,
586 pub gas_limit: u64,
588 pub opcode_cost: u64,
590}
591
592impl FastGasCounter {
593 pub fn new(limit: u64, opcode: u64) -> Self {
595 FastGasCounter {
596 burnt_gas: 0,
597 gas_limit: limit,
598 opcode_cost: opcode,
599 }
600 }
601 pub fn burnt(&self) -> u64 {
603 self.burnt_gas
604 }
605}
606
607impl fmt::Display for FastGasCounter {
608 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
609 write!(
610 f,
611 "burnt: {} limit: {} op_cost: {} ",
612 self.burnt(),
613 self.gas_limit,
614 self.opcode_cost
615 )
616 }
617}
618
619#[derive(Clone)]
621pub struct InstanceConfig {
622 pub gas_counter: *mut FastGasCounter,
624 default_gas_counter: Option<Rc<UnsafeCell<FastGasCounter>>>,
625 pub stack_limit: i32,
627}
628
629const DEFAULT_STACK_LIMIT: i32 = 100 * 1024;
631
632impl InstanceConfig {
633 pub fn default() -> Self {
635 let result = Rc::new(UnsafeCell::new(FastGasCounter {
636 burnt_gas: 0,
637 gas_limit: u64::MAX,
638 opcode_cost: 0,
639 }));
640 Self {
641 gas_counter: result.get(),
642 default_gas_counter: Some(result),
643 stack_limit: DEFAULT_STACK_LIMIT,
644 }
645 }
646
647 pub unsafe fn with_counter(mut self, gas_counter: *mut FastGasCounter) -> Self {
651 self.gas_counter = gas_counter;
652 self.default_gas_counter = None;
653 self
654 }
655
656 pub unsafe fn with_stack_limit(mut self, stack_limit: i32) -> Self {
658 self.stack_limit = stack_limit;
659 self
660 }
661}
662
663#[cfg(test)]
664mod tests {
665 use super::*;
666
667 const VOID_TO_VOID: ([Type; 0], [Type; 0]) = ([], []);
668 const I32_I32_TO_VOID: ([Type; 2], [Type; 0]) = ([Type::I32, Type::I32], []);
669 const V128_I64_TO_I32: ([Type; 2], [Type; 1]) = ([Type::V128, Type::I64], [Type::I32]);
670 const NINE_V128_TO_NINE_I32: ([Type; 9], [Type; 9]) = ([Type::V128; 9], [Type::I32; 9]);
671
672 #[test]
673 fn convert_tuple_to_functiontype() {
674 let ty: FunctionType = VOID_TO_VOID.into();
675 assert_eq!(ty.params().len(), 0);
676 assert_eq!(ty.results().len(), 0);
677
678 let ty: FunctionType = I32_I32_TO_VOID.into();
679 assert_eq!(ty.params().len(), 2);
680 assert_eq!(ty.params()[0], Type::I32);
681 assert_eq!(ty.params()[1], Type::I32);
682 assert_eq!(ty.results().len(), 0);
683
684 let ty: FunctionType = V128_I64_TO_I32.into();
685 assert_eq!(ty.params().len(), 2);
686 assert_eq!(ty.params()[0], Type::V128);
687 assert_eq!(ty.params()[1], Type::I64);
688 assert_eq!(ty.results().len(), 1);
689 assert_eq!(ty.results()[0], Type::I32);
690
691 let ty: FunctionType = NINE_V128_TO_NINE_I32.into();
692 assert_eq!(ty.params().len(), 9);
693 assert_eq!(ty.results().len(), 9);
694 }
695}