1use alloc::vec::Vec;
16use core::ops::Deref;
17
18use num_enum::{TryFromPrimitive, UnsafeFromPrimitive};
19
20use crate::error::*;
21
22#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, UnsafeFromPrimitive)]
23#[repr(u8)]
24pub enum NumType {
25 I32 = 0x7f,
26 I64 = 0x7e,
27 F32 = 0x7d,
28 F64 = 0x7c,
29}
30
31#[allow(dead_code)] #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, UnsafeFromPrimitive)]
33#[repr(u8)]
34pub enum VecType {
35 V128 = 0x7b,
36}
37
38#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, UnsafeFromPrimitive)]
39#[repr(u8)]
40pub enum RefType {
41 FuncRef = 0x70,
42 ExternRef = 0x6f,
43}
44
45impl RefType {
46 pub(crate) fn is_unsupported(byte: u8) -> Option<Unsupported> {
47 match byte {
48 0x6f | 0x70 => None,
49 0x63 | 0x64 | 0x69 ..= 0x74 => Some(if_debug!(Unsupported::HeapType)),
52 _ => None,
53 }
54 }
55}
56
57#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, UnsafeFromPrimitive)]
58#[repr(u8)]
59pub enum ValType {
60 I32 = 0x7f,
61 I64 = 0x7e,
62 F32 = 0x7d,
63 F64 = 0x7c,
64 V128 = 0x7b,
65 FuncRef = 0x70,
66 ExternRef = 0x6f,
67}
68
69impl ValType {
70 pub(crate) fn is_unsupported(byte: u8) -> Option<Unsupported> {
71 RefType::is_unsupported(byte)
72 }
73}
74
75#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
76pub struct ResultType<'m>(&'m [ValType]);
77
78#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
79pub struct FuncType<'m> {
80 pub params: ResultType<'m>,
81 pub results: ResultType<'m>,
82}
83
84#[derive(Debug, Copy, Clone, PartialEq, Eq)]
85pub struct Limits {
86 pub min: u32,
87 pub max: u32,
88}
89
90pub const TABLE_MAX: u32 = u32::MAX;
91pub const MEM_MAX: u32 = 0x10000;
92
93impl Limits {
94 pub fn valid(&self, k: u32) -> bool {
95 self.min <= self.max && self.max <= k
96 }
97
98 pub fn matches(self, other: Limits) -> bool {
99 self.min >= other.min && self.max <= other.max
100 }
101}
102
103pub type MemType = Limits;
104
105#[derive(Debug, Copy, Clone, PartialEq, Eq)]
106pub struct TableType {
107 pub limits: Limits,
108 pub item: RefType,
109}
110
111#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, UnsafeFromPrimitive)]
112#[repr(u8)]
113pub enum Mut {
114 Const = 0,
115 Var = 1,
116}
117
118#[derive(Debug, Copy, Clone, PartialEq, Eq)]
119pub struct GlobalType {
120 pub mutable: Mut,
121 pub value: ValType,
122}
123
124#[derive(Debug, Copy, Clone, PartialEq, Eq)]
125pub enum Sx {
126 U,
127 S,
128}
129
130#[derive(Debug, Copy, Clone, PartialEq, Eq)]
131pub enum Nx {
132 N32,
133 N64,
134}
135
136#[derive(Debug, Copy, Clone, PartialEq, Eq)]
137pub enum Bx {
138 N32B8,
139 N32B16,
140 N64B8,
141 N64B16,
142 N64B32,
143}
144
145#[derive(Debug, Clone, PartialEq, Eq)]
146pub enum ITestOp {
147 Eqz,
148}
149
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub enum IRelOp {
152 Eq,
153 Ne,
154 Lt(Sx),
155 Gt(Sx),
156 Le(Sx),
157 Ge(Sx),
158}
159
160#[derive(Debug, Clone, PartialEq, Eq)]
161pub enum IUnOp {
162 Clz,
163 Ctz,
164 PopCnt,
165}
166
167#[derive(Debug, Clone, PartialEq, Eq)]
168pub enum IBinOp {
169 Add,
170 Sub,
171 Mul,
172 Div(Sx),
173 Rem(Sx),
174 And,
175 Or,
176 Xor,
177 Shl,
178 Shr(Sx),
179 Rotl,
180 Rotr,
181}
182
183#[cfg(feature = "float-types")]
184#[derive(Debug, Clone, PartialEq, Eq)]
185pub enum FRelOp {
186 Eq,
187 Ne,
188 Lt,
189 Gt,
190 Le,
191 Ge,
192}
193
194#[cfg(feature = "float-types")]
195#[derive(Debug, Clone, PartialEq, Eq)]
196pub enum FUnOp {
197 Abs,
198 Neg,
199 Ceil,
200 Floor,
201 Trunc,
202 Nearest,
203 Sqrt,
204}
205
206#[cfg(feature = "float-types")]
207#[derive(Debug, Clone, PartialEq, Eq)]
208pub enum FBinOp {
209 Add,
210 Sub,
211 Mul,
212 Div,
213 Min,
214 Max,
215 CopySign,
216}
217
218#[derive(Debug, Clone, PartialEq, Eq)]
219pub enum CvtOp {
220 Wrap,
221 Extend(Sx),
222 #[cfg(feature = "float-types")]
223 Trunc(Nx, Nx, Sx),
224 #[cfg(feature = "float-types")]
225 TruncSat(Nx, Nx, Sx),
226 #[cfg(feature = "float-types")]
227 Convert(Nx, Nx, Sx),
228 #[cfg(feature = "float-types")]
229 Demote,
230 #[cfg(feature = "float-types")]
231 Promote,
232 #[cfg(feature = "float-types")]
233 IReinterpret(Nx),
234 #[cfg(feature = "float-types")]
235 FReinterpret(Nx),
236}
237
238#[derive(Debug, Clone, PartialEq, Eq)]
239pub enum Instr<'m> {
240 Unreachable,
241 Nop,
242 Block(BlockType),
243 Loop(BlockType),
244 If(BlockType),
245 Else,
246 End,
247 Br(LabelIdx),
248 BrIf(LabelIdx),
249 BrTable(Vec<LabelIdx>, LabelIdx),
250 Return,
251 Call(FuncIdx),
252 CallIndirect(TableIdx, TypeIdx), Drop,
254 Select(Option<ResultType<'m>>),
255 LocalGet(LocalIdx),
256 LocalSet(LocalIdx),
257 LocalTee(LocalIdx),
258 GlobalGet(GlobalIdx),
259 GlobalSet(GlobalIdx),
260 TableGet(TableIdx),
261 TableSet(TableIdx),
262 ILoad(Nx, MemArg),
263 #[cfg(feature = "float-types")]
264 FLoad(Nx, MemArg),
265 ILoad_(Bx, Sx, MemArg),
266 IStore(Nx, MemArg),
267 #[cfg(feature = "float-types")]
268 FStore(Nx, MemArg),
269 IStore_(Bx, MemArg),
270 MemorySize,
271 MemoryGrow,
272 I32Const(u32),
273 I64Const(u64),
274 #[cfg(feature = "float-types")]
275 F32Const(u32),
276 #[cfg(feature = "float-types")]
277 F64Const(u64),
278 ITestOp(Nx, ITestOp),
279 IRelOp(Nx, IRelOp),
280 #[cfg(feature = "float-types")]
281 FRelOp(Nx, FRelOp),
282 IUnOp(Nx, IUnOp),
283 #[cfg(feature = "float-types")]
284 FUnOp(Nx, FUnOp),
285 IBinOp(Nx, IBinOp),
286 #[cfg(feature = "float-types")]
287 FBinOp(Nx, FBinOp),
288 CvtOp(CvtOp),
289 IExtend(Bx),
290 RefNull(RefType),
291 RefIsNull,
292 RefFunc(FuncIdx),
293 MemoryInit(DataIdx),
294 DataDrop(DataIdx),
295 MemoryCopy,
296 MemoryFill,
297 TableInit(TableIdx, ElemIdx), ElemDrop(ElemIdx),
299 TableCopy(TableIdx, TableIdx),
300 TableGrow(TableIdx),
301 TableSize(TableIdx),
302 TableFill(TableIdx),
303}
304
305pub type TypeIdx = u32;
306pub type FuncIdx = u32;
307pub type TableIdx = u32;
308pub type MemIdx = u32;
309pub type GlobalIdx = u32;
310pub type ElemIdx = u32;
311pub type DataIdx = u32;
312pub type LocalIdx = u32;
313pub type LabelIdx = u32;
314
315#[derive(Debug, Clone, PartialEq, Eq)]
316pub enum ExportDesc {
317 Func(FuncIdx),
318 Table(TableIdx),
319 Mem(MemIdx),
320 Global(GlobalIdx),
321}
322
323#[derive(Debug, Clone, PartialEq, Eq)]
324pub enum ImportDesc {
325 Func(TypeIdx),
326 Table(TableType),
327 Mem(MemType),
328 Global(GlobalType),
329}
330
331#[derive(Debug, Clone)]
332pub struct Import<'m> {
333 pub module: &'m str,
334 pub name: &'m str,
335 pub desc: ImportDesc,
336}
337
338#[derive(Debug, Clone, PartialEq, Eq)]
339pub enum ExternType<'m> {
340 Func(FuncType<'m>),
341 Table(TableType),
342 Mem(MemType),
343 Global(GlobalType),
344}
345
346impl<'m> ExternType<'m> {
347 pub fn matches(&self, other: &ExternType<'m>) -> bool {
348 match (self, other) {
349 (ExternType::Func(x), ExternType::Func(y)) => x == y,
350 (
351 ExternType::Table(TableType { limits: t, item: x }),
352 ExternType::Table(TableType { limits: s, item: y }),
353 ) => t.matches(*s) && x == y,
354 (ExternType::Mem(t), ExternType::Mem(s)) => t.matches(*s),
355 (ExternType::Global(x), ExternType::Global(y)) => x == y,
356 _ => false,
357 }
358 }
359}
360
361#[derive(Debug, Clone, PartialEq, Eq)]
362pub enum BlockType {
363 None,
364 Type(ValType),
365 Index(TypeIdx),
366}
367
368#[derive(Debug, Copy, Clone, PartialEq, Eq)]
369pub struct MemArg {
370 pub align: u32,
371 pub offset: u32,
372}
373
374#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, UnsafeFromPrimitive)]
375#[repr(u8)]
376pub enum SectionId {
377 Custom = 0,
378 Type = 1,
379 Import = 2,
380 Function = 3,
381 Table = 4,
382 Memory = 5,
383 Global = 6,
384 Export = 7,
385 Start = 8,
386 Element = 9,
387 Code = 10,
388 Data = 11,
389 DataCount = 12,
390 Tag = 13,
391}
392
393impl Deref for ResultType<'_> {
394 type Target = [ValType];
395
396 fn deref(&self) -> &Self::Target {
397 self.0
398 }
399}
400
401impl<'m> From<&'m [ValType]> for ResultType<'m> {
402 fn from(xs: &'m [ValType]) -> Self {
403 Self(xs)
404 }
405}
406
407impl From<ValType> for ResultType<'_> {
408 fn from(x: ValType) -> Self {
409 macro_rules! make {
410 ($($x:ident),*) => {{
411 static VAL_TYPES: &[ValType] = &[$(ValType::$x),*];
412 make!([][0][$($x)*])
413 }};
414 ([$($output:tt)*][$i:expr][]) => {
415 Self(match x { $($output)* })
416 };
417 ([$($output:tt)*][$i:expr][$x:ident $($input:ident)*]) => {
418 make!([$($output)* ValType::$x => core::slice::from_ref(&VAL_TYPES[$i]),]
419 [$i + 1][$($input)*])
420 };
421 }
422 make!(I32, I64, F32, F64, V128, FuncRef, ExternRef)
423 }
424}
425
426impl From<()> for ResultType<'_> {
427 fn from(_: ()) -> Self {
428 Self(&[])
429 }
430}
431
432impl NumType {
433 pub fn i(n: Nx) -> Self {
434 match n {
435 Nx::N32 => NumType::I32,
436 Nx::N64 => NumType::I64,
437 }
438 }
439
440 #[cfg(feature = "float-types")]
441 pub fn f(n: Nx) -> Self {
442 match n {
443 Nx::N32 => NumType::F32,
444 Nx::N64 => NumType::F64,
445 }
446 }
447}
448
449impl From<Nx> for usize {
450 fn from(x: Nx) -> Self {
451 match x {
452 Nx::N32 => 32,
453 Nx::N64 => 64,
454 }
455 }
456}
457
458impl From<Bx> for Nx {
459 fn from(x: Bx) -> Self {
460 match x {
461 Bx::N32B8 | Bx::N32B16 => Nx::N32,
462 Bx::N64B8 | Bx::N64B16 | Bx::N64B32 => Nx::N64,
463 }
464 }
465}
466
467impl From<Bx> for usize {
468 fn from(x: Bx) -> Self {
469 match x {
470 Bx::N32B8 | Bx::N64B8 => 8,
471 Bx::N32B16 | Bx::N64B16 => 16,
472 Bx::N64B32 => 32,
473 }
474 }
475}
476
477impl CvtOp {
478 pub fn dst(&self) -> NumType {
479 match *self {
480 CvtOp::Wrap => NumType::I32,
481 CvtOp::Extend(_) => NumType::I64,
482 #[cfg(feature = "float-types")]
483 CvtOp::Trunc(n, _, _) => NumType::i(n),
484 #[cfg(feature = "float-types")]
485 CvtOp::TruncSat(n, _, _) => NumType::i(n),
486 #[cfg(feature = "float-types")]
487 CvtOp::Convert(n, _, _) => NumType::f(n),
488 #[cfg(feature = "float-types")]
489 CvtOp::Demote => NumType::F32,
490 #[cfg(feature = "float-types")]
491 CvtOp::Promote => NumType::F64,
492 #[cfg(feature = "float-types")]
493 CvtOp::IReinterpret(n) => NumType::i(n),
494 #[cfg(feature = "float-types")]
495 CvtOp::FReinterpret(n) => NumType::f(n),
496 }
497 }
498
499 pub fn src(&self) -> NumType {
500 match *self {
501 CvtOp::Wrap => NumType::I64,
502 CvtOp::Extend(_) => NumType::I32,
503 #[cfg(feature = "float-types")]
504 CvtOp::Trunc(_, m, _) => NumType::f(m),
505 #[cfg(feature = "float-types")]
506 CvtOp::TruncSat(_, m, _) => NumType::f(m),
507 #[cfg(feature = "float-types")]
508 CvtOp::Convert(_, m, _) => NumType::i(m),
509 #[cfg(feature = "float-types")]
510 CvtOp::Demote => NumType::F64,
511 #[cfg(feature = "float-types")]
512 CvtOp::Promote => NumType::F32,
513 #[cfg(feature = "float-types")]
514 CvtOp::IReinterpret(n) => NumType::f(n),
515 #[cfg(feature = "float-types")]
516 CvtOp::FReinterpret(n) => NumType::i(n),
517 }
518 }
519}
520
521macro_rules! impl_op {
522 ($n:ident, $u:ident, $i:ident, $f:ident) => {
523 impl ITestOp {
524 pub fn $n(&self, x: $u) -> bool {
525 match self {
526 ITestOp::Eqz => x == 0,
527 }
528 }
529 }
530
531 impl IRelOp {
532 pub fn $n(&self, x: $u, y: $u) -> bool {
533 match self {
534 IRelOp::Eq => x == y,
535 IRelOp::Ne => x != y,
536 IRelOp::Lt(Sx::U) => x < y,
537 IRelOp::Lt(Sx::S) => (x as $i) < (y as $i),
538 IRelOp::Gt(Sx::U) => x > y,
539 IRelOp::Gt(Sx::S) => (x as $i) > (y as $i),
540 IRelOp::Le(Sx::U) => x <= y,
541 IRelOp::Le(Sx::S) => (x as $i) <= (y as $i),
542 IRelOp::Ge(Sx::U) => x >= y,
543 IRelOp::Ge(Sx::S) => (x as $i) >= (y as $i),
544 }
545 }
546 }
547
548 impl IUnOp {
549 pub fn $n(&self, x: $u) -> Option<$u> {
550 Some(match self {
551 IUnOp::Clz => x.leading_zeros(),
552 IUnOp::Ctz => x.trailing_zeros(),
553 IUnOp::PopCnt => x.count_ones(),
554 } as $u)
555 }
556 }
557
558 impl IBinOp {
559 pub fn $n(&self, x: $u, y: $u) -> Option<$u> {
560 match self {
561 IBinOp::Add => Some(x.wrapping_add(y)),
562 IBinOp::Sub => Some(x.wrapping_sub(y)),
563 IBinOp::Mul => Some(x.wrapping_mul(y)),
564 IBinOp::Div(Sx::U) => x.checked_div(y),
565 IBinOp::Div(Sx::S) => (x as $i).checked_div(y as $i).map(|z| z as $u),
566 IBinOp::Rem(Sx::U) => x.checked_rem(y),
567 IBinOp::Rem(Sx::S) if y == 0 => None,
568 IBinOp::Rem(Sx::S) => Some((x as $i).wrapping_rem(y as $i) as $u),
569 IBinOp::And => Some(x & y),
570 IBinOp::Or => Some(x | y),
571 IBinOp::Xor => Some(x ^ y),
572 IBinOp::Shl => Some(x.wrapping_shl(y as u32)),
573 IBinOp::Shr(Sx::U) => Some(x.wrapping_shr(y as u32)),
574 IBinOp::Shr(Sx::S) => Some((x as $i).wrapping_shr(y as u32) as $u),
575 IBinOp::Rotl => Some(x.rotate_left(y as u32)),
576 IBinOp::Rotr => Some(x.rotate_right(y as u32)),
577 }
578 }
579 }
580
581 #[cfg(feature = "float-types")]
582 impl FRelOp {
583 pub fn $n(&self, x: $u, y: $u) -> bool {
584 let x = $f::from_bits(x);
585 let y = $f::from_bits(y);
586 match self {
587 FRelOp::Eq => x == y,
588 FRelOp::Ne => x != y,
589 FRelOp::Lt => x < y,
590 FRelOp::Gt => x > y,
591 FRelOp::Le => x <= y,
592 FRelOp::Ge => x >= y,
593 }
594 }
595 }
596
597 #[cfg(feature = "float-types")]
598 impl FUnOp {
599 pub fn $n(&self, x: $u) -> $u {
600 let x = $f::from_bits(x);
601 let z = match self {
602 FUnOp::Abs => float::$f::abs(x),
603 FUnOp::Neg => -x,
604 FUnOp::Ceil => float::$f::ceil(x),
605 FUnOp::Floor => float::$f::floor(x),
606 FUnOp::Trunc => float::$f::trunc(x),
607 FUnOp::Nearest => {
608 let round = float::$f::round(x);
609 if float::$f::abs(x - round) == 0.5 {
610 match round % 2. {
611 r if r == 1. => float::$f::floor(x),
612 r if r == -1. => float::$f::ceil(x),
613 r if r == 0. => round,
614 _ => unreachable!(),
615 }
616 } else {
617 round
618 }
619 }
620 FUnOp::Sqrt => float::$f::sqrt(x),
621 };
622 z.to_bits()
623 }
624 }
625
626 #[cfg(feature = "float-types")]
627 impl FBinOp {
628 pub fn $n(&self, x_: $u, y_: $u) -> $u {
629 let x = $f::from_bits(x_);
630 let y = $f::from_bits(y_);
631 let z = match self {
632 FBinOp::Add => x + y,
633 FBinOp::Sub => x - y,
634 FBinOp::Mul => x * y,
635 FBinOp::Div => x / y,
636 FBinOp::Min => x.minimum(y),
637 FBinOp::Max => x.maximum(y),
638 FBinOp::CopySign => {
639 const M: $u = 1 << ($u::BITS - 1);
640 return (x_ & !M) | (y_ & M);
641 }
642 };
643 z.to_bits()
644 }
645 }
646 };
647}
648impl_op!(n32, u32, i32, f32);
649impl_op!(n64, u64, i64, f64);
650
651#[cfg(feature = "float-types")]
652#[allow(non_upper_case_globals)]
653mod float {
654 pub mod f32 {
655 pub const abs: fn(f32) -> f32 = libm::fabsf;
656 pub const ceil: fn(f32) -> f32 = libm::ceilf;
657 pub const floor: fn(f32) -> f32 = libm::floorf;
658 pub const round: fn(f32) -> f32 = libm::roundf;
659 pub const sqrt: fn(f32) -> f32 = libm::sqrtf;
660 pub const trunc: fn(f32) -> f32 = libm::truncf;
661 }
662
663 pub mod f64 {
664 pub const abs: fn(f64) -> f64 = libm::fabs;
665 pub const ceil: fn(f64) -> f64 = libm::ceil;
666 pub const floor: fn(f64) -> f64 = libm::floor;
667 pub const round: fn(f64) -> f64 = libm::round;
668 pub const sqrt: fn(f64) -> f64 = libm::sqrt;
669 pub const trunc: fn(f64) -> f64 = libm::trunc;
670 }
671}
672
673impl From<u8> for Sx {
674 fn from(x: u8) -> Self {
675 match x {
676 0 => Sx::S,
677 1 => Sx::U,
678 _ => unreachable!(),
679 }
680 }
681}
682
683impl From<u8> for Nx {
684 fn from(x: u8) -> Self {
685 match x {
686 0 => Nx::N32,
687 1 => Nx::N64,
688 _ => unreachable!(),
689 }
690 }
691}
692
693impl From<u8> for Bx {
694 fn from(x: u8) -> Self {
695 match x {
696 0 => Bx::N32B8,
697 1 => Bx::N32B16,
698 2 => Bx::N64B8,
699 3 => Bx::N64B16,
700 4 => Bx::N64B32,
701 _ => unreachable!(),
702 }
703 }
704}
705
706impl From<u8> for IRelOp {
707 fn from(x: u8) -> Self {
708 match x {
709 0 => IRelOp::Eq,
710 1 => IRelOp::Ne,
711 x @ 2 ..= 3 => IRelOp::Lt((x - 2).into()),
712 x @ 4 ..= 5 => IRelOp::Gt((x - 4).into()),
713 x @ 6 ..= 7 => IRelOp::Le((x - 6).into()),
714 x @ 8 ..= 9 => IRelOp::Ge((x - 8).into()),
715 _ => unreachable!(),
716 }
717 }
718}
719
720impl From<u8> for IUnOp {
721 fn from(x: u8) -> Self {
722 match x {
723 0 => IUnOp::Clz,
724 1 => IUnOp::Ctz,
725 2 => IUnOp::PopCnt,
726 _ => unreachable!(),
727 }
728 }
729}
730
731impl From<u8> for IBinOp {
732 fn from(x: u8) -> Self {
733 match x {
734 0 => IBinOp::Add,
735 1 => IBinOp::Sub,
736 2 => IBinOp::Mul,
737 x @ 3 ..= 4 => IBinOp::Div((x - 3).into()),
738 x @ 5 ..= 6 => IBinOp::Rem((x - 5).into()),
739 7 => IBinOp::And,
740 8 => IBinOp::Or,
741 9 => IBinOp::Xor,
742 10 => IBinOp::Shl,
743 x @ 11 ..= 12 => IBinOp::Shr((x - 11).into()),
744 13 => IBinOp::Rotl,
745 14 => IBinOp::Rotr,
746 _ => unreachable!(),
747 }
748 }
749}
750
751#[cfg(feature = "float-types")]
752impl From<u8> for FRelOp {
753 fn from(x: u8) -> Self {
754 match x {
755 0 => FRelOp::Eq,
756 1 => FRelOp::Ne,
757 2 => FRelOp::Lt,
758 3 => FRelOp::Gt,
759 4 => FRelOp::Le,
760 5 => FRelOp::Ge,
761 _ => unreachable!(),
762 }
763 }
764}
765
766#[cfg(feature = "float-types")]
767impl From<u8> for FUnOp {
768 fn from(x: u8) -> Self {
769 match x {
770 0 => FUnOp::Abs,
771 1 => FUnOp::Neg,
772 2 => FUnOp::Ceil,
773 3 => FUnOp::Floor,
774 4 => FUnOp::Trunc,
775 5 => FUnOp::Nearest,
776 6 => FUnOp::Sqrt,
777 _ => unreachable!(),
778 }
779 }
780}
781
782#[cfg(feature = "float-types")]
783impl From<u8> for FBinOp {
784 fn from(x: u8) -> Self {
785 match x {
786 0 => FBinOp::Add,
787 1 => FBinOp::Sub,
788 2 => FBinOp::Mul,
789 3 => FBinOp::Div,
790 4 => FBinOp::Min,
791 5 => FBinOp::Max,
792 6 => FBinOp::CopySign,
793 _ => unreachable!(),
794 }
795 }
796}
797
798impl SectionId {
799 pub fn order(self) -> u8 {
800 match self as u8 {
802 x @ 0 ..= 5 => x,
803 13 => 6,
804 x @ 6 ..= 9 => x + 1,
805 12 => 11,
806 x @ 10 ..= 11 => x + 2,
807 _ => unreachable!(),
808 }
809 }
810}
811
812pub trait TryFromByte: Sized {
813 fn try_from_byte(byte: u8) -> Option<Self>;
814}
815
816pub trait UnsafeFromByte {
817 unsafe fn from_byte_unchecked(byte: u8) -> Self;
819}
820
821impl TryFromByte for bool {
822 fn try_from_byte(byte: u8) -> Option<Self> {
823 Some(match byte {
824 0 => false,
825 1 => true,
826 _ => return None,
827 })
828 }
829}
830
831impl UnsafeFromByte for bool {
832 unsafe fn from_byte_unchecked(byte: u8) -> Self {
833 unsafe { Self::try_from_byte(byte).unwrap_unchecked() }
834 }
835}
836
837macro_rules! impl_from_byte {
838 ($name:ident) => {
839 impl UnsafeFromByte for $name {
840 unsafe fn from_byte_unchecked(byte: u8) -> Self {
841 unsafe { Self::unchecked_transmute_from(byte) }
842 }
843 }
844 impl TryFromByte for $name {
845 fn try_from_byte(byte: u8) -> Option<Self> {
846 Self::try_from_primitive(byte).ok()
847 }
848 }
849 };
850}
851impl_from_byte!(RefType);
852impl_from_byte!(ValType);
853impl_from_byte!(Mut);
854impl_from_byte!(SectionId);