use evy_ecs_storage::{Namespace, ParticleId};
use evy_platform_caps::Engine;
use crate::ctx::DispatchCtx;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ShardRef {
Namespace(Namespace),
Particle(Namespace, ParticleId),
}
impl ShardRef {
pub fn disjoint(self, other: Self) -> bool {
match (self, other) {
(ShardRef::Particle(a_ns, a_p), ShardRef::Particle(b_ns, b_p)) => {
a_ns != b_ns || a_p != b_p
}
(ShardRef::Namespace(a), ShardRef::Namespace(b)) => a != b,
(ShardRef::Namespace(ns), ShardRef::Particle(p_ns, _))
| (ShardRef::Particle(p_ns, _), ShardRef::Namespace(ns)) => ns != p_ns,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CommitPolicy {
None,
BbgDimension(Namespace),
BbgPrivate,
}
impl CommitPolicy {
pub fn is_committed(self) -> bool {
!matches!(self, CommitPolicy::None)
}
}
pub trait DispatchNode: Send {
fn engine(&self) -> Engine;
fn reads(&self) -> &[ShardRef];
fn writes(&self) -> &[ShardRef];
fn commit_policy(&self) -> CommitPolicy;
fn dispatch(&mut self, ctx: &mut DispatchCtx<'_>);
fn label(&self) -> &str {
core::any::type_name::<Self>()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn namespace_refs_disjoint_when_different() {
assert!(ShardRef::Namespace(Namespace::Particles)
.disjoint(ShardRef::Namespace(Namespace::Coins)));
assert!(!ShardRef::Namespace(Namespace::Particles)
.disjoint(ShardRef::Namespace(Namespace::Particles)));
}
#[test]
fn particle_refs_disjoint_when_different_particle() {
let a = ParticleId::from_entity(1, 0);
let b = ParticleId::from_entity(2, 0);
assert!(ShardRef::Particle(Namespace::Neurons, a)
.disjoint(ShardRef::Particle(Namespace::Neurons, b)));
assert!(!ShardRef::Particle(Namespace::Neurons, a)
.disjoint(ShardRef::Particle(Namespace::Neurons, a)));
}
#[test]
fn namespace_and_particle_refs_conflict_in_same_namespace() {
let p = ParticleId::from_entity(1, 0);
assert!(!ShardRef::Namespace(Namespace::Coins)
.disjoint(ShardRef::Particle(Namespace::Coins, p)));
assert!(ShardRef::Namespace(Namespace::Coins)
.disjoint(ShardRef::Particle(Namespace::Cards, p)));
}
#[test]
fn commit_policy_classification() {
assert!(!CommitPolicy::None.is_committed());
assert!(CommitPolicy::BbgDimension(Namespace::Coins).is_committed());
assert!(CommitPolicy::BbgPrivate.is_committed());
}
}