Skip to main content

codec/
types.rs

1//! Core types for the codec.
2
3/// A simulation tick number.
4///
5/// Ticks are monotonically increasing identifiers for simulation states.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
7pub struct SnapshotTick(u32);
8
9impl SnapshotTick {
10    /// Creates a new snapshot tick.
11    #[must_use]
12    pub const fn new(tick: u32) -> Self {
13        Self(tick)
14    }
15
16    /// Returns the raw tick value.
17    #[must_use]
18    pub const fn raw(self) -> u32 {
19        self.0
20    }
21
22    /// Returns `true` if this tick is zero (often used as "no baseline").
23    #[must_use]
24    pub const fn is_zero(self) -> bool {
25        self.0 == 0
26    }
27}
28
29impl From<u32> for SnapshotTick {
30    fn from(tick: u32) -> Self {
31        Self(tick)
32    }
33}
34
35impl From<SnapshotTick> for u32 {
36    fn from(tick: SnapshotTick) -> Self {
37        tick.0
38    }
39}
40
41/// A stable entity identifier.
42///
43/// Entity IDs are assigned by the simulation layer and must remain stable
44/// for the lifetime of an entity.
45#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
46pub struct EntityId(u32);
47
48impl EntityId {
49    /// Creates a new entity ID.
50    #[must_use]
51    pub const fn new(id: u32) -> Self {
52        Self(id)
53    }
54
55    /// Returns the raw entity ID value.
56    #[must_use]
57    pub const fn raw(self) -> u32 {
58        self.0
59    }
60}
61
62impl From<u32> for EntityId {
63    fn from(id: u32) -> Self {
64        Self(id)
65    }
66}
67
68impl From<EntityId> for u32 {
69    fn from(id: EntityId) -> Self {
70        id.0
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    // SnapshotTick tests
79    #[test]
80    fn snapshot_tick_new() {
81        let tick = SnapshotTick::new(100);
82        assert_eq!(tick.raw(), 100);
83    }
84
85    #[test]
86    fn snapshot_tick_zero() {
87        let zero = SnapshotTick::new(0);
88        assert!(zero.is_zero());
89
90        let nonzero = SnapshotTick::new(1);
91        assert!(!nonzero.is_zero());
92    }
93
94    #[test]
95    fn snapshot_tick_from_u32() {
96        let tick: SnapshotTick = 42u32.into();
97        assert_eq!(tick.raw(), 42);
98    }
99
100    #[test]
101    fn snapshot_tick_into_u32() {
102        let tick = SnapshotTick::new(99);
103        let value: u32 = tick.into();
104        assert_eq!(value, 99);
105    }
106
107    #[test]
108    fn snapshot_tick_ordering() {
109        let t1 = SnapshotTick::new(1);
110        let t2 = SnapshotTick::new(2);
111        let t3 = SnapshotTick::new(2);
112
113        assert!(t1 < t2);
114        assert!(t2 > t1);
115        assert!(t2 == t3);
116        assert!(t2 >= t3);
117        assert!(t2 <= t3);
118    }
119
120    #[test]
121    fn snapshot_tick_hash() {
122        use std::collections::HashSet;
123        let mut set = HashSet::new();
124        set.insert(SnapshotTick::new(1));
125        set.insert(SnapshotTick::new(2));
126        set.insert(SnapshotTick::new(1)); // duplicate
127
128        assert_eq!(set.len(), 2);
129        assert!(set.contains(&SnapshotTick::new(1)));
130        assert!(set.contains(&SnapshotTick::new(2)));
131    }
132
133    #[test]
134    fn snapshot_tick_default() {
135        let tick = SnapshotTick::default();
136        assert_eq!(tick.raw(), 0);
137        assert!(tick.is_zero());
138    }
139
140    #[test]
141    fn snapshot_tick_equality() {
142        let t1 = SnapshotTick::new(100);
143        let t2 = SnapshotTick::new(100);
144        let t3 = SnapshotTick::new(101);
145
146        assert_eq!(t1, t2);
147        assert_ne!(t1, t3);
148    }
149
150    #[test]
151    fn snapshot_tick_clone_copy() {
152        let tick = SnapshotTick::new(42);
153        let copied = tick; // Copy
154        assert_eq!(tick, copied);
155    }
156
157    #[test]
158    fn snapshot_tick_debug() {
159        let tick = SnapshotTick::new(123);
160        let debug = format!("{tick:?}");
161        assert!(debug.contains("123"));
162    }
163
164    #[test]
165    fn snapshot_tick_const() {
166        const TICK: SnapshotTick = SnapshotTick::new(42);
167        assert_eq!(TICK.raw(), 42);
168    }
169
170    // EntityId tests
171    #[test]
172    fn entity_id_new() {
173        let id = EntityId::new(42);
174        assert_eq!(id.raw(), 42);
175    }
176
177    #[test]
178    fn entity_id_from_u32() {
179        let id: EntityId = 123u32.into();
180        assert_eq!(id.raw(), 123);
181    }
182
183    #[test]
184    fn entity_id_into_u32() {
185        let id = EntityId::new(99);
186        let value: u32 = id.into();
187        assert_eq!(value, 99);
188    }
189
190    #[test]
191    fn entity_id_ordering() {
192        let id1 = EntityId::new(1);
193        let id2 = EntityId::new(2);
194
195        assert!(id1 < id2);
196        assert!(id2 > id1);
197    }
198
199    #[test]
200    fn entity_id_hash() {
201        use std::collections::HashSet;
202        let mut set = HashSet::new();
203        set.insert(EntityId::new(1));
204        set.insert(EntityId::new(2));
205
206        assert!(set.contains(&EntityId::new(1)));
207        assert!(!set.contains(&EntityId::new(3)));
208    }
209
210    #[test]
211    fn entity_id_default() {
212        let id = EntityId::default();
213        assert_eq!(id.raw(), 0);
214    }
215
216    #[test]
217    fn entity_id_equality() {
218        let id1 = EntityId::new(42);
219        let id2 = EntityId::new(42);
220        let id3 = EntityId::new(43);
221
222        assert_eq!(id1, id2);
223        assert_ne!(id1, id3);
224    }
225
226    #[test]
227    fn entity_id_clone_copy() {
228        let id = EntityId::new(42);
229        let copied = id; // Copy
230        assert_eq!(id, copied);
231    }
232
233    #[test]
234    fn entity_id_const() {
235        const ID: EntityId = EntityId::new(999);
236        assert_eq!(ID.raw(), 999);
237    }
238}