1use std::time::{Duration, SystemTime};
2use crate::{Label, NoLabel, Sid};
3
4pub struct MonotonicGenerator<T = NoLabel> {
5 previous: Sid<T>,
6}
7
8impl<T: Label> MonotonicGenerator<T> {
9 pub fn new() -> Self {
10 Self {
11 previous: Sid::<T>::null(),
12 }
13 }
14
15 pub fn generate(&mut self) -> Sid<T> {
16 let now = SystemTime::now();
17 self.generate_from_datetime(now)
18 }
19
20 pub fn generate_from_datetime(&mut self, datetime: SystemTime) -> Sid<T> {
21 self.generate_from_datetime_with_source(datetime, &mut rand::thread_rng())
22 }
23
24 pub fn generate_from_datetime_with_source<R>(
25 &mut self,
26 datetime: SystemTime,
27 source: &mut R,
28 ) -> Sid<T>
29 where
30 R: rand::Rng,
31 {
32 let last_ms = self.previous.timestamp();
33 let ts = datetime
36 .duration_since(SystemTime::UNIX_EPOCH)
37 .unwrap_or(Duration::ZERO)
38 .as_millis() as u64;
39 let next = if ts <= last_ms {
40 self.previous.increment()
41 } else {
42 Sid::from_timestamp_with_rng(ts, source)
43 };
44 self.previous = next.clone();
45 next
46 }
47}