use core::error::Error;
use crate::allocation::AllocationError;
use crate::bytes::ByteCount;
use crate::program::{
ReturnByteLimit, StateByteLimit, StepCount, StepLimit, TraceSnapshotByteLimit,
};
#[derive(Debug, PartialEq, Eq)]
pub enum RunError {
Input(InputError),
Allocation(AllocationError),
StateSize(StateSizeError),
Limit(LimitError),
}
impl Error for RunError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Input(error) => Some(error),
Self::Allocation(error) => Some(error),
Self::StateSize(error) => Some(error),
Self::Limit(error) => Some(error),
}
}
}
impl From<InputError> for RunError {
fn from(value: InputError) -> Self {
Self::Input(value)
}
}
impl From<AllocationError> for RunError {
fn from(value: AllocationError) -> Self {
Self::Allocation(value)
}
}
impl From<StateSizeError> for RunError {
fn from(value: StateSizeError) -> Self {
Self::StateSize(value)
}
}
impl From<LimitError> for RunError {
fn from(value: LimitError) -> Self {
Self::Limit(value)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InputError {
column: InputColumn,
byte: u8,
}
impl InputError {
pub(crate) const fn new(column: InputColumn, byte: u8) -> Self {
Self { column, byte }
}
#[must_use]
pub const fn column(&self) -> InputColumn {
self.column
}
#[must_use]
pub const fn byte(&self) -> u8 {
self.byte
}
}
impl Error for InputError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InputColumn {
one_based: usize,
}
impl InputColumn {
pub(crate) const fn from_zero_based(zero_based: usize) -> Self {
Self {
one_based: zero_based.saturating_add(1),
}
}
#[must_use]
pub const fn get(self) -> usize {
self.one_based
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StateSizeError {
state: ByteCount,
lhs: ByteCount,
rhs: ByteCount,
}
impl StateSizeError {
pub(crate) const fn new(state_len: usize, lhs_len: usize, rhs_len: usize) -> Self {
Self {
state: ByteCount::new(state_len),
lhs: ByteCount::new(lhs_len),
rhs: ByteCount::new(rhs_len),
}
}
#[must_use]
pub const fn state_len(&self) -> ByteCount {
self.state
}
#[must_use]
pub const fn lhs_len(&self) -> ByteCount {
self.lhs
}
#[must_use]
pub const fn rhs_len(&self) -> ByteCount {
self.rhs
}
}
impl Error for StateSizeError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StateLimitContext {
Input,
Rewrite,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LimitError {
State {
context: StateLimitContext,
limit: StateByteLimit,
attempted_len: ByteCount,
},
Return {
limit: ReturnByteLimit,
attempted_len: ByteCount,
},
TraceSnapshot {
limit: TraceSnapshotByteLimit,
attempted_len: ByteCount,
},
Step {
max_steps: StepLimit,
completed_steps: StepCount,
state_len: ByteCount,
},
}
impl LimitError {
pub(crate) const fn state(
context: StateLimitContext,
limit: StateByteLimit,
attempted_len: usize,
) -> Self {
Self::State {
context,
limit,
attempted_len: ByteCount::new(attempted_len),
}
}
pub(crate) const fn return_output(limit: ReturnByteLimit, attempted_len: usize) -> Self {
Self::Return {
limit,
attempted_len: ByteCount::new(attempted_len),
}
}
pub(crate) const fn trace_snapshot(
limit: TraceSnapshotByteLimit,
attempted_len: usize,
) -> Self {
Self::TraceSnapshot {
limit,
attempted_len: ByteCount::new(attempted_len),
}
}
pub(crate) const fn step(
max_steps: StepLimit,
completed_steps: StepCount,
state_len: usize,
) -> Self {
Self::Step {
max_steps,
completed_steps,
state_len: ByteCount::new(state_len),
}
}
}
impl Error for LimitError {}