#[cfg(feature = "ids")]
pub fn uuid_v4() -> String {
uuid::Uuid::new_v4().to_string()
}
#[cfg(feature = "ids")]
pub fn uuid_v7() -> String {
uuid::Uuid::now_v7().to_string()
}
#[cfg(feature = "ids")]
pub fn ulid() -> String {
use std::time::{SystemTime, UNIX_EPOCH};
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis();
let chars: String = (0..10)
.map(|_| {
let idx = rand::random::<u8>() % 36;
let c = if idx < 10 {
b'0' + idx
} else {
b'A' + idx - 10
};
c as char
})
.collect();
format!("{:>016X}{}", now, chars)
}
#[cfg(feature = "ids")]
pub fn is_uuid(s: &str) -> bool {
uuid::Uuid::parse_str(s).is_ok()
}
#[cfg(feature = "ids")]
pub fn is_ulid(s: &str) -> bool {
s.len() == 26 && s.chars().all(|c| c.is_ascii_alphanumeric())
}
#[cfg(feature = "ids")]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_uuid_v4() {
let u = uuid_v4();
assert_eq!(u.len(), 36);
}
#[test]
fn test_uuid_v7() {
let u = uuid_v7();
assert_eq!(u.len(), 36);
}
#[test]
fn test_ulid() {
let u = ulid();
assert_eq!(u.len(), 26);
}
#[test]
fn test_is_uuid() {
let u = uuid::Uuid::new_v4().to_string();
assert!(is_uuid(&u));
assert!(!is_uuid("not-a-uuid"));
}
#[test]
fn test_is_ulid() {
assert!(is_ulid("01ARZ3NDEKTSV4RRFFQ69G5FAV"));
assert!(!is_ulid("invalid"));
}
}