use std::mem::transmute; use std::sync::atomic::{AtomicU32, Ordering}; static NEXT: AtomicU32 = AtomicU32::new(1); // Bit 0 and 1 for the kind const KIND_BITS: u64 = 0x03; #[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_part = NEXT.fetch_add(1, Ordering::Relaxed); Self { inner: (u64::from(id_part) << 32) | 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 & KIND_BITS) as u8) } } }