use crate::engine::Instr;
use core::fmt::Display;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DropKeep {
drop: u16,
keep: u16,
}
#[derive(Debug, Copy, Clone)]
pub enum DropKeepError {
OutOfBoundsKeep,
OutOfBoundsDrop,
}
impl Display for DropKeepError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
DropKeepError::OutOfBoundsKeep => {
write!(f, "amount of kept elements exceeds engine's limits")
}
DropKeepError::OutOfBoundsDrop => {
write!(f, "amount of dropped elements exceeds engine's limits")
}
}
}
}
impl DropKeep {
pub fn none() -> Self {
Self { drop: 0, keep: 0 }
}
pub fn new(drop: usize, keep: usize) -> Result<Self, DropKeepError> {
let drop = drop
.try_into()
.map_err(|_| DropKeepError::OutOfBoundsDrop)?;
let keep = keep
.try_into()
.map_err(|_| DropKeepError::OutOfBoundsKeep)?;
Ok(Self { drop, keep })
}
pub fn drop(self) -> usize {
self.drop as usize
}
pub fn keep(self) -> usize {
self.keep as usize
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct FuncIdx(u32);
impl From<u32> for FuncIdx {
fn from(index: u32) -> Self {
Self(index)
}
}
impl FuncIdx {
pub fn into_inner(self) -> u32 {
self.0
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct TableIdx(u32);
impl From<u32> for TableIdx {
fn from(index: u32) -> Self {
Self(index)
}
}
impl TableIdx {
pub fn into_inner(self) -> u32 {
self.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct SignatureIdx(u32);
impl From<u32> for SignatureIdx {
fn from(index: u32) -> Self {
Self(index)
}
}
impl SignatureIdx {
pub fn into_inner(self) -> u32 {
self.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct LocalDepth(usize);
impl From<usize> for LocalDepth {
fn from(index: usize) -> Self {
Self(index)
}
}
impl LocalDepth {
pub fn into_inner(self) -> usize {
self.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct GlobalIdx(u32);
impl From<u32> for GlobalIdx {
fn from(index: u32) -> Self {
Self(index)
}
}
impl GlobalIdx {
pub fn into_inner(self) -> u32 {
self.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct DataSegmentIdx(u32);
impl From<u32> for DataSegmentIdx {
fn from(index: u32) -> Self {
Self(index)
}
}
impl DataSegmentIdx {
pub fn into_inner(self) -> u32 {
self.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct ElementSegmentIdx(u32);
impl From<u32> for ElementSegmentIdx {
fn from(index: u32) -> Self {
Self(index)
}
}
impl ElementSegmentIdx {
pub fn into_inner(self) -> u32 {
self.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct Offset(u32);
impl From<u32> for Offset {
fn from(index: u32) -> Self {
Self(index)
}
}
impl Offset {
pub fn into_inner(self) -> u32 {
self.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct BranchParams {
offset: BranchOffset,
drop_keep: DropKeep,
}
impl BranchParams {
pub fn new(offset: BranchOffset, drop_keep: DropKeep) -> Self {
Self { offset, drop_keep }
}
fn is_init(&self) -> bool {
self.offset.is_init()
}
pub fn init(&mut self, offset: BranchOffset) {
assert!(offset.is_init());
assert!(!self.is_init());
self.offset = offset;
}
pub fn offset(self) -> BranchOffset {
self.offset
}
pub fn drop_keep(self) -> DropKeep {
self.drop_keep
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct BranchOffset(i32);
impl BranchOffset {
#[cfg(test)]
pub fn from_i32(value: i32) -> Self {
Self(value)
}
pub fn uninit() -> Self {
Self(0)
}
pub fn init(src: Instr, dst: Instr) -> Self {
let src = src.into_u32() as i32;
let dst = dst.into_u32() as i32;
Self(dst - src)
}
pub fn is_init(self) -> bool {
self.0 != 0
}
pub fn into_i32(self) -> i32 {
self.0
}
}