1use rkyv::{Archive, Deserialize, Serialize};
4use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
5use std::fmt;
6use std::hash::Hash;
7
8macro_rules! define_id {
10 ($name:ident, $doc:expr) => {
11 #[doc = $doc]
12 #[derive(
13 Archive,
14 Deserialize,
15 Serialize,
16 SerdeDeserialize,
17 SerdeSerialize,
18 Clone,
19 Copy,
20 PartialEq,
21 Eq,
22 Hash,
23 Default,
24 )]
25 #[rkyv(compare(PartialEq))]
26 pub struct $name(pub u32);
27
28 impl $name {
29 #[inline]
31 pub const fn new(id: u32) -> Self {
32 Self(id)
33 }
34
35 #[inline]
37 pub const fn as_u32(&self) -> u32 {
38 self.0
39 }
40 }
41
42 impl fmt::Debug for $name {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 write!(f, "{}({})", stringify!($name), self.0)
45 }
46 }
47
48 impl fmt::Display for $name {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 write!(f, "{}", self.0)
51 }
52 }
53
54 impl From<u32> for $name {
55 fn from(id: u32) -> Self {
56 Self(id)
57 }
58 }
59
60 impl From<$name> for u32 {
61 fn from(id: $name) -> Self {
62 id.0
63 }
64 }
65 };
66}
67
68define_id!(RobotId, "Unique identifier for a robot");
69define_id!(NodeId, "Unique identifier for a map node");
70define_id!(EdgeId, "Unique identifier for a map edge");
71define_id!(StationId, "Unique identifier for a station");
72define_id!(RackId, "Unique identifier for a storage rack");
73define_id!(BinId, "Unique identifier for a storage bin");
74define_id!(SkuId, "Unique identifier for a SKU");
75define_id!(OrderId, "Unique identifier for an order");
76define_id!(TaskId, "Unique identifier for a task");
77define_id!(EventId, "Unique identifier for a scheduled event");
78define_id!(
79 ShipmentId,
80 "Unique identifier for an inbound/outbound shipment"
81);
82define_id!(
83 ChargingStationId,
84 "Unique identifier for a charging station"
85);
86define_id!(
87 MaintenanceStationId,
88 "Unique identifier for a maintenance station"
89);
90
91#[derive(Debug, Clone, Default)]
93pub struct IdGenerator<T> {
94 next: u32,
95 _marker: std::marker::PhantomData<T>,
96}
97
98impl<T> IdGenerator<T> {
99 pub fn new() -> Self {
101 Self {
102 next: 0,
103 _marker: std::marker::PhantomData,
104 }
105 }
106
107 pub fn starting_from(start: u32) -> Self {
109 Self {
110 next: start,
111 _marker: std::marker::PhantomData,
112 }
113 }
114
115 pub fn peek(&self) -> u32 {
117 self.next
118 }
119}
120
121macro_rules! impl_id_generator {
122 ($id_type:ident) => {
123 impl IdGenerator<$id_type> {
124 pub fn next_id(&mut self) -> $id_type {
126 let id = $id_type(self.next);
127 self.next += 1;
128 id
129 }
130 }
131 };
132}
133
134impl_id_generator!(RobotId);
135impl_id_generator!(NodeId);
136impl_id_generator!(EdgeId);
137impl_id_generator!(StationId);
138impl_id_generator!(RackId);
139impl_id_generator!(BinId);
140impl_id_generator!(SkuId);
141impl_id_generator!(OrderId);
142impl_id_generator!(TaskId);
143impl_id_generator!(EventId);
144impl_id_generator!(ShipmentId);
145impl_id_generator!(ChargingStationId);
146impl_id_generator!(MaintenanceStationId);
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151
152 #[test]
153 fn test_id_generation() {
154 let mut gen = IdGenerator::<RobotId>::new();
155 assert_eq!(gen.next_id(), RobotId(0));
156 assert_eq!(gen.next_id(), RobotId(1));
157 assert_eq!(gen.next_id(), RobotId(2));
158 }
159
160 #[test]
161 fn test_id_equality() {
162 let id1 = RobotId(42);
163 let id2 = RobotId(42);
164 let id3 = RobotId(43);
165 assert_eq!(id1, id2);
166 assert_ne!(id1, id3);
167 }
168}