bind/interpreter/
common.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::errors::UserError;
6use byteorder::ByteOrder;
7use std::fmt;
8use thiserror::Error;
9
10// Common functions and enums for interpreting the bytecode.
11
12#[derive(Debug, Error, Clone, PartialEq)]
13pub enum BytecodeError {
14    UnexpectedEnd,
15    InvalidHeader(u32, u32),
16    InvalidVersion(u32),
17    InvalidStringLength,
18    EmptyString,
19    Utf8ConversionFailure,
20    InvalidSymbolTableKey(u32),
21    IncorrectSectionSize,
22    InvalidOp(u8),
23    InvalidValueType(u8),
24    InvalidBoolValue(u32),
25    MissingEntryInSymbolTable(u32),
26    MismatchValueTypes,
27    InvalidJumpLocation,
28    InvalidKeyType,
29    InvalidPrimaryNode,
30    MultiplePrimaryNodes,
31    InvalidNodeType(u8),
32    IncorrectNodeSectionSize,
33    MissingDeviceNameInSymbolTable,
34    MissingNodeIdInSymbolTable,
35    InvalidDebugFlag(u8),
36}
37
38impl fmt::Display for BytecodeError {
39    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40        write!(f, "{}", UserError::from(self.clone()))
41    }
42}
43
44pub type BytecodeIter<'a> = std::slice::Iter<'a, u8>;
45
46pub fn next_u8<'a>(iter: &mut BytecodeIter<'a>) -> Result<&'a u8, BytecodeError> {
47    iter.next().ok_or(BytecodeError::UnexpectedEnd)
48}
49
50pub fn next_u32<'a>(iter: &mut BytecodeIter<'a>) -> Result<u32, BytecodeError> {
51    let mut bytes: [u8; 4] = [0; 4];
52    for i in 0..4 {
53        bytes[i] = *next_u8(iter)?;
54    }
55
56    Ok(byteorder::LittleEndian::read_u32(&bytes))
57}
58
59// Return the next four bytes in the iterator as a u32. If the iterator is empty,
60// return None.
61pub fn try_next_u32(iter: &mut BytecodeIter) -> Result<Option<u32>, BytecodeError> {
62    let mut bytes: [u8; 4] = [0; 4];
63    if let Some(byte) = iter.next() {
64        bytes[0] = *byte;
65    } else {
66        return Ok(None);
67    }
68
69    for i in 1..4 {
70        bytes[i] = *next_u8(iter)?;
71    }
72
73    Ok(Some(byteorder::LittleEndian::read_u32(&bytes)))
74}