use std::fmt;
use crate::engine::types::{ArchetypeID, ChunkID, ComponentID, EntityID, RowID};
use super::attribute::AttributeError;
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MoveError {
InconsistentStorage,
PushFromFailed {
component_id: ComponentID,
source_error: AttributeError,
},
RowMisalignment {
expected: (ChunkID, RowID),
got: (ChunkID, RowID),
component_id: ComponentID,
},
NoComponentsMoved,
ComponentAlreadyPresent {
component_id: ComponentID,
},
PushFailed {
component_id: ComponentID,
source_error: AttributeError,
},
SwapRemoveError {
component_id: ComponentID,
source_error: AttributeError,
},
InconsistentSwapInfo,
BatchSpansArchetypes {
expected: ArchetypeID,
got: ArchetypeID,
},
BatchWouldEmptyEntity {
component_id: ComponentID,
},
MetadataFailure {
entity: Option<EntityID>,
source_archetype: Option<ArchetypeID>,
destination_archetype: Option<ArchetypeID>,
},
}
impl fmt::Display for MoveError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MoveError::InconsistentStorage => {
f.write_str("component storage layouts are inconsistent between archetypes")
}
MoveError::PushFromFailed {
component_id,
source_error,
} => {
write!(
f,
"failed to move component {} from source archetype: {}",
component_id, source_error
)
}
MoveError::RowMisalignment {
expected,
got,
component_id,
} => {
write!(
f,
"component {} storage misaligned: expected position {:?}, got {:?}",
component_id, expected, got
)
}
MoveError::NoComponentsMoved => {
f.write_str("no components were moved during archetype transition")
}
MoveError::ComponentAlreadyPresent { component_id } => {
write!(f, "component {} is already present", component_id)
}
MoveError::PushFailed {
component_id,
source_error,
} => {
write!(
f,
"failed to insert component {} into destination archetype: {}",
component_id, source_error
)
}
MoveError::SwapRemoveError {
component_id,
source_error,
} => {
write!(
f,
"failed to remove component {} from source archetype: {}",
component_id, source_error
)
}
MoveError::InconsistentSwapInfo => {
f.write_str("swap-remove produced inconsistent metadata")
}
MoveError::BatchSpansArchetypes { expected, got } => {
write!(
f,
"add-component batch spans archetypes ({expected} and {got}); issue one batch per archetype"
)
}
MoveError::BatchWouldEmptyEntity { component_id } => {
write!(
f,
"removing component {component_id} would leave entities empty; despawn them instead"
)
}
MoveError::MetadataFailure {
entity,
source_archetype,
destination_archetype,
} => {
write!(f, "failed to update entity metadata after archetype move")?;
if let Some(e) = entity {
write!(f, " (entity: {})", e)?;
}
if let Some(src) = source_archetype {
write!(f, " (source archetype: {})", src)?;
}
if let Some(dst) = destination_archetype {
write!(f, " (destination archetype: {})", dst)?;
}
Ok(())
}
}
}
}
impl std::error::Error for MoveError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
MoveError::PushFromFailed { source_error, .. } => Some(source_error),
MoveError::PushFailed { source_error, .. } => Some(source_error),
MoveError::SwapRemoveError { source_error, .. } => Some(source_error),
_ => None,
}
}
}