1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//! # Robust and Hassle-Free ULIDs
//!
//! This crate provides an implementation of ULIDs (Universally Unique Lexicographically Sortable Identifiers)
//! with an emphasis on correctness, resilience, and hassle-free usability, in that order.
//! It enables the generation and manipulation of ULIDs that are guaranteed to be unique
//! and strictly monotonically increasing in any circumstances.
//!
//! ## Generating ULIDs
//!
//! ULIDs are generated using the [`Ulid::new()`] method:
//!
//! ```
//! use mr_ulid::Ulid;
//!
//! let u = Ulid::new();
//! ```
//!
//! Each ULID generated is guaranteed to be unique and strictly monotonically increasing.
//! The generation is thread-safe, maintaining all guarantees even when ULIDs are produced
//! concurrently across multiple threads.
//!
//! ## Printing ULIDs and converting to Strings
//!
//! ULIDs implement the [`std::fmt::Display`] trait:
//!
//! ```
//! use mr_ulid::Ulid;
//!
//! let u = Ulid::new();
//!
//! println!("Generated ULID: {u}");
//!
//! let s = u.to_string();
//!
//! ```
//!
//! ## Parsing ULIDs from Strings:
//!
//! ULIDs implements the [`std::str::FromStr`] trait and can be parsed with [`str::parse()`] method:
//!
//! ```
//! # use std::error::Error;
//! # fn main() -> Result<(), Box<dyn Error>> {
//! use mr_ulid::Ulid;
//!
//! // Method A
// cspell:disable-next-line
//! let u1: Ulid = "01JB5C84ZBM8QVBE5QRZW6HY89".parse()?;
//!
//! // Method B
// cspell:disable-next-line
//! let u2 = "01JB5C84ZBM8QVBE5QRZW6HY89".parse::<Ulid>()?;
//! # Ok(()) }
//! ```
//!
//! ## Serializing and Deserializing using `Serde` (JSON)
//!
//! For serializing/deserializing the feature flag `serde` needs to be enabled:
//!
//! ```bash
//! cargo add mr-ulid -F serde
//! ```
//!
//! Once the `serde` feature is enabled, ULIDs implement the `Serialize` and `Deserialize` traits:
//!
//! ```
//! # use std::error::Error;
//! # fn main() -> Result<(), Box<dyn Error>> {
//! # #[cfg(feature = "serde")]
//! # {
//! use mr_ulid::Ulid;
//! # use serde_derive as serde;
//! use serde::{Deserialize, Serialize};
//!
//! #[derive(Serialize, Deserialize, PartialEq, Debug)]
//! struct Example {
//! id: Ulid,
//! data: String,
//! }
//!
//! let e1 = Example {
//! id: Ulid::new(),
//! data: "Hello, World!".to_string(),
//! };
//!
//! let s = serde_json::to_string(&e1)?;
//!
//! println!("JSON: {s}");
//!
//! let e2: Example = serde_json::from_str(&s)?;
//!
//! assert_eq!(e1, e2);
//! # }
//! # Ok(()) }
//! ```
//!
//! ## Guarantees
//!
//! A notable feature of this crate is the guarantee that a sufficient number
//! of ULIDs can be generated at any time without the random part overflowing
//! and the guarantees of uniqueness and strict monotonicity is maintained
//! under all circumstances.
//!
//! The 80-bit random component of a ULID is slightly reduced by 10<sup>10</sup> values,
//! resulting in a negligible reduction in entropy of approximately 0.000000000001%.
//! This ensures that at least 10<sup>10</sup> ULIDs can be generated per _millisecond_,
//! equating to 10<sup>13</sup> ULIDs per _second_.
//! Such capacity exceeds the capabilities of current systems by magnitudes.
//!
//! In the very unlikely event that a system could generate more than 10<sup>13</sup> ULIDs
//! per second, any overflowing random part is projected into the next millisecond.
//! There, the full range of 2<sup>80</sup> (ca. 10<sup>24</sup>) is available.
//!
//! ## ULID Types
//!
//! - [`Ulid`]: This is the preferred type for most use cases and represents a ULID that can never be zero.
//! - [`ZeroableUlid`]: This alternative type allows for zero values ULIDs (e.g., `"00000000000000000000000000"`).
//!
//! In idiomatic Rust code, if an absent ULID is needed, it is best represented as [`Option<Ulid>`](Ulid).
//! However, for use cases that may represent absent ULIDs with a zero ULID,
//! the [`ZeroableUlid`] may be an easier choice.
//!
//! ## Feature Flags
//!
//! - **`rand`**: Utilizes the `rand` crate as the source for random numbers, enabled by default.
//! - **`serde`**: Provides support for serialization and deserialization via `Serde`, optional.
//!
use Cow;
pub use Error;
pub use STANDARD_ENTROPY_SOURCE;
pub use ;
pub use Ulid;
pub use ZeroableUlid;
const RESERVED: u128 = 10_000_000_000;
const RANDOM_BITS: u32 = 80;
const RANDOM_MASK: u128 = - 1;
const RANDOM_GEN_MAX: u128 = RANDOM_MASK - RESERVED;
const TIMESTAMP_BITS: u32 = 48;
const TIMESTAMP_MAX: u64 = - 1;
const TIMESTAMP_MASK: u128 = << RANDOM_BITS;
/// Canonicalizes a ULID string by converting it to a standard format.
///
/// Takes a ULID string and returns the canonicalized version:
/// Letters 'i', 'l', and 'o' are replaced by their corresponding digits '1' and `0`,
/// and all characters are converted into uppercase.
///
/// If the input is already in canonical form, it returns a borrowed version of the input string
/// without allocating a new `String`.
///
/// # Errors
///
/// The string must be a valid ULID. It must have the correct length (26) and contain only valid characters,
/// and it is not to be overflowed. If not, an error is returned.
///
/// # Example
///
/// ```
// cspell:disable-next-line
/// let s = "olixjazthsfjzt7wd6j8ir92vn";
///
// cspell:disable-next-line
/// assert_eq!(mr_ulid::canonicalize(s), Ok("011XJAZTHSFJZT7WD6J81R92VN".into()));
/// ```
///
/// Checks a ULID string for validity.
///
/// To be valid, a ULID must have the correct length (26) and contain only valid characters,
/// and not overflowed.
///
/// It is not checked, if the ULID has a zero value or if the ULID is in its canonical form.
///
/// # Errors
///
/// If the ULID string is not valid, an appropriate error is returned.
///
/// # Example
///
/// ```
// cspell:disable-next-line
/// assert!(mr_ulid::validate("olixjazthsfjzt7wd6j8ir92vn").is_ok());
// cspell:disable-next-line
/// assert!(mr_ulid::validate("011XJAZTHSFJZT7WD6J81R92VN").is_ok());
///
/// assert!(mr_ulid::validate("00000000000000000000000000").is_ok());
/// assert!(mr_ulid::validate("7FFFFFFFFFFFFFFFFFFFFFFFFF").is_ok());
/// assert_eq!(mr_ulid::validate("80000000000000000000000000"), Err(mr_ulid::Error::InvalidChar));
///
/// assert_eq!(mr_ulid::validate("0000000000000000000000u89$"), Err(mr_ulid::Error::InvalidChar));
/// assert_eq!(mr_ulid::validate("xxxxxxxxxxxxxxxxxxxxxx"), Err(mr_ulid::Error::TooShort));
/// assert_eq!(mr_ulid::validate("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), Err(mr_ulid::Error::TooLong));
/// ```