wain-syntax-binary 0.1.5

WebAssembly binary format parser for wain project
Documentation
use crate::source::describe_position;
use std::fmt;
use std::str::Utf8Error;

#[cfg_attr(test, derive(Debug))]
pub enum ErrorKind {
    IntOverflow {
        ty: &'static str,
        got: Option<u64>,
    },
    UnexpectedEof {
        expected: &'static str,
    },
    WasmMagicNotFound,
    VersionMismatch([u8; 4]),
    LengthOutOfInput {
        input: usize,
        specified: usize,
        what: &'static str,
    },
    InvalidUtf8 {
        what: &'static str,
        error: Utf8Error,
    },
    UnexpectedByte {
        expected: Vec<u8>,
        got: u8,
        what: &'static str,
    },
    FuncCodeLengthMismatch {
        num_funcs: usize,
        num_codes: usize,
    },
    TooManyLocalVariables(usize),
    MalformedSectionSize {
        name: &'static str,
        remaining_bytes: usize,
    },
    MalformedCodeSize {
        remaining_bytes: usize,
    },
    ExpectedEof(u8),
}

#[cfg_attr(test, derive(Debug))]
pub struct Error<'source> {
    pub kind: ErrorKind,
    pub pos: usize,
    pub source: &'source [u8],
    pub when: &'static str,
}

impl<'s> Error<'s> {
    pub(crate) fn new(kind: ErrorKind, pos: usize, source: &'s [u8], when: &'static str) -> Box<Error<'s>> {
        Box::new(Error {
            kind,
            pos,
            source,
            when,
        })
    }
}

impl<'s> fmt::Display for Error<'s> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use ErrorKind::*;
        match &self.kind {
            IntOverflow { ty, got: Some(got) } => {
                write!(f, "LEB128-encoded integer '{:x}' is too large for {} value", got, ty)?
            }
            IntOverflow { ty, got: None } => write!(f, "LEB128-encoded integer is too large for {} value", ty)?,
            UnexpectedEof { expected } => {
                write!(f, "expected {} but reached end of current section or input", expected)?
            }
            WasmMagicNotFound => write!(f, "WebAssembly binary must start with magic 0x00 0x61 0x73 0x6d")?,
            VersionMismatch(v) => write!(f, "expected version [1, 0, 0, 0] but got {:?}", v)?,
            LengthOutOfInput { input, specified, what } => write!(
                f,
                "{} ({} bytes) is larger than the rest of input ({} bytes)",
                what, specified, input
            )?,
            InvalidUtf8 { what, error } => write!(f, "{} must be UTF-8 sequence: {}", what, error)?,
            UnexpectedByte { expected, got, what } if expected.is_empty() => {
                write!(f, "unexpected byte 0x{:02x} at {}", got, what,)?
            }
            UnexpectedByte { expected, got, what } if expected.len() == 1 => write!(
                f,
                "expected byte 0x{:02x} for {} but got 0x{:02x}",
                expected[0], what, got
            )?,
            UnexpectedByte { expected, got, what } => {
                f.write_str("expected one of ")?;
                let mut first = true;
                for b in expected.iter() {
                    if !first {
                        f.write_str(", ")?;
                    }
                    write!(f, "0x{:02x}", b)?;
                    first = false;
                }
                write!(f, " for {} but got byte 0x{:02x}", what, got)?;
            }
            FuncCodeLengthMismatch { num_funcs, num_codes } => write!(
                f,
                "number of function sections '{}' does not match to number of code sections '{}'",
                num_funcs, num_codes,
            )?,
            TooManyLocalVariables(num) => write!(f, "too many ({}) local variables", num)?,
            MalformedSectionSize { name, remaining_bytes } => write!(
                f,
                "expected end of {} but trailing {} bytes still remain",
                name, remaining_bytes
            )?,
            MalformedCodeSize { remaining_bytes } => write!(
                f,
                "expected end of code but trailing {} bytes still remain",
                remaining_bytes
            )?,
            ExpectedEof(b) => write!(f, "expected end of input but byte 0x{:02x} is still following", b)?,
        }
        write!(f, " while parsing {}.", self.when)?;
        describe_position(f, self.source, self.pos)
    }
}

pub type Result<'s, T> = ::std::result::Result<T, Box<Error<'s>>>;