Loading page…
Rust walkthroughs
Loading page…
The uuid crate provides facilities for generating and parsing Universally Unique Identifiers (UUIDs). A UUID is a 128-bit number used to identify information in computer systems. The crate supports multiple UUID versions: v1 (timestamp-based), v3 (MD5 hash-based), v4 (random), v5 (SHA-1 hash-based), v6 (sortable timestamp-based), and v7 (time-ordered). UUIDs are essential for database primary keys, distributed systems, session identifiers, and anywhere you need unique identifiers without central coordination.
Key concepts:
# Cargo.toml
[dependencies]
uuid = { version = "1.0", features = ["v4", "v7", "serde"] }use uuid::Uuid;
fn main() {
// Generate a random UUID (v4)
let id = Uuid::new_v4();
println!("Random UUID: {}", id);
// Generate a time-ordered UUID (v7)
let time_id = Uuid::now_v7();
println!("Time-ordered UUID: {}", time_id);
}use uuid::Uuid;
fn main() {
// v4: Random UUID (most common)
let v4 = Uuid::new_v4();
println!("v4 (random): {}", v4);
// Requires "v7" feature
let v7 = Uuid::now_v7();
println!("v7 (time-ordered): {}", v7);
// Nil UUID (all zeros)
let nil = Uuid::nil();
println!("Nil: {}", nil);
// Check properties
println!("Is nil: {}", nil.is_nil());
println!("Version: {:?}", v4.get_version());
println!("Variant: {:?}", v4.get_variant());
}use uuid::Uuid;
fn main() {
// v1: Timestamp + MAC address (requires "v1" feature)
// Not recommended due to privacy concerns with MAC address exposure
// let v1 = Uuid::new_v1(timestamp, node_id);
// v3: MD5 hash of namespace + name (requires "v3" feature)
// Deterministic - same input always produces same UUID
// let v3 = Uuid::new_v3(namespace, name);
// v4: Random (requires "v4" feature)
// Best for general use when you don't need determinism
let v4 = Uuid::new_v4();
println!("v4 random: {}", v4);
// v5: SHA-1 hash of namespace + name (requires "v5" feature)
// Better than v3 (stronger hash), deterministic
// let v5 = Uuid::new_v5(namespace, name);
// v6: Field-compatible with v1 but sortable (requires "v6" feature)
// let v6 = Uuid::new_v6(timestamp, node_id);
// v7: Time-ordered (requires "v7" feature)
// Best for database primary keys - naturally sortable by time
let v7 = Uuid::now_v7();
println!("v7 time-ordered: {}", v7);
// v8: Custom UUID (requires "v8" feature)
// For application-specific UUID formats
// let v8 = Uuid::new_v8(custom_bytes);
}use uuid::Uuid;
fn main() {
// Parse from standard hyphenated format
let parsed = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000");
match parsed {
Ok(uuid) => println!("Parsed: {}", uuid),
Err(e) => println!("Parse error: {}", e),
}
// Parse from simple format (no hyphens)
let simple = Uuid::parse_str("550e8400e29b41d4a716446655440000");
println!("Simple parse: {:?}", simple);
// Parse from URN format
let urn = Uuid::parse_str("urn:uuid:550e8400-e29b-41d4-a716-446655440000");
println!("URN parse: {:?}", urn);
// Parse from braced format
let braced = Uuid::parse_str("{550e8400-e29b-41d4-a716-446655440000}");
println!("Braced parse: {:?}", braced);
// Use try_into for parsing
let uuid: Result<Uuid, _> = "550e8400-e29b-41d4-a716-446655440000".parse();
println!("Using parse: {:?}", uuid);
}use uuid::Uuid;
fn main() {
let uuid = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
// Default Display (hyphenated, lowercase)
println!("Hyphenated: {}", uuid);
// Hyphenated, uppercase
println!("Upper: {}", uuid.hyphenated().to_uppercase());
// Simple (no hyphens)
println!("Simple: {}", uuid.simple());
// URN format
println!("URN: {}", uuid.urn());
// Braced format
println!("Braced: {}", uuid.braced());
}use uuid::{Uuid, uuid};
fn main() {
// Use a namespace UUID
let namespace = Uuid::NAMESPACE_DNS;
// Generate a deterministic UUID from "example.com"
let uuid1 = Uuid::new_v5(namespace, b"example.com");
println!("UUID for example.com: {}", uuid1);
// Same input always produces same UUID
let uuid2 = Uuid::new_v5(namespace, b"example.com");
assert_eq!(uuid1, uuid2);
println!("Deterministic: uuid1 == uuid2");
// Different input produces different UUID
let uuid3 = Uuid::new_v5(namespace, b"different.com");
assert_ne!(uuid1, uuid3);
println!("UUID for different.com: {}", uuid3);
// Standard namespaces
println!("DNS namespace: {}", Uuid::NAMESPACE_DNS);
println!("URL namespace: {}", Uuid::NAMESPACE_URL);
println!("OID namespace: {}", Uuid::NAMESPACE_OID);
println!("X500 namespace: {}", Uuid::NAMESPACE_X500);
}use uuid::Uuid;
fn main() {
// Create a custom namespace for your application
let app_namespace = Uuid::new_v4();
println!("App namespace: {}", app_namespace);
// Now you can generate deterministic UUIDs for your entities
let user_id = Uuid::new_v5(app_namespace, b"user:12345");
println!("User 12345 UUID: {}", user_id);
let order_id = Uuid::new_v5(app_namespace, b"order:67890");
println!("Order 67890 UUID: {}", order_id);
// Same names always produce same UUIDs
let user_id_again = Uuid::new_v5(app_namespace, b"user:12345");
assert_eq!(user_id, user_id_again);
}use uuid::Uuid;
use std::thread;
use std::time::Duration;
fn main() {
let mut uuids = Vec::new();
// Generate several UUIDs over time
for i in 0..5 {
let uuid = Uuid::now_v7();
uuids.push(uuid);
println!("UUID {}: {}", i, uuid);
thread::sleep(Duration::from_millis(10));
}
// v7 UUIDs are sortable by creation time
let mut sorted = uuids.clone();
sorted.sort();
println!("\nOriginal order matches sorted order:");
for (original, sorted) in uuids.iter().zip(sorted.iter()) {
println!(" {} == {} ? {}", original, sorted, original == sorted);
}
}use uuid::Uuid;
fn main() {
let uuid = Uuid::now_v7();
println!("UUID v7: {}", uuid);
// Extract the timestamp
if let Some(ts) = uuid.get_timestamp() {
println!("Timestamp: {:?}", ts);
// Convert to Unix timestamp
let seconds = ts.to_unix();
println!("Unix timestamp: {} seconds, {} nanos", seconds.secs, seconds.nanos);
// Convert to SystemTime
let time = std::time::SystemTime::from(ts);
println!("SystemTime: {:?}", time);
}
}use uuid::Uuid;
fn main() {
let uuid = Uuid::new_v4();
println!("UUID: {}", uuid);
// Get as bytes array
let bytes = uuid.as_bytes();
println!("Bytes: {:?}", bytes);
println!("Length: {} bytes", bytes.len());
// Create from bytes
let from_bytes = Uuid::from_bytes(*bytes);
println!("From bytes: {}", from_bytes);
// Get as u128
let as_u128 = uuid.as_u128();
println!("As u128: {}", as_u128);
// Create from u128
let from_u128 = Uuid::from_u128(as_u128);
println!("From u128: {}", from_u128);
// Get as two u64s
let (high, low) = uuid.as_u64_pair();
println!("High: {}, Low: {}", high, low);
}// Cargo.toml:
// uuid = { version = "1.0", features = ["v4", "serde"] }
use uuid::Uuid;
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]
struct User {
id: Uuid,
name: String,
}
fn main() {
let user = User {
id: Uuid::new_v4(),
name: "Alice".to_string(),
};
// Serialize to JSON
let json = serde_json::to_string(&user).unwrap();
println!("JSON: {}", json);
// Deserialize from JSON
let parsed: User = serde_json::from_str(&json).unwrap();
println!("Parsed: {:?}", parsed);
}// Cargo.toml:
// uuid = { version = "1.0", features = ["v4", "serde"] }
use serde::{Serialize, Deserialize};
use uuid::Uuid;
#[derive(Debug, Serialize, Deserialize)]
struct Document {
// Default: hyphenated string
#[serde(default)]
id: Uuid,
// Simple format (no hyphens)
#[serde(with = "uuid::serde::simple")]
simple_id: Uuid,
// URN format
#[serde(with = "uuid::serde::urn")]
urn_id: Uuid,
// Braced format
#[serde(with = "uuid::serde::braced")]
braced_id: Uuid,
}
fn main() {
let doc = Document {
id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
simple_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
urn_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
braced_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
};
let json = serde_json::to_string_pretty(&doc).unwrap();
println!("{}", json);
}// Example with sqlx (requires "sqlx" feature or manual implementation)
use uuid::Uuid;
// Hypothetical database record
#[derive(Debug)]
struct User {
id: Uuid,
email: String,
created_at: chrono::DateTime<chrono::Utc>,
}
impl User {
fn new(email: String) -> Self {
Self {
id: Uuid::new_v4(), // or Uuid::now_v7() for sortable keys
email,
created_at: chrono::Utc::now(),
}
}
}
fn main() {
let user = User::new("alice@example.com".to_string());
println!("User ID: {}", user.id);
println!("Email: {}", user.email);
println!("Created: {}", user.created_at);
// UUID v7 is ideal for database primary keys
let id_v7 = Uuid::now_v7();
println!("\nv7 for database: {}", id_v7);
println!("Sorts naturally by creation time");
}use uuid::Uuid;
fn main() {
let uuid1 = Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap();
let uuid2 = Uuid::parse_str("00000000-0000-0000-0000-000000000002").unwrap();
let uuid3 = Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap();
// Comparison
println!("uuid1 == uuid3: {}", uuid1 == uuid3);
println!("uuid1 < uuid2: {}", uuid1 < uuid2);
// Sorting
let mut uuids = vec![uuid2, uuid1, uuid3];
uuids.sort();
uuids.dedup(); // Remove duplicates
println!("Sorted and deduped: {:?}", uuids);
// Use in collections
let mut map = std::collections::HashMap::new();
let key = Uuid::new_v4();
map.insert(key, "value");
println!("Map value: {:?}", map.get(&key));
}use uuid::Uuid;
#[derive(Debug, Clone)]
struct Entity {
id: Uuid,
name: String,
}
impl Entity {
fn new(name: String) -> Self {
Self {
id: Uuid::new_v4(),
name,
}
}
fn with_id(id: Uuid, name: String) -> Self {
Self { id, name }
}
}
fn main() {
let entity = Entity::new("Test Entity".to_string());
println!("Entity: {:?}", entity);
// Recreate from stored UUID
let stored_id = entity.id;
let restored = Entity::with_id(stored_id, "Restored Entity".to_string());
println!("Restored: {:?}", restored);
}use uuid::uuid;
// Define UUID constants at compile time
const NAMESPACE_DNS: Uuid = uuid!("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
const MY_APP_ID: Uuid = uuid!("550e8400-e29b-41d4-a716-446655440000");
fn main() {
println!("DNS Namespace: {}", NAMESPACE_DNS);
println!("App ID: {}", MY_APP_ID);
// Use as namespace for v5
let user_uuid = Uuid::new_v5(MY_APP_ID, b"user:42");
println!("User UUID: {}", user_uuid);
}use uuid::Uuid;
fn main() {
// Generate multiple UUIDs
let uuids: Vec<Uuid> = (0..10).map(|_| Uuid::new_v4()).collect();
println!("Generated {} UUIDs:", uuids.len());
for (i, uuid) in uuids.iter().enumerate() {
println!(" {}: {}", i, uuid);
}
// Check uniqueness
let mut unique = uuids.clone();
unique.sort();
unique.dedup();
println!("\nAll unique: {}", unique.len() == uuids.len());
}use uuid::{Uuid, Builder};
fn main() {
// Build UUID from bytes
let bytes: [u8; 16] = [
0x55, 0x0e, 0x84, 0x00,
0xe2, 0x9b,
0x41, 0xd4,
0xa7, 0x16,
0x44, 0x66, 0x55, 0x44, 0x00, 0x00,
];
let uuid = Builder::from_bytes(bytes).into_uuid();
println!("Built: {}", uuid);
// Build from random bytes and set version
let mut random_bytes = [0u8; 16];
// In real code, use a proper RNG
for (i, byte) in random_bytes.iter_mut().enumerate() {
*byte = i as u8;
}
let uuid = Builder::from_random_bytes(random_bytes).into_uuid();
println!("From random bytes: {}", uuid);
}use uuid::Uuid;
fn parse_uuid(input: &str) -> Result<Uuid, String> {
Uuid::parse_str(input).map_err(|e| format!("Invalid UUID '{}': {}", input, e))
}
fn main() {
// Valid UUIDs
match parse_uuid("550e8400-e29b-41d4-a716-446655440000") {
Ok(uuid) => println!("Parsed: {}", uuid),
Err(e) => println!("Error: {}", e),
}
// Invalid UUIDs
match parse_uuid("not-a-uuid") {
Ok(uuid) => println!("Parsed: {}", uuid),
Err(e) => println!("Error: {}", e),
}
match parse_uuid("550e8400-e29b-41d4-a716-44665544000") { // Too short
Ok(uuid) => println!("Parsed: {}", uuid),
Err(e) => println!("Error: {}", e),
}
}use uuid::Uuid;
use std::collections::HashMap;
struct Session {
id: Uuid,
user_id: String,
created_at: std::time::Instant,
}
impl Session {
fn new(user_id: String) -> Self {
Self {
id: Uuid::new_v4(),
user_id,
created_at: std::time::Instant::now(),
}
}
}
struct SessionManager {
sessions: HashMap<Uuid, Session>,
}
impl SessionManager {
fn new() -> Self {
Self { sessions: HashMap::new() }
}
fn create_session(&mut self, user_id: String) -> Uuid {
let session = Session::new(user_id);
let id = session.id;
self.sessions.insert(id, session);
id
}
fn get_session(&self, id: &Uuid) -> Option<&Session> {
self.sessions.get(id)
}
fn remove_session(&mut self, id: &Uuid) -> bool {
self.sessions.remove(id).is_some()
}
}
fn main() {
let mut manager = SessionManager::new();
// Create session
let session_id = manager.create_session("user_123".to_string());
println!("Created session: {}", session_id);
// Get session
if let Some(session) = manager.get_session(&session_id) {
println!("User: {}", session.user_id);
}
// Remove session
manager.remove_session(&session_id);
println!("Session removed");
}use uuid::Uuid;
// Namespace for this application's entities
const APP_NAMESPACE: Uuid = uuid::uuid!("f47ac10b-58cc-4372-a567-0e02b2c3d479");
#[derive(Debug)]
struct Order {
id: Uuid,
customer_id: Uuid,
items: Vec<String>,
}
impl Order {
fn new(customer_id: Uuid) -> Self {
Self {
id: Uuid::new_v4(), // Random ID for the order
customer_id,
items: Vec::new(),
}
}
fn add_item(&mut self, item: String) {
self.items.push(item);
}
}
#[derive(Debug)]
struct Customer {
id: Uuid,
email: String,
name: String,
}
impl Customer {
fn new(email: String, name: String) -> Self {
// Use v5 for deterministic customer ID from email
let id = Uuid::new_v5(APP_NAMESPACE, email.as_bytes());
Self { id, email, name }
}
}
fn main() {
// Create customer (same email = same ID)
let customer = Customer::new("alice@example.com".to_string(), "Alice".to_string());
println!("Customer: {:?}", customer);
// Create order
let mut order = Order::new(customer.id);
order.add_item("Widget".to_string());
order.add_item("Gadget".to_string());
println!("Order: {:?}", order);
}Uuid::new_v4() generates random UUIDs — most common for general useUuid::now_v7() generates time-ordered UUIDs — ideal for sortable database keysUuid::new_v5(namespace, name) generates deterministic UUIDs from a nameUuid::parse_str() or .parse()as_bytes(), as_u128(), or as_u64_pair()uuid!() macro for compile-time UUID constants#[serde(with = "uuid::serde::simple")] for custom formatsNAMESPACE_DNS, NAMESPACE_URL, NAMESPACE_OID, NAMESPACE_X500v4, v5, v7, serde as needed