use std::mem::transmute; use std::sync::atomic::{AtomicU32, Ordering}; use crate::util::{gen_mask_64, BitMask, NumberExt}; static NEXT: AtomicU32 = AtomicU32::new(1); const ID_BITS: BitMask = BitMask::new(gen_mask_64!(32..=63)); const KIND_BITS: BitMask = BitMask::new(gen_mask_64!(0..=1)); #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] #[repr(u8)] pub enum Kind { Entity = 2, Component = 1, } /// Unique entity/component ID. #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Uid { inner: u64, } impl Uid { /// Returns a new unique entity/component ID. pub fn new_unique(kind: Kind) -> Self { let id = NEXT.fetch_add(1, Ordering::Relaxed); Self { inner: ID_BITS.field_prep(id as u64) | KIND_BITS.field_prep(kind as u64), } } #[must_use] pub fn kind(&self) -> Kind { // SAFETY: The kind bits cannot be invalid since they are set using the Kind enum // in the new_unique function unsafe { transmute(self.inner.field_get(KIND_BITS) as u8) } } }