sid/
monotonic.rs

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        // maybe time went backward, or it is the same ms.
34        // increment instead of generating a new random so that it is monotonic
35        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}