elevator_core/entity.rs
1//! Entity identity and allocation via generational keys.
2
3use serde::{Deserialize, Serialize};
4
5slotmap::new_key_type! {
6 /// Universal entity identifier used across all component storages.
7 /// Serialize/Deserialize provided by slotmap's `serde` feature.
8 pub struct EntityId;
9}
10
11/// Generates a typed newtype wrapper around [`EntityId`].
12///
13/// Each wrapper is `#[repr(transparent)]` with a public inner field for
14/// convenient internal access via `.0`, and delegates `Display` to
15/// `EntityId`'s `Debug` (since slotmap keys do not implement `Display`).
16macro_rules! typed_entity_id {
17 ($(#[$meta:meta])* $name:ident) => {
18 $(#[$meta])*
19 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
20 #[serde(transparent)]
21 #[repr(transparent)]
22 pub struct $name(pub EntityId);
23
24 impl $name {
25 /// Returns the inner [`EntityId`].
26 #[inline]
27 pub const fn entity(self) -> EntityId {
28 self.0
29 }
30 }
31
32 impl std::fmt::Display for $name {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 write!(f, "{}({:?})", stringify!($name), self.0)
35 }
36 }
37
38 impl From<EntityId> for $name {
39 /// Wrap an `EntityId` in this typed newtype **without** verifying
40 /// the entity is actually of that kind. Wrong-type IDs surface
41 /// later as `EntityNotFound` / `NotAnElevator` from accessor
42 /// calls — for compile-time safety, prefer the typed
43 /// `_id` accessors on `Simulation` (`elevator_ids`,
44 /// `rider_ids`, etc.) that yield typed IDs directly. (#290)
45 #[inline]
46 fn from(id: EntityId) -> Self {
47 Self(id)
48 }
49 }
50
51 impl Default for $name {
52 fn default() -> Self {
53 Self(EntityId::default())
54 }
55 }
56 };
57}
58
59typed_entity_id! {
60 /// Typed wrapper around [`EntityId`] for elevator entities.
61 ElevatorId
62}
63
64typed_entity_id! {
65 /// Typed wrapper around [`EntityId`] for rider entities.
66 RiderId
67}