| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use crate::errors::UserError; |
| use byteorder::ByteOrder; |
| use std::fmt; |
| use thiserror::Error; |
| |
| // Common functions and enums for interpreting the bytecode. |
| |
| #[derive(Debug, Error, Clone, PartialEq)] |
| pub enum BytecodeError { |
| UnexpectedEnd, |
| InvalidHeader(u32, u32), |
| InvalidVersion(u32), |
| InvalidStringLength, |
| EmptyString, |
| Utf8ConversionFailure, |
| InvalidSymbolTableKey(u32), |
| IncorrectSectionSize, |
| InvalidOp(u8), |
| InvalidValueType(u8), |
| InvalidBoolValue(u32), |
| MissingEntryInSymbolTable(u32), |
| MismatchValueTypes, |
| InvalidJumpLocation, |
| } |
| |
| impl fmt::Display for BytecodeError { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, "{}", UserError::from(self.clone())) |
| } |
| } |
| |
| pub type BytecodeIter = std::vec::IntoIter<u8>; |
| |
| pub fn next_u8(iter: &mut BytecodeIter) -> Result<u8, BytecodeError> { |
| iter.next().ok_or(BytecodeError::UnexpectedEnd) |
| } |
| |
| pub fn next_u32(iter: &mut BytecodeIter) -> Result<u32, BytecodeError> { |
| let mut bytes: [u8; 4] = [0; 4]; |
| for i in 0..4 { |
| bytes[i] = next_u8(iter)?; |
| } |
| |
| Ok(byteorder::LittleEndian::read_u32(&bytes)) |
| } |
| |
| // Return the next four bytes in the iterator as a u32. If the iterator is empty, |
| // return None. |
| pub fn try_next_u32(iter: &mut BytecodeIter) -> Result<Option<u32>, BytecodeError> { |
| let mut bytes: [u8; 4] = [0; 4]; |
| if let Some(byte) = iter.next() { |
| bytes[0] = byte; |
| } else { |
| return Ok(None); |
| } |
| |
| for i in 1..4 { |
| bytes[i] = next_u8(iter)?; |
| } |
| |
| Ok(Some(byteorder::LittleEndian::read_u32(&bytes))) |
| } |