1use core::fmt;
9use core::num::NonZeroU32;
10
11#[repr(transparent)]
13#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
14pub struct VariableId(u32);
15
16impl VariableId {
17 #[must_use]
22 pub const fn from_raw(raw: u32) -> Self {
23 Self(raw)
24 }
25
26 #[must_use]
28 pub const fn raw(self) -> u32 {
29 self.0
30 }
31
32 #[must_use]
34 pub const fn as_usize(self) -> usize {
35 self.0 as usize
36 }
37}
38
39impl fmt::Display for VariableId {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 write!(f, "V{}", self.0)
42 }
43}
44
45#[repr(transparent)]
47#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
48pub struct EnvironmentId(u32);
49
50impl EnvironmentId {
51 #[must_use]
53 pub const fn from_raw(raw: u32) -> Self {
54 Self(raw)
55 }
56
57 #[must_use]
59 pub const fn raw(self) -> u32 {
60 self.0
61 }
62}
63
64impl fmt::Display for EnvironmentId {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 write!(f, "E{}", self.0)
67 }
68}
69
70#[repr(transparent)]
74#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
75pub struct DynamicRuleId(u32);
76
77impl DynamicRuleId {
78 #[must_use]
80 pub const fn from_raw(raw: u32) -> Self {
81 Self(raw)
82 }
83
84 #[must_use]
86 pub const fn raw(self) -> u32 {
87 self.0
88 }
89}
90
91impl fmt::Display for DynamicRuleId {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 write!(f, "DR{}", self.0)
94 }
95}
96
97#[repr(transparent)]
101#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
102pub struct DistributionRef(u32);
103
104impl DistributionRef {
105 #[must_use]
107 pub const fn from_raw(raw: u32) -> Self {
108 Self(raw)
109 }
110
111 #[must_use]
113 pub const fn raw(self) -> u32 {
114 self.0
115 }
116}
117
118impl fmt::Display for DistributionRef {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 write!(f, "DRef{}", self.0)
121 }
122}
123
124#[repr(transparent)]
126#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
127pub struct RegimeId(u32);
128
129impl RegimeId {
130 #[must_use]
132 pub const fn from_raw(raw: u32) -> Self {
133 Self(raw)
134 }
135
136 #[must_use]
138 pub const fn raw(self) -> u32 {
139 self.0
140 }
141}
142
143impl fmt::Display for RegimeId {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 write!(f, "R{}", self.0)
146 }
147}
148
149#[repr(transparent)]
155#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
156pub struct Lag(u32);
157
158impl Lag {
159 pub const CONTEMPORANEOUS: Self = Self(0);
161
162 #[must_use]
164 pub const fn from_raw(raw: u32) -> Self {
165 Self(raw)
166 }
167
168 #[must_use]
170 pub const fn historical(steps: NonZeroU32) -> Self {
171 Self(steps.get())
172 }
173
174 #[must_use]
176 pub const fn raw(self) -> u32 {
177 self.0
178 }
179
180 #[must_use]
182 pub const fn is_contemporaneous(self) -> bool {
183 self.0 == 0
184 }
185}
186
187impl fmt::Display for Lag {
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 write!(f, "L{}", self.0)
190 }
191}
192
193#[repr(transparent)]
198#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
199pub struct ComponentId(VariableId);
200
201impl ComponentId {
202 #[must_use]
204 pub const fn from_variable(variable: VariableId) -> Self {
205 Self(variable)
206 }
207
208 #[must_use]
210 pub const fn variable(self) -> VariableId {
211 self.0
212 }
213
214 #[must_use]
216 pub const fn from_raw(raw: u32) -> Self {
217 Self(VariableId::from_raw(raw))
218 }
219
220 #[must_use]
222 pub const fn raw(self) -> u32 {
223 self.0.raw()
224 }
225
226 #[must_use]
228 pub const fn as_usize(self) -> usize {
229 self.0.as_usize()
230 }
231}
232
233impl fmt::Display for ComponentId {
234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235 write!(f, "C{}", self.0.raw())
236 }
237}
238
239impl From<VariableId> for ComponentId {
240 fn from(variable: VariableId) -> Self {
241 Self::from_variable(variable)
242 }
243}
244
245#[repr(transparent)]
247#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
248pub struct CategoryDomainId(u32);
249
250impl CategoryDomainId {
251 #[must_use]
253 pub const fn from_raw(raw: u32) -> Self {
254 Self(raw)
255 }
256
257 #[must_use]
259 pub const fn raw(self) -> u32 {
260 self.0
261 }
262}
263
264impl fmt::Display for CategoryDomainId {
265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266 write!(f, "C{}", self.0)
267 }
268}
269
270#[repr(transparent)]
272#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
273pub struct QueryId(u32);
274
275impl QueryId {
276 #[must_use]
278 pub const fn from_raw(raw: u32) -> Self {
279 Self(raw)
280 }
281
282 #[must_use]
284 pub const fn raw(self) -> u32 {
285 self.0
286 }
287
288 #[must_use]
290 pub const fn as_usize(self) -> usize {
291 self.0 as usize
292 }
293}
294
295impl fmt::Display for QueryId {
296 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
297 write!(f, "Q{}", self.0)
298 }
299}
300
301#[repr(transparent)]
303#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
304pub struct ModelId(u32);
305
306impl ModelId {
307 #[must_use]
309 pub const fn from_raw(raw: u32) -> Self {
310 Self(raw)
311 }
312
313 #[must_use]
315 pub const fn raw(self) -> u32 {
316 self.0
317 }
318
319 #[must_use]
321 pub const fn as_usize(self) -> usize {
322 self.0 as usize
323 }
324}
325
326impl fmt::Display for ModelId {
327 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328 write!(f, "M{}", self.0)
329 }
330}
331
332#[repr(transparent)]
334#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
335pub struct StateVersion(u64);
336
337impl StateVersion {
338 pub const ZERO: Self = Self(0);
340
341 #[must_use]
343 pub const fn from_raw(raw: u64) -> Self {
344 Self(raw)
345 }
346
347 #[must_use]
349 pub const fn raw(self) -> u64 {
350 self.0
351 }
352
353 #[must_use]
355 pub const fn next(self) -> Self {
356 Self(self.0.wrapping_add(1))
357 }
358}
359
360impl fmt::Display for StateVersion {
361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362 write!(f, "S{}", self.0)
363 }
364}
365
366#[cfg(test)]
367mod tests {
368 use super::*;
369 use core::mem::size_of;
370
371 #[test]
372 fn ids_are_copyable_and_compact() {
373 assert_eq!(size_of::<VariableId>(), 4);
374 assert_eq!(size_of::<EnvironmentId>(), 4);
375 assert_eq!(size_of::<DynamicRuleId>(), 4);
376 assert_eq!(size_of::<DistributionRef>(), 4);
377 assert_eq!(size_of::<RegimeId>(), 4);
378 assert_eq!(size_of::<Lag>(), 4);
379 assert_eq!(size_of::<CategoryDomainId>(), 4);
380 assert_eq!(size_of::<ComponentId>(), 4);
381 assert_eq!(size_of::<QueryId>(), 4);
382 assert_eq!(size_of::<ModelId>(), 4);
383 assert_eq!(size_of::<StateVersion>(), 8);
384 }
385
386 #[test]
387 fn lag_zero_is_contemporaneous() {
388 assert!(Lag::CONTEMPORANEOUS.is_contemporaneous());
389 assert!(!Lag::historical(NonZeroU32::new(1).expect("nonzero")).is_contemporaneous());
390 }
391}