/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ulid-1.2.1/src/generator.rs
Line | Count | Source |
1 | | use std::time::{Duration, SystemTime}; |
2 | | |
3 | | use std::fmt; |
4 | | |
5 | | use crate::Ulid; |
6 | | |
7 | | /// A Ulid generator that provides monotonically increasing Ulids |
8 | | pub struct Generator { |
9 | | previous: Ulid, |
10 | | } |
11 | | |
12 | | impl Generator { |
13 | | /// Create a new ulid generator for monotonically ordered ulids |
14 | | /// |
15 | | /// # Example |
16 | | /// ```rust |
17 | | /// use ulid::Generator; |
18 | | /// |
19 | | /// let mut gen = Generator::new(); |
20 | | /// |
21 | | /// let ulid1 = gen.generate().unwrap(); |
22 | | /// let ulid2 = gen.generate().unwrap(); |
23 | | /// |
24 | | /// assert!(ulid1 < ulid2); |
25 | | /// ``` |
26 | 0 | pub const fn new() -> Generator { |
27 | 0 | Generator { |
28 | 0 | previous: Ulid::nil(), |
29 | 0 | } |
30 | 0 | } |
31 | | |
32 | | /// Generate a new Ulid. Each call is guaranteed to provide a Ulid with a larger value than the |
33 | | /// last call. If the random bits would overflow, this method will return an error. |
34 | | /// |
35 | | /// ```rust |
36 | | /// use ulid::Generator; |
37 | | /// let mut gen = Generator::new(); |
38 | | /// |
39 | | /// let ulid1 = gen.generate().unwrap(); |
40 | | /// let ulid2 = gen.generate().unwrap(); |
41 | | /// |
42 | | /// assert!(ulid1 < ulid2); |
43 | | /// ``` |
44 | 0 | pub fn generate(&mut self) -> Result<Ulid, MonotonicError> { |
45 | 0 | self.generate_from_datetime(crate::time_utils::now()) |
46 | 0 | } |
47 | | |
48 | | /// Generate a new Ulid matching the given DateTime. |
49 | | /// Each call is guaranteed to provide a Ulid with a larger value than the last call. |
50 | | /// If the random bits would overflow, this method will return an error. |
51 | | /// |
52 | | /// # Example |
53 | | /// ```rust |
54 | | /// use ulid::Generator; |
55 | | /// use std::time::SystemTime; |
56 | | /// |
57 | | /// let dt = SystemTime::now(); |
58 | | /// let mut gen = Generator::new(); |
59 | | /// |
60 | | /// let ulid1 = gen.generate_from_datetime(dt).unwrap(); |
61 | | /// let ulid2 = gen.generate_from_datetime(dt).unwrap(); |
62 | | /// |
63 | | /// assert_eq!(ulid1.datetime(), ulid2.datetime()); |
64 | | /// assert!(ulid1 < ulid2); |
65 | | /// ``` |
66 | 0 | pub fn generate_from_datetime(&mut self, datetime: SystemTime) -> Result<Ulid, MonotonicError> { |
67 | 0 | self.generate_from_datetime_with_source(datetime, &mut rand::rng()) |
68 | 0 | } |
69 | | |
70 | | /// Generate a new monotonic increasing Ulid with the given source |
71 | | /// Each call is guaranteed to provide a Ulid with a larger value than the last call. |
72 | | /// If the random bits would overflow, this method will return an error. |
73 | | /// |
74 | | /// # Example |
75 | | /// ```rust |
76 | | /// use ulid::Generator; |
77 | | /// use ulid::Ulid; |
78 | | /// use std::time::SystemTime; |
79 | | /// use rand::prelude::*; |
80 | | /// |
81 | | /// let mut rng = StdRng::from_os_rng(); |
82 | | /// let mut gen = Generator::new(); |
83 | | /// |
84 | | /// let ulid1 = gen.generate_with_source(&mut rng).unwrap(); |
85 | | /// let ulid2 = gen.generate_with_source(&mut rng).unwrap(); |
86 | | /// |
87 | | /// assert!(ulid1 < ulid2); |
88 | | /// ``` |
89 | 0 | pub fn generate_with_source<R>(&mut self, source: &mut R) -> Result<Ulid, MonotonicError> |
90 | 0 | where |
91 | 0 | R: rand::Rng + ?Sized, |
92 | | { |
93 | 0 | self.generate_from_datetime_with_source(crate::time_utils::now(), source) |
94 | 0 | } |
95 | | |
96 | | /// Generate a new monotonic increasing Ulid with the given source matching the given DateTime |
97 | | /// Each call is guaranteed to provide a Ulid with a larger value than the last call. |
98 | | /// If the random bits would overflow, this method will return an error. |
99 | | /// |
100 | | /// # Example |
101 | | /// ```rust |
102 | | /// use ulid::Generator; |
103 | | /// use std::time::SystemTime; |
104 | | /// use rand::prelude::*; |
105 | | /// |
106 | | /// let dt = SystemTime::now(); |
107 | | /// let mut rng = StdRng::from_os_rng(); |
108 | | /// let mut gen = Generator::new(); |
109 | | /// |
110 | | /// let ulid1 = gen.generate_from_datetime_with_source(dt, &mut rng).unwrap(); |
111 | | /// let ulid2 = gen.generate_from_datetime_with_source(dt, &mut rng).unwrap(); |
112 | | /// |
113 | | /// assert_eq!(ulid1.datetime(), ulid2.datetime()); |
114 | | /// assert!(ulid1 < ulid2); |
115 | | /// ``` |
116 | 0 | pub fn generate_from_datetime_with_source<R>( |
117 | 0 | &mut self, |
118 | 0 | datetime: SystemTime, |
119 | 0 | source: &mut R, |
120 | 0 | ) -> Result<Ulid, MonotonicError> |
121 | 0 | where |
122 | 0 | R: rand::Rng + ?Sized, |
123 | | { |
124 | 0 | let last_ms = self.previous.timestamp_ms(); |
125 | | // maybe time went backward, or it is the same ms. |
126 | | // increment instead of generating a new random so that it is monotonic |
127 | 0 | if datetime |
128 | 0 | .duration_since(SystemTime::UNIX_EPOCH) |
129 | 0 | .unwrap_or(Duration::ZERO) |
130 | 0 | .as_millis() |
131 | 0 | <= u128::from(last_ms) |
132 | | { |
133 | 0 | if let Some(next) = self.previous.increment() { |
134 | 0 | self.previous = next; |
135 | 0 | return Ok(next); |
136 | | } else { |
137 | 0 | return Err(MonotonicError::Overflow); |
138 | | } |
139 | 0 | } |
140 | 0 | let next = Ulid::from_datetime_with_source(datetime, source); |
141 | 0 | self.previous = next; |
142 | 0 | Ok(next) |
143 | 0 | } |
144 | | } |
145 | | |
146 | | impl Default for Generator { |
147 | 0 | fn default() -> Self { |
148 | 0 | Self::new() |
149 | 0 | } |
150 | | } |
151 | | |
152 | | /// Error while trying to generate a monotonic increment in the same millisecond |
153 | | #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] |
154 | | pub enum MonotonicError { |
155 | | /// Would overflow into the next millisecond |
156 | | Overflow, |
157 | | } |
158 | | |
159 | | impl std::error::Error for MonotonicError {} |
160 | | |
161 | | impl fmt::Display for MonotonicError { |
162 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { |
163 | 0 | let text = match *self { |
164 | 0 | MonotonicError::Overflow => "Ulid random bits would overflow", |
165 | | }; |
166 | 0 | write!(f, "{}", text) |
167 | 0 | } |
168 | | } |
169 | | |
170 | | #[cfg(test)] |
171 | | mod tests { |
172 | | use super::*; |
173 | | use std::time::Duration; |
174 | | |
175 | | #[test] |
176 | | fn test_order_monotonic() { |
177 | | let dt = SystemTime::now(); |
178 | | let mut gen = Generator::new(); |
179 | | let ulid1 = gen.generate_from_datetime(dt).unwrap(); |
180 | | let ulid2 = gen.generate_from_datetime(dt).unwrap(); |
181 | | let ulid3 = Ulid::from_datetime(dt + Duration::from_millis(1)); |
182 | | assert_eq!(ulid1.0 + 1, ulid2.0); |
183 | | assert!(ulid2 < ulid3); |
184 | | assert!(ulid2.timestamp_ms() < ulid3.timestamp_ms()) |
185 | | } |
186 | | |
187 | | #[test] |
188 | | fn test_order_monotonic_with_source() { |
189 | | use rand::rngs::mock::StepRng; |
190 | | let mut source = StepRng::new(123, 0); |
191 | | let mut gen = Generator::new(); |
192 | | |
193 | | let _has_default = Generator::default(); |
194 | | |
195 | | let ulid1 = gen.generate_with_source(&mut source).unwrap(); |
196 | | let ulid2 = gen.generate_with_source(&mut source).unwrap(); |
197 | | assert!(ulid1 < ulid2); |
198 | | } |
199 | | |
200 | | #[test] |
201 | | fn can_display_things() { |
202 | | println!("{}", MonotonicError::Overflow); |
203 | | } |
204 | | } |