use crate::vector::Vector;
use crate::{reader::Reader, VectorFactory};
use core::fmt::{Display, Formatter};
use core::str::Utf8Error;
pub trait Decode<V: VectorFactory>: Sized {
fn decode(reader: &mut Reader) -> Result<Self, DecodeError>;
fn decode_vector(reader: &mut Reader) -> Result<V::Vector<Self>, DecodeError> {
let len = reader.read_usize()?;
let mut items = V::create_vector(Some(len));
for _ in 0..len {
items.push(Self::decode(reader)?);
}
Ok(items)
}
}
impl<V: VectorFactory> Decode<V> for u8 {
fn decode(reader: &mut Reader) -> Result<Self, DecodeError> {
reader.read_u8()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DecodeError {
UnexpectedEndOfBytes,
InvalidMagic {
value: [u8; 4],
},
InvalidVersion {
value: [u8; 4],
},
InvalidSectionId {
value: u8,
},
InvalidImportDescTag {
value: u8,
},
InvalidExportDescTag {
value: u8,
},
InvalidLimitsFlag {
value: u8,
},
InvalidValType {
value: u8,
},
InvalidMutabilityFlag {
value: u8,
},
InvalidElemType {
value: u8,
},
InvalidFuncTypeTag {
value: u8,
},
InvalidMemoryCount {
value: usize,
},
InvalidTableCount {
value: usize,
},
InvalidResultArity {
value: usize,
},
InvalidMemIdx {
value: u32,
},
InvalidTableIdx {
value: u32,
},
InvalidOpcode {
value: u8,
},
UnexpectedExpr,
InvalidSectionOrder {
last_section_id: u8,
current_section_id: u8,
},
InvalidSectionByteSize {
section_id: u8,
expected_byte_size: usize,
actual_byte_size: usize,
},
InvalidUtf8(Utf8Error),
MismatchFunctionAndCodeSectionSize {
function_section_size: usize,
code_section_size: usize,
},
MalformedInteger,
}
impl Display for DecodeError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Self::UnexpectedEndOfBytes => write!(f, "Unexpected end-of-bytes"),
Self::InvalidMagic { value } => write!(f, "Invalid magic number {value:?}"),
Self::InvalidVersion { value } => write!(f, "Invalid version number {value:?}"),
Self::InvalidSectionId { value } => write!(f, "Invalid section ID {value:?}"),
Self::InvalidImportDescTag { value } => {
write!(f, "Invalid import description tag {value:?})")
}
Self::InvalidExportDescTag { value } => {
write!(f, "Invalid export description tag {value:?})")
}
Self::InvalidLimitsFlag { value } => write!(f, "Invalid limits flag {value:?}"),
Self::InvalidValType { value } => write!(f, "Invalid value type {value:?}"),
Self::InvalidMutabilityFlag { value } => write!(f, "Invalid mutability flag {value:?}"),
Self::InvalidElemType { value } => write!(f, "Invalid element type {value:?}"),
Self::InvalidFuncTypeTag { value } => write!(f, "Invalid function type {value:?}"),
Self::InvalidMemoryCount { value } => write!(f, "Invalid memory count {value:?}"),
Self::InvalidTableCount { value } => write!(f, "Invalid table count {value:?}"),
Self::InvalidResultArity { value } => write!(f, "Invalid result arity {value:?}"),
Self::InvalidMemIdx { value } => write!(f, "Invalid memory index {value:?}"),
Self::InvalidTableIdx { value } => write!(f, "Invalid table index {value:?}"),
Self::InvalidOpcode { value } => write!(f, "Invalid opcode {value:?}"),
Self::UnexpectedExpr => write!(f, "Unexpected expression"),
Self::InvalidSectionOrder {
last_section_id,
current_section_id,
} => write!(
f,
"Invalid section order (last={last_section_id:?}), current={current_section_id:?})"
),
Self::InvalidSectionByteSize {
section_id,
expected_byte_size,
actual_byte_size
} => write!(f, "Invalid section {section_id:?} byte size (expected={expected_byte_size:?} bytes, actual={actual_byte_size:?} bytes)"),
Self::InvalidUtf8(e) => write!(f,"Invalid UTF-8 bytes ({e})"),
Self::MismatchFunctionAndCodeSectionSize {
function_section_size,
code_section_size
} => write!(f, "Mismatch function section size ({function_section_size:?}) and code section size ({code_section_size:?})"),
Self::MalformedInteger => write!(f,"Malformed LEB128 integer"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for DecodeError {}