use core::fmt;
#[cfg(feature = "std")]
use std::error::Error;
use crate::types::EdgeIndex;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum QueueError {
AtOrAboveHardCap,
Backpressured,
Empty,
Unsupported,
Poisoned,
}
impl fmt::Display for QueueError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
QueueError::AtOrAboveHardCap => {
f.write_str("queue is at or above the hard watermark capacity")
}
QueueError::Backpressured => {
f.write_str("queue is backpressured but not full; caller may retry later")
}
QueueError::Empty => f.write_str("queue is empty"),
QueueError::Unsupported => f.write_str("operation unsupported by this queue/backend"),
QueueError::Poisoned => f.write_str("queue lock is poisoned"),
}
}
}
#[cfg(feature = "std")]
impl Error for QueueError {}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeErrorKind {
NoInput,
Backpressured,
OverBudget,
ExternalUnavailable,
ExecutionFailed,
}
impl fmt::Display for NodeErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
NodeErrorKind::NoInput => {
f.write_str("inputs were not available to progress this node")
}
NodeErrorKind::Backpressured => {
f.write_str("outputs could not be enqueued due to backpressure")
}
NodeErrorKind::OverBudget => {
f.write_str("an execution budget or deadline was exceeded")
}
NodeErrorKind::ExternalUnavailable => {
f.write_str("an external dependency was unavailable or timed out")
}
NodeErrorKind::ExecutionFailed => {
f.write_str("a generic failure occurred in node logic")
}
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NodeError {
kind: NodeErrorKind,
code: u32,
}
impl NodeError {
pub const fn new(kind: NodeErrorKind, code: u32) -> Self {
Self { kind, code }
}
}
impl fmt::Display for NodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "node error: {} (code: {})", self.kind, self.code)
}
}
#[cfg(feature = "std")]
impl Error for NodeError {}
impl NodeError {
#[inline]
pub const fn no_input() -> Self {
Self::new(NodeErrorKind::NoInput, 0)
}
#[inline]
pub const fn backpressured() -> Self {
Self::new(NodeErrorKind::Backpressured, 0)
}
#[inline]
pub const fn over_budget() -> Self {
Self::new(NodeErrorKind::OverBudget, 0)
}
#[inline]
pub const fn external_unavailable() -> Self {
Self::new(NodeErrorKind::ExternalUnavailable, 0)
}
#[inline]
pub const fn execution_failed() -> Self {
Self::new(NodeErrorKind::ExecutionFailed, 0)
}
#[inline]
pub const fn with_code(mut self, code: u32) -> Self {
self.code = code;
self
}
#[inline]
pub const fn kind(&self) -> &NodeErrorKind {
&self.kind
}
#[inline]
pub const fn code(&self) -> &u32 {
&self.code
}
}
impl From<NodeErrorKind> for NodeError {
#[inline]
fn from(kind: NodeErrorKind) -> Self {
NodeError::new(kind, 0)
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InferenceErrorKind {
InvalidArtifact,
ShapeOrTypeMismatch,
ExecutionFailed,
ResourceUnavailable,
}
impl fmt::Display for InferenceErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InferenceErrorKind::InvalidArtifact => {
f.write_str("model artifact is invalid or unsupported")
}
InferenceErrorKind::ShapeOrTypeMismatch => {
f.write_str("input or output payload is incompatible with the model")
}
InferenceErrorKind::ExecutionFailed => {
f.write_str("execution failed inside the backend")
}
InferenceErrorKind::ResourceUnavailable => {
f.write_str("backend resource is unavailable")
}
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct InferenceError {
kind: InferenceErrorKind,
code: u32,
}
impl InferenceError {
pub const fn new(kind: InferenceErrorKind, code: u32) -> Self {
Self { kind, code }
}
#[inline]
pub const fn kind(&self) -> &InferenceErrorKind {
&self.kind
}
#[inline]
pub const fn code(&self) -> &u32 {
&self.code
}
}
impl fmt::Display for InferenceError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "inference error: {} (code: {})", self.kind, self.code)
}
}
#[cfg(feature = "std")]
impl Error for InferenceError {}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GraphError {
Cyclic,
IncompatiblePorts,
InvalidCapacity,
InvalidEdgeIndex,
OccupancySampleFailed(EdgeIndex),
}
impl fmt::Display for GraphError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GraphError::Cyclic => f.write_str("graph contains a cycle"),
GraphError::IncompatiblePorts => {
f.write_str("port schema or memory placement is incompatible across an edge")
}
GraphError::InvalidCapacity => {
f.write_str("queue capacity or watermark configuration is invalid")
}
GraphError::InvalidEdgeIndex => f.write_str("edge index is invalid"),
GraphError::OccupancySampleFailed(ei) => {
write!(f, "failed to sample occupancy for edge {}", ei.as_usize())
}
}
}
}
#[cfg(feature = "std")]
impl Error for GraphError {}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RuntimeErrorKind {
InvariantViolation,
PlatformUnavailable,
Unsupported,
Unknown,
}
impl fmt::Display for RuntimeErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RuntimeErrorKind::InvariantViolation => f.write_str("an invariant has been violated"),
RuntimeErrorKind::PlatformUnavailable => {
f.write_str("a requested platform service is unavailable")
}
RuntimeErrorKind::Unsupported => {
f.write_str("the operation is unsupported in this profile or configuration")
}
RuntimeErrorKind::Unknown => f.write_str("an unspecified failure occurred"),
}
}
}
#[cfg(feature = "std")]
impl Error for RuntimeErrorKind {}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SchedulerError {
InvariantViolation,
Internal,
}
impl fmt::Display for SchedulerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SchedulerError::InvariantViolation => {
f.write_str("the scheduler cannot proceed due to an invariant violation")
}
SchedulerError::Internal => f.write_str("an internal scheduler error occurred"),
}
}
}
#[cfg(feature = "std")]
impl Error for SchedulerError {}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SensorError {
OpenFailed,
ReadFailed,
EndOfStream,
ResetFailed,
ConfigurationInvalid,
}
impl fmt::Display for SensorError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SensorError::OpenFailed => f.write_str("sensor open failed"),
SensorError::ReadFailed => f.write_str("sensor read failed"),
SensorError::EndOfStream => f.write_str("sensor stream ended"),
SensorError::ResetFailed => f.write_str("sensor reset failed"),
SensorError::ConfigurationInvalid => f.write_str("invalid sensor configuration"),
}
}
}
#[cfg(feature = "std")]
impl Error for SensorError {}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OutputError {
WriteFailed,
FlushFailed,
}
impl fmt::Display for OutputError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
OutputError::WriteFailed => f.write_str("sink write failed"),
OutputError::FlushFailed => f.write_str("sink flush failed"),
}
}
}
#[cfg(feature = "std")]
impl Error for OutputError {}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MemoryError {
NoFreeSlots,
BadToken,
NotAllocated,
AlreadyBorrowed,
BorrowActive,
Poisoned,
}
impl fmt::Display for MemoryError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MemoryError::NoFreeSlots => f.write_str("no free slots in memory manager"),
MemoryError::BadToken => f.write_str("token index out of range or slot not allocated"),
MemoryError::NotAllocated => {
f.write_str("attempted to free a slot that is not allocated")
}
MemoryError::AlreadyBorrowed => f.write_str("slot already borrowed incompatibly"),
MemoryError::BorrowActive => f.write_str("cannot free slot while borrows are active"),
MemoryError::Poisoned => f.write_str("synchronization primitive is poisoned"),
}
}
}
#[cfg(feature = "std")]
impl Error for MemoryError {}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RuntimeInvariantError {
UninitializedClock,
UninitializedTelemetry,
}
impl fmt::Display for RuntimeInvariantError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RuntimeInvariantError::UninitializedClock => f.write_str("clock not present"),
RuntimeInvariantError::UninitializedTelemetry => f.write_str("telemetry not present"),
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RuntimeError {
Graph(GraphError),
Node(NodeError),
RuntimeInvariant(RuntimeInvariantError),
}
impl From<GraphError> for RuntimeError {
#[inline]
fn from(e: GraphError) -> Self {
RuntimeError::Graph(e)
}
}
impl From<NodeError> for RuntimeError {
#[inline]
fn from(e: NodeError) -> Self {
RuntimeError::Node(e)
}
}
impl From<RuntimeInvariantError> for RuntimeError {
#[inline]
fn from(e: RuntimeInvariantError) -> Self {
RuntimeError::RuntimeInvariant(e)
}
}
impl fmt::Display for RuntimeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RuntimeError::Graph(e) => write!(f, "runtime graph error: {e}"),
RuntimeError::Node(e) => write!(f, "runtime node error: {e}"),
RuntimeError::RuntimeInvariant(e) => write!(f, "runtime invariant error: {e}"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for RuntimeError {}