diff options
Diffstat (limited to 'engine-ecs/src/uid.rs')
| -rw-r--r-- | engine-ecs/src/uid.rs | 130 |
1 files changed, 38 insertions, 92 deletions
diff --git a/engine-ecs/src/uid.rs b/engine-ecs/src/uid.rs index bb393a1..26fbaee 100644 --- a/engine-ecs/src/uid.rs +++ b/engine-ecs/src/uid.rs @@ -1,5 +1,4 @@ use std::fmt::{Debug, Display, Formatter}; -use std::mem::transmute; use std::sync::atomic::{AtomicU32, Ordering}; use seq_macro::seq; @@ -13,16 +12,7 @@ static WILDCARD_ID: u32 = 1; const ID_BITS: BitMask<u64> = BitMask::new(gen_mask_64!(32..=63)); const RELATION_BITS: BitMask<u64> = BitMask::new(gen_mask_64!(6..=31)); -const KIND_BITS: BitMask<u64> = BitMask::new(gen_mask_64!(0..=1)); - -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[repr(u8)] -pub enum Kind -{ - Pair = 3, - Entity = 2, - Component = 1, -} +const IS_PAIR_BITS: BitMask<u64> = BitMask::new(1 << 0); /// A unique identifier. #[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] @@ -38,12 +28,12 @@ impl Uid pub const FIRST_UNIQUE_ID: u32 = 5; /// Returns a new unique entity/component ID. - pub fn new_unique(kind: Kind) -> Self + pub fn new_unique() -> Self { let id = NEXT.fetch_add(1, Ordering::Relaxed); Self { - inner: ID_BITS.field_prep(u64::from(id)) | KIND_BITS.field_prep(kind as u64), + inner: ID_BITS.field_prep(u64::from(id)) | IS_PAIR_BITS.field_prep(0), } } @@ -52,7 +42,7 @@ impl Uid { Self { inner: ID_BITS.field_prep(u64::from(WILDCARD_ID)) - | KIND_BITS.field_prep(Kind::Component as u64), + | IS_PAIR_BITS.field_prep(0), } } @@ -63,22 +53,13 @@ impl Uid #[must_use] pub fn new_pair(params: &PairParams) -> Self { - assert_ne!( - params.relation.kind(), - Kind::Pair, - "Pair relation cannot be a pair" - ); - - assert_ne!( - params.target.kind(), - Kind::Pair, - "Pair target cannot be a pair" - ); + assert!(!params.relation.is_pair(), "Pair relation cannot be a pair"); + assert!(!params.target.is_pair(), "Pair target cannot be a pair"); Self { inner: ID_BITS.field_prep(u64::from(params.target.id())) | RELATION_BITS.field_prep(u64::from(params.relation.id())) - | KIND_BITS.field_prep(Kind::Pair as u64), + | IS_PAIR_BITS.field_prep(1), } } @@ -93,102 +74,72 @@ impl Uid } #[must_use] - pub fn kind(&self) -> Kind + pub fn is_pair(&self) -> bool { - let Ok(kind) = u8::try_from(self.inner.field_get(KIND_BITS)) else { - unreachable!("Uid kind does not fit in u8"); + let Ok(is_pair) = u8::try_from(self.inner.field_get(IS_PAIR_BITS)) else { + unreachable!(); }; - // SAFETY: The kind bits cannot be invalid since they are set using the Kind enum - // in the new_unique function - unsafe { transmute::<u8, Kind>(kind) } + is_pair == 1 } - /// If this `Uid` is a pair, returns the relation as a component `Uid`. + /// If this `Uid` is a pair, returns the relation `Uid`. /// /// # Panics /// Will panic if this `Uid` is not a pair. #[must_use] - pub fn relation_component(&self) -> Self + pub fn relation(&self) -> Self { - assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair"); - - Self { - inner: ID_BITS.field_prep(u64::from(self.relation())) - | KIND_BITS.field_prep(Kind::Component as u64), - } - } + assert!(self.is_pair(), "Uid is not a pair"); - #[must_use] - pub fn has_same_relation_as(&self, other: Self) -> bool - { - self.relation() == other.relation() - } - - /// If this `Uid` is a pair, returns the relation as a entity `Uid`. - /// - /// # Panics - /// Will panic if this `Uid` is not a pair. - #[must_use] - pub fn relation_entity(&self) -> Self - { - assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair"); + let Ok(relation) = u32::try_from(self.inner.field_get(RELATION_BITS)) else { + unreachable!("Uid relation does not fit in u32"); + }; Self { - inner: ID_BITS.field_prep(u64::from(self.relation())) - | KIND_BITS.field_prep(Kind::Entity as u64), + inner: ID_BITS.field_prep(u64::from(relation)) | IS_PAIR_BITS.field_prep(0), } } - /// If this `Uid` is a pair, returns the target as a component `Uid`. + /// Compares the relation of this pair `Uid` with the relation of another pair `Uid`. /// /// # Panics - /// Will panic if this `Uid` is not a pair. + /// Will panic if any of the `Uid`s are not a pair. #[must_use] - pub fn target_component(&self) -> Self + pub fn has_same_relation_as(&self, other: Self) -> bool { - assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair"); - - Self { - inner: ID_BITS.field_prep(u64::from(self.id())) - | KIND_BITS.field_prep(Kind::Component as u64), - } + self.relation() == other.relation() } - /// If this `Uid` is a pair, returns the target as a entity `Uid`. + /// If this `Uid` is a pair, returns the target `Uid`. /// /// # Panics /// Will panic if this `Uid` is not a pair. #[must_use] - pub fn target_entity(&self) -> Self + pub fn target(&self) -> Self { - assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair"); + assert!(self.is_pair(), "Uid is not a pair"); Self { - inner: ID_BITS.field_prep(u64::from(self.id())) - | KIND_BITS.field_prep(Kind::Entity as u64), + inner: ID_BITS.field_prep(u64::from(self.id())) | IS_PAIR_BITS.field_prep(0), } } - - fn relation(self) -> u32 - { - let Ok(relation) = u32::try_from(self.inner.field_get(RELATION_BITS)) else { - unreachable!("Uid relation does not fit in u32"); - }; - - relation - } } impl Debug for Uid { fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result { - formatter - .debug_struct("Uid") - .field("id", &self.id()) - .field("kind", &self.kind()) - .finish_non_exhaustive() + let mut debug_struct = formatter.debug_struct("Uid"); + + if self.is_pair() { + return debug_struct + .field("relation", &self.relation()) + .field("target", &self.target()) + .finish(); + } + + debug_struct.field("id", &self.id()).finish() } } @@ -196,13 +147,8 @@ impl Display for Uid { fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result { - if self.kind() == Kind::Pair { - return write!( - formatter, - "({}, {})", - self.relation(), - self.target_component() - ); + if self.is_pair() { + return write!(formatter, "({}, {})", self.relation(), self.target()); } if *self == Uid::wildcard() { |
