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
use core::fmt::{Debug, Display};

use alloc::string::{String, ToString};
use wasmparser::Encoding;

#[derive(Debug)]
/// Errors that can occur when parsing a WebAssembly module
pub enum ParseError {
    /// An invalid type was encountered
    InvalidType,
    /// An unsupported section was encountered
    UnsupportedSection(String),
    /// A duplicate section was encountered
    DuplicateSection(String),
    /// An empty section was encountered
    EmptySection(String),
    /// An unsupported operator was encountered
    UnsupportedOperator(String),
    /// An error occurred while parsing the module
    ParseError {
        /// The error message
        message: String,
        /// The offset in the module where the error occurred
        offset: usize,
    },
    /// An invalid encoding was encountered
    InvalidEncoding(Encoding),
    /// An invalid local count was encountered
    InvalidLocalCount {
        /// The expected local count
        expected: u32,
        /// The actual local count
        actual: u32,
    },
    /// The end of the module was not reached
    EndNotReached,
    /// An unknown error occurred
    Other(String),
}

impl Display for ParseError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            Self::InvalidType => write!(f, "invalid type"),
            Self::UnsupportedSection(section) => write!(f, "unsupported section: {}", section),
            Self::DuplicateSection(section) => write!(f, "duplicate section: {}", section),
            Self::EmptySection(section) => write!(f, "empty section: {}", section),
            Self::UnsupportedOperator(operator) => write!(f, "unsupported operator: {}", operator),
            Self::ParseError { message, offset } => {
                write!(f, "error parsing module: {} at offset {}", message, offset)
            }
            Self::InvalidEncoding(encoding) => write!(f, "invalid encoding: {:?}", encoding),
            Self::InvalidLocalCount { expected, actual } => {
                write!(f, "invalid local count: expected {}, actual {}", expected, actual)
            }
            Self::EndNotReached => write!(f, "end of module not reached"),
            Self::Other(message) => write!(f, "unknown error: {}", message),
        }
    }
}

#[cfg(any(feature = "std", all(not(feature = "std"), nightly)))]
impl crate::std::error::Error for ParseError {}

impl From<wasmparser::BinaryReaderError> for ParseError {
    fn from(value: wasmparser::BinaryReaderError) -> Self {
        Self::ParseError { message: value.message().to_string(), offset: value.offset() }
    }
}

pub(crate) type Result<T, E = ParseError> = core::result::Result<T, E>;