1use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::sync::atomic::{AtomicU64, Ordering};
6
7static NEXT_ID: AtomicU64 = AtomicU64::new(1);
9
10#[derive(Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
15#[serde(transparent)]
16pub struct EntityId(pub u64);
17
18impl EntityId {
19 pub fn new() -> Self {
21 Self(NEXT_ID.fetch_add(1, Ordering::Relaxed))
22 }
23
24 pub fn from_raw(id: u64) -> Self {
26 Self(id)
27 }
28
29 pub fn raw(&self) -> u64 {
31 self.0
32 }
33
34 #[cfg(test)]
36 pub fn reset_counter() {
37 NEXT_ID.store(1, Ordering::Relaxed);
38 }
39
40 pub fn ensure_counter_above(value: u64) {
42 let mut current = NEXT_ID.load(Ordering::Relaxed);
43 while current <= value {
44 match NEXT_ID.compare_exchange_weak(
45 current,
46 value + 1,
47 Ordering::Relaxed,
48 Ordering::Relaxed,
49 ) {
50 Ok(_) => break,
51 Err(c) => current = c,
52 }
53 }
54 }
55}
56
57impl Default for EntityId {
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63impl fmt::Debug for EntityId {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 write!(f, "EntityId({})", self.0)
66 }
67}
68
69impl fmt::Display for EntityId {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 write!(f, "{}", self.0)
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn test_id_generation() {
81 EntityId::reset_counter();
82 let id1 = EntityId::new();
83 let id2 = EntityId::new();
84 assert_ne!(id1, id2);
85 assert!(id2.0 > id1.0);
86 }
87
88 #[test]
89 fn test_from_raw() {
90 let id = EntityId::from_raw(42);
91 assert_eq!(id.raw(), 42);
92 }
93
94 #[test]
95 fn test_ensure_counter_above() {
96 EntityId::reset_counter();
97 EntityId::ensure_counter_above(100);
98 let id = EntityId::new();
99 assert!(id.0 > 100);
100 }
101}