use std::fmt;
use std::sync::atomic::{AtomicU64, Ordering};
static FAULTS: AtomicU64 = AtomicU64::new(0);
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RuntimeError {
PoisonedLock(&'static str),
}
impl fmt::Display for RuntimeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RuntimeError::PoisonedLock(where_) => {
write!(f, "runtime mutex poisoned at {where_}")
}
}
}
}
impl std::error::Error for RuntimeError {}
#[cold]
pub fn report_fault(err: RuntimeError) {
FAULTS.fetch_add(1, Ordering::Relaxed);
eprintln!("byteflow: {err} — fail-closed");
}
pub fn fault_count() -> u64 {
FAULTS.load(Ordering::Relaxed)
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SpawnError {
BadFunction { index: u32, table_size: u32 },
VerifyFailed(String),
ThreadSpawnFailed(String),
VmInit(String),
}
impl fmt::Display for SpawnError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SpawnError::BadFunction { index, table_size } => {
write!(
f,
"spawn: function index {index} out of range (table size {table_size})"
)
}
SpawnError::VerifyFailed(msg) => write!(f, "chunk verification failed: {msg}"),
SpawnError::ThreadSpawnFailed(msg) => {
write!(f, "failed to spawn runtime thread: {msg}")
}
SpawnError::VmInit(msg) => write!(f, "vm init failed: {msg}"),
}
}
}
impl std::error::Error for SpawnError {}
impl From<crate::vm::Fault> for SpawnError {
fn from(fault: crate::vm::Fault) -> Self {
match fault {
crate::vm::Fault::BadFunction { index, table_size } => {
SpawnError::BadFunction { index, table_size }
}
other => SpawnError::VmInit(other.to_string()),
}
}
}