1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use thiserror::Error;
pub use wasmbin_derive::Wasmbin;
#[derive(Error, Debug)]
pub enum DecodeError {
#[error("{0}")]
Io(#[from] std::io::Error),
#[error("{0}")]
Leb128(#[from] leb128::read::Error),
#[error("{0}")]
Utf8(#[from] std::string::FromUtf8Error),
#[error("Could not recognise discriminant 0x{discriminant:X} for type {ty}")]
UnsupportedDiscriminant {
ty: &'static str,
discriminant: i128,
},
#[error("Invalid module magic signature [{actual:02X?}]")]
InvalidMagic { actual: [u8; 8] },
#[error("Unrecognized data")]
UnrecognizedData,
#[error("Section out of order: {current:?} after {prev:?}")]
SectionOutOfOrder {
current: crate::sections::Kind,
prev: crate::sections::Kind,
},
}
impl From<std::num::TryFromIntError> for DecodeError {
fn from(_err: std::num::TryFromIntError) -> Self {
DecodeError::Leb128(leb128::read::Error::Overflow)
}
}
impl From<std::convert::Infallible> for DecodeError {
fn from(err: std::convert::Infallible) -> Self {
match err {}
}
}
pub trait Encode {
fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()>;
}
pub trait Decode: Sized {
fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError>;
}
macro_rules! encode_decode_as {
($ty:ty, {
$($lhs:tt <=> $rhs:tt,)*
} $(, |$other:pat| $other_handler:expr)?) => {
impl crate::io::Encode for $ty {
#[allow(unused_parens)]
fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
match *self {
$($lhs => $rhs,)*
}.encode(w)
}
}
impl crate::io::Decode for $ty {
#[allow(unused_parens)]
fn decode(r: &mut impl std::io::Read) -> Result<Self, crate::io::DecodeError> {
Ok(match crate::io::Decode::decode(r)? {
$($rhs => $lhs,)*
$($other => return $other_handler)?
})
}
}
};
}
pub trait DecodeWithDiscriminant: Decode {
const NAME: &'static str;
type Discriminant: Decode + Copy + Into<i128>;
fn maybe_decode_with_discriminant(
discriminant: Self::Discriminant,
r: &mut impl std::io::Read,
) -> Result<Option<Self>, DecodeError>;
fn decode_with_discriminant(
discriminant: Self::Discriminant,
r: &mut impl std::io::Read,
) -> Result<Self, DecodeError> {
Self::maybe_decode_with_discriminant(discriminant, r)?.ok_or_else(|| {
DecodeError::UnsupportedDiscriminant {
ty: Self::NAME,
discriminant: discriminant.into(),
}
})
}
fn decode_without_discriminant(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
Self::decode_with_discriminant(Self::Discriminant::decode(r)?, r)
}
}