use std::fmt;
use crate::engine::error::ECSError;
use crate::engine::types::{ComponentID, COMPONENT_CAP};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AgentError {
TemplateNotFound(String),
DuplicateTemplate(String),
MissingComponent(ComponentID),
StaleHandle,
DuplicateComponent(ComponentID),
InvalidComponentId {
component_id: ComponentID,
cap: usize,
},
UnregisteredTemplate(String),
RegistrySealed,
BatchLengthMismatch {
component_id: ComponentID,
expected: usize,
actual: usize,
},
}
impl fmt::Display for AgentError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AgentError::TemplateNotFound(name) => write!(f, "agent template not found: {name}"),
AgentError::DuplicateTemplate(name) => {
write!(f, "agent template already registered: {name}")
}
AgentError::MissingComponent(id) => {
write!(f, "component {id} is not in the template signature")
}
AgentError::StaleHandle => write!(f, "stale agent handle: entity no longer exists"),
AgentError::DuplicateComponent(id) => {
write!(f, "component {id} is already registered in this template")
}
AgentError::InvalidComponentId { component_id, cap } => write!(
f,
"invalid component id {component_id}; valid component ids are < {cap}"
),
AgentError::UnregisteredTemplate(name) => {
write!(f, "agent template '{name}' has not been registered")
}
AgentError::RegistrySealed => write!(
f,
"agent registry is sealed; no further templates may be registered"
),
AgentError::BatchLengthMismatch {
component_id,
expected,
actual,
} => write!(
f,
"batch column {component_id} has length {actual}, expected {expected}"
),
}
}
}
impl std::error::Error for AgentError {}
impl AgentError {
pub(crate) fn invalid_component_id(component_id: ComponentID) -> Self {
AgentError::InvalidComponentId {
component_id,
cap: COMPONENT_CAP,
}
}
}
impl From<AgentError> for ECSError {
fn from(e: AgentError) -> Self {
ECSError::Agent(e)
}
}
pub type AgentResult<T> = Result<T, AgentError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_template_not_found() {
let e = AgentError::TemplateNotFound("Sheep".into());
assert!(e.to_string().contains("Sheep"));
}
#[test]
fn display_missing_component() {
let e = AgentError::MissingComponent(42);
assert!(e.to_string().contains("42"));
}
#[test]
fn display_stale_handle() {
let e = AgentError::StaleHandle;
assert!(e.to_string().contains("stale"));
}
#[test]
fn display_duplicate_component() {
let e = AgentError::DuplicateComponent(7);
assert!(e.to_string().contains("7"));
}
#[test]
fn display_invalid_component_id() {
let e = AgentError::InvalidComponentId {
component_id: COMPONENT_CAP as ComponentID,
cap: COMPONENT_CAP,
};
assert!(e.to_string().contains(&COMPONENT_CAP.to_string()));
}
#[test]
fn display_unregistered_template() {
let e = AgentError::UnregisteredTemplate("Fox".into());
assert!(e.to_string().contains("Fox"));
}
#[test]
fn display_registry_sealed() {
let e = AgentError::RegistrySealed;
assert!(e.to_string().contains("sealed"));
}
#[test]
fn into_ecs_error_does_not_panic() {
let e = AgentError::TemplateNotFound("X".into());
let ecs: ECSError = e.into();
assert!(matches!(
ecs,
ECSError::Agent(AgentError::TemplateNotFound(_))
));
}
}