1use crate::{Error, SigId26, COUNTER_MAX, EPOCH, TIMESTAMP_MAX, WORKER_MAX};
17
18#[derive(Debug, Clone)]
20pub struct Generator {
21 seed: u64,
22 last_ms: u64,
23 counter: u16,
24 worker_id: u16,
25}
26
27impl Generator {
28 pub const fn new(seed: u64) -> Self {
30 let seed = if seed == 0 { 0x9e3779b97f4a7c15 } else { seed };
32 Self {
33 seed,
34 last_ms: 0,
35 counter: 0,
36 worker_id: 0,
37 }
38 }
39
40 pub const fn with_worker_id(seed: u64, worker_id: u16) -> Self {
42 let seed = if seed == 0 { 0x9e3779b97f4a7c15 } else { seed };
43 Self {
44 seed,
45 last_ms: 0,
46 counter: 0,
47 worker_id: worker_id & WORKER_MAX,
48 }
49 }
50
51 pub const fn set_worker_id(mut self, worker_id: u16) -> Self {
53 self.worker_id = worker_id & WORKER_MAX;
54 self
55 }
56
57 pub const fn get_worker_id(&self) -> u16 {
59 self.worker_id
60 }
61
62 pub fn reset(&mut self) {
64 self.counter = 0;
65 self.last_ms = 0;
66 }
67
68 pub fn generate(&mut self, ms: u64) -> Result<SigId26, Error> {
70 let timestamp = ms.saturating_sub(EPOCH);
71
72 if timestamp > TIMESTAMP_MAX {
74 return Err(Error::TimestampOverflow);
75 }
76
77 if ms == self.last_ms {
79 if self.counter >= COUNTER_MAX {
81 return self.wait_for_next_ms(ms);
82 }
83 self.counter += 1;
84 } else {
85 self.last_ms = ms;
86 self.counter = 0;
87 }
88
89 let random = self.next_random();
90
91 Ok(SigId26::raw_new_with_worker(
93 timestamp,
94 self.worker_id,
95 self.counter,
96 random,
97 ))
98 }
99
100 fn wait_for_next_ms(&mut self, _ms: u64) -> Result<SigId26, Error> {
102 #[cfg(not(feature = "std"))]
104 {
105 return Err(Error::CounterOverflow);
106 }
107
108 #[cfg(feature = "std")]
110 {
111 use std::time::{SystemTime, UNIX_EPOCH};
112
113 let now_ms = SystemTime::now()
114 .duration_since(UNIX_EPOCH)
115 .map_err(|_| Error::TimestampOverflow)?
116 .as_millis() as u64;
117
118 if now_ms <= self.last_ms {
122 return Err(Error::CounterOverflow);
123 }
124
125 self.last_ms = now_ms;
127 self.counter = 0;
128 let timestamp = now_ms.saturating_sub(EPOCH);
129 let random = self.next_random();
130 Ok(SigId26::raw_new_with_worker(
131 timestamp,
132 self.worker_id,
133 self.counter,
134 random,
135 ))
136 }
137 }
138
139 fn next_random(&mut self) -> u64 {
141 let mut x = self.seed;
142 x ^= x << 13;
143 x ^= x >> 7;
144 x ^= x << 17;
145 self.seed = x;
146 x
147 }
148}
149
150impl Default for Generator {
151 fn default() -> Self {
152 Self::new(0x9e3779b97f4a7c15)
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn test_generator_worker_id() {
162 let mut gen = Generator::with_worker_id(0x123456789abcdef, 0x1234);
163 assert_eq!(gen.get_worker_id(), 0x1234);
164
165 let id = gen.generate(1234567890).unwrap();
166 assert_eq!(id.worker_id(), 0x1234);
167 }
168
169 #[test]
170 fn test_generator_counter_increment() {
171 let mut gen = Generator::new(0x123456789abcdef);
172 let ms = 1234567890;
173
174 let id1 = gen.generate(ms).unwrap();
175 let id2 = gen.generate(ms).unwrap();
176
177 assert_eq!(id2.counter(), id1.counter() + 1);
178 }
179
180 #[test]
181 fn test_generator_timestamp() {
182 let mut gen = Generator::new(0x123456789abcdef);
183 let ms = 1700000000000;
184 let id = gen.generate(ms).unwrap();
185 assert_eq!(id.timestamp_ms(), ms);
186 }
187
188 #[test]
189 fn test_counter_overflow() {
190 let mut gen = Generator::new(0x123456789abcdef);
191
192 let ms = 32503680000000u64;
196
197 for i in 0..=COUNTER_MAX {
199 let result = gen.generate(ms);
200 assert!(result.is_ok(), "Unexpected error at iteration {}", i);
201 }
202
203 let result = gen.generate(ms);
206
207 assert!(
208 result.is_err(),
209 "Expected CounterOverflow error after {} generated IDs",
210 COUNTER_MAX + 1
211 );
212 match result {
213 Err(Error::CounterOverflow) => {}
214 _ => panic!("Expected CounterOverflow error, got {:?}", result),
215 }
216 }
217
218 #[cfg(feature = "std")]
219 #[test]
220 fn test_generator_now() {
221 let mut gen = Generator::new(0x123456789abcdef);
222 let id = gen.generate(1700000000000).unwrap();
223 assert!(id.is_valid());
224 }
225}