wain_syntax_binary/
error.rs

1use crate::source::describe_position;
2use std::fmt;
3use std::str::Utf8Error;
4
5#[cfg_attr(test, derive(Debug))]
6pub enum ErrorKind {
7    IntOverflow {
8        ty: &'static str,
9        got: Option<u64>,
10    },
11    UnexpectedEof {
12        expected: &'static str,
13    },
14    WasmMagicNotFound,
15    VersionMismatch([u8; 4]),
16    LengthOutOfInput {
17        input: usize,
18        specified: usize,
19        what: &'static str,
20    },
21    InvalidUtf8 {
22        what: &'static str,
23        error: Utf8Error,
24    },
25    UnexpectedByte {
26        expected: Vec<u8>,
27        got: u8,
28        what: &'static str,
29    },
30    FuncCodeLengthMismatch {
31        num_funcs: usize,
32        num_codes: usize,
33    },
34    TooManyLocalVariables(usize),
35    MalformedSectionSize {
36        name: &'static str,
37        remaining_bytes: usize,
38    },
39    MalformedCodeSize {
40        remaining_bytes: usize,
41    },
42    ExpectedEof(u8),
43}
44
45#[cfg_attr(test, derive(Debug))]
46pub struct Error<'source> {
47    pub kind: ErrorKind,
48    pub pos: usize,
49    pub source: &'source [u8],
50    pub when: &'static str,
51}
52
53impl<'s> Error<'s> {
54    pub(crate) fn new(kind: ErrorKind, pos: usize, source: &'s [u8], when: &'static str) -> Box<Error<'s>> {
55        Box::new(Error {
56            kind,
57            pos,
58            source,
59            when,
60        })
61    }
62}
63
64impl<'s> fmt::Display for Error<'s> {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        use ErrorKind::*;
67        match &self.kind {
68            IntOverflow { ty, got: Some(got) } => {
69                write!(f, "LEB128-encoded integer '{:x}' is too large for {} value", got, ty)?
70            }
71            IntOverflow { ty, got: None } => write!(f, "LEB128-encoded integer is too large for {} value", ty)?,
72            UnexpectedEof { expected } => {
73                write!(f, "expected {} but reached end of current section or input", expected)?
74            }
75            WasmMagicNotFound => write!(f, "WebAssembly binary must start with magic 0x00 0x61 0x73 0x6d")?,
76            VersionMismatch(v) => write!(f, "expected version [1, 0, 0, 0] but got {:?}", v)?,
77            LengthOutOfInput { input, specified, what } => write!(
78                f,
79                "{} ({} bytes) is larger than the rest of input ({} bytes)",
80                what, specified, input
81            )?,
82            InvalidUtf8 { what, error } => write!(f, "{} must be UTF-8 sequence: {}", what, error)?,
83            UnexpectedByte { expected, got, what } if expected.is_empty() => {
84                write!(f, "unexpected byte 0x{:02x} at {}", got, what,)?
85            }
86            UnexpectedByte { expected, got, what } if expected.len() == 1 => write!(
87                f,
88                "expected byte 0x{:02x} for {} but got 0x{:02x}",
89                expected[0], what, got
90            )?,
91            UnexpectedByte { expected, got, what } => {
92                f.write_str("expected one of ")?;
93                let mut first = true;
94                for b in expected.iter() {
95                    if !first {
96                        f.write_str(", ")?;
97                    }
98                    write!(f, "0x{:02x}", b)?;
99                    first = false;
100                }
101                write!(f, " for {} but got byte 0x{:02x}", what, got)?;
102            }
103            FuncCodeLengthMismatch { num_funcs, num_codes } => write!(
104                f,
105                "number of function sections '{}' does not match to number of code sections '{}'",
106                num_funcs, num_codes,
107            )?,
108            TooManyLocalVariables(num) => write!(f, "too many ({}) local variables", num)?,
109            MalformedSectionSize { name, remaining_bytes } => write!(
110                f,
111                "expected end of {} but trailing {} bytes still remain",
112                name, remaining_bytes
113            )?,
114            MalformedCodeSize { remaining_bytes } => write!(
115                f,
116                "expected end of code but trailing {} bytes still remain",
117                remaining_bytes
118            )?,
119            ExpectedEof(b) => write!(f, "expected end of input but byte 0x{:02x} is still following", b)?,
120        }
121        write!(f, " while parsing {}.", self.when)?;
122        describe_position(f, self.source, self.pos)
123    }
124}
125
126pub type Result<'s, T> = ::std::result::Result<T, Box<Error<'s>>>;