1#[cfg(feature = "ids")]
2pub fn uuid_v4() -> String {
3 uuid::Uuid::new_v4().to_string()
4}
5
6#[cfg(feature = "ids")]
7pub fn uuid_v7() -> String {
8 uuid::Uuid::now_v7().to_string()
9}
10
11#[cfg(feature = "ids")]
12pub fn ulid() -> String {
13 use std::time::{SystemTime, UNIX_EPOCH};
14 let now = SystemTime::now()
15 .duration_since(UNIX_EPOCH)
16 .unwrap()
17 .as_millis();
18 let chars: String = (0..10)
19 .map(|_| {
20 let idx = rand::random::<u8>() % 36;
21 let c = if idx < 10 {
22 b'0' + idx
23 } else {
24 b'A' + idx - 10
25 };
26 c as char
27 })
28 .collect();
29 format!("{:>016X}{}", now, chars)
30}
31
32#[cfg(feature = "ids")]
33pub fn is_uuid(s: &str) -> bool {
34 uuid::Uuid::parse_str(s).is_ok()
35}
36
37#[cfg(feature = "ids")]
38pub fn is_ulid(s: &str) -> bool {
39 s.len() == 26 && s.chars().all(|c| c.is_ascii_alphanumeric())
40}
41
42#[cfg(feature = "ids")]
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn test_uuid_v4() {
49 let u = uuid_v4();
50 assert_eq!(u.len(), 36);
51 }
52
53 #[test]
54 fn test_uuid_v7() {
55 let u = uuid_v7();
56 assert_eq!(u.len(), 36);
57 }
58
59 #[test]
60 fn test_ulid() {
61 let u = ulid();
62 assert_eq!(u.len(), 26);
63 }
64
65 #[test]
66 fn test_is_uuid() {
67 let u = uuid::Uuid::new_v4().to_string();
68 assert!(is_uuid(&u));
69 assert!(!is_uuid("not-a-uuid"));
70 }
71
72 #[test]
73 fn test_is_ulid() {
74 assert!(is_ulid("01ARZ3NDEKTSV4RRFFQ69G5FAV"));
75 assert!(!is_ulid("invalid"));
76 }
77}