Como Gerar UUID em Rust

Aprenda a gerar UUID em Rust com a crate uuid: v4 aleatório, v7 ordenável, from_str, Display e uso como identificador único. Guia completo com exemplos.

UUIDs (Universally Unique Identifiers) são identificadores de 128 bits usados para identificar recursos de forma única sem coordenação central. São essenciais em sistemas distribuídos, bancos de dados, APIs e mensageria. A crate uuid do Rust suporta todas as versões do padrão, incluindo o moderno UUIDv7 ordenável por tempo.

Dependências

[package]
name = "receita-uuid"
version = "0.1.0"
edition = "2021"

[dependencies]
uuid = { version = "1", features = ["v4", "v7"] }

Código Completo

use uuid::Uuid;

fn main() {
    // =============================================
    // 1. Gerar UUID v4 (aleatório)
    // =============================================
    println!("=== UUID v4 (aleatório) ===");
    let id = Uuid::new_v4();
    println!("UUID v4: {}", id);
    println!("Bytes:   {:?}", id.as_bytes());
    println!("Versão:  {}", id.get_version_num());

    // Gerar vários UUIDs
    println!("\nVários UUIDs v4:");
    for i in 1..=5 {
        println!("  {}: {}", i, Uuid::new_v4());
    }

    // =============================================
    // 2. Gerar UUID v7 (ordenável por tempo)
    // =============================================
    println!("\n=== UUID v7 (ordenável por tempo) ===");
    let id1 = Uuid::now_v7();
    let id2 = Uuid::now_v7();
    let id3 = Uuid::now_v7();

    println!("UUID v7 #1: {}", id1);
    println!("UUID v7 #2: {}", id2);
    println!("UUID v7 #3: {}", id3);
    println!("Ordenados? {} < {} < {}", id1 < id2, id2 < id3, id1 < id3);
    println!("(UUIDs v7 são ordenáveis por tempo de criação)");

    // =============================================
    // 3. Parse de string para UUID
    // =============================================
    println!("\n=== Parse de String ===");

    // Formato padrão com hifens
    let id = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
    println!("Parsed: {}", id);

    // Formato sem hifens
    let id = Uuid::parse_str("550e8400e29b41d4a716446655440000").unwrap();
    println!("Sem hifens: {}", id);

    // Formato com chaves (URN)
    let id = Uuid::parse_str("{550e8400-e29b-41d4-a716-446655440000}").unwrap();
    println!("Com chaves: {}", id);

    // Tratando erro de parse
    match Uuid::parse_str("não-é-uuid") {
        Ok(id) => println!("Parsed: {}", id),
        Err(e) => println!("Erro de parse: {}", e),
    }

    // =============================================
    // 4. Formatos de exibição
    // =============================================
    println!("\n=== Formatos de Exibição ===");
    let id = Uuid::new_v4();

    println!("Display (padrão):  {}", id);
    println!("Hyphenated:        {}", id.hyphenated());
    println!("Simple (sem -):    {}", id.simple());
    println!("URN:               {}", id.urn());
    println!("Braced:            {}", id.braced());

    // =============================================
    // 5. UUID nil e max
    // =============================================
    println!("\n=== Valores Especiais ===");
    let nil = Uuid::nil();
    let max = Uuid::max();

    println!("Nil UUID: {}", nil);
    println!("Max UUID: {}", max);
    println!("Nil é nil? {}", nil.is_nil());
    println!("Max é max? {}", max.is_max());

    // =============================================
    // 6. Comparação e ordenação
    // =============================================
    println!("\n=== Comparação e Ordenação ===");
    let mut ids: Vec<Uuid> = (0..5).map(|_| Uuid::new_v4()).collect();
    println!("Desordenados:");
    for id in &ids {
        println!("  {}", id);
    }

    ids.sort();
    println!("Ordenados:");
    for id in &ids {
        println!("  {}", id);
    }

    // Comparação
    let a = Uuid::new_v4();
    let b = Uuid::new_v4();
    println!("\na == b? {}", a == b);
    println!("a != b? {}", a != b);

    // =============================================
    // 7. UUID como chave de HashMap
    // =============================================
    println!("\n=== UUID como Chave de HashMap ===");
    use std::collections::HashMap;

    #[derive(Debug)]
    struct Usuario {
        id: Uuid,
        nome: String,
    }

    let mut usuarios: HashMap<Uuid, Usuario> = HashMap::new();

    let id1 = Uuid::new_v4();
    let id2 = Uuid::new_v4();

    usuarios.insert(id1, Usuario { id: id1, nome: "Ana".into() });
    usuarios.insert(id2, Usuario { id: id2, nome: "Bia".into() });

    // Buscar por UUID
    if let Some(u) = usuarios.get(&id1) {
        println!("Encontrado: {} ({})", u.nome, u.id);
    }

    println!("Total de usuários: {}", usuarios.len());

    // =============================================
    // 8. Exemplo prático: gerador de IDs
    // =============================================
    println!("\n=== Gerador de IDs ===");

    struct IdGenerator {
        prefixo: String,
    }

    impl IdGenerator {
        fn new(prefixo: &str) -> Self {
            IdGenerator { prefixo: prefixo.to_string() }
        }

        fn proximo(&self) -> String {
            format!("{}_{}", self.prefixo, Uuid::new_v4().simple())
        }

        fn proximo_curto(&self) -> String {
            let uuid = Uuid::new_v4();
            let curto = &uuid.simple().to_string()[..8];
            format!("{}_{}", self.prefixo, curto)
        }
    }

    let gen_pedido = IdGenerator::new("PED");
    let gen_nota = IdGenerator::new("NF");

    println!("Pedido: {}", gen_pedido.proximo());
    println!("Pedido: {}", gen_pedido.proximo());
    println!("Nota:   {}", gen_nota.proximo());
    println!("Curto:  {}", gen_pedido.proximo_curto());
    println!("Curto:  {}", gen_pedido.proximo_curto());
}

Saída do Programa

=== UUID v4 (aleatório) ===
UUID v4: 3f7e9a12-4b5c-4d6e-8f1a-2b3c4d5e6f7a
Bytes:   [63, 126, 154, 18, 75, 92, 77, 110, 143, 26, 43, 60, 77, 94, 111, 122]
Versão:  4

Vários UUIDs v4:
  1: a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5
  2: 11223344-5566-4778-899a-bbccddeeff00
  ...

=== UUID v7 (ordenável por tempo) ===
UUID v7 #1: 01953e8a-1234-7abc-8def-0123456789ab
UUID v7 #2: 01953e8a-1235-7bcd-8ef0-123456789abc
UUID v7 #3: 01953e8a-1236-7cde-8f01-23456789abcd
Ordenados? true < true < true
(UUIDs v7 são ordenáveis por tempo de criação)

=== Parse de String ===
Parsed: 550e8400-e29b-41d4-a716-446655440000
Sem hifens: 550e8400-e29b-41d4-a716-446655440000
Com chaves: 550e8400-e29b-41d4-a716-446655440000
Erro de parse: invalid character: expected an optional prefix ...

=== Formatos de Exibição ===
Display (padrão):  3f7e9a12-4b5c-4d6e-8f1a-2b3c4d5e6f7a
Hyphenated:        3f7e9a12-4b5c-4d6e-8f1a-2b3c4d5e6f7a
Simple (sem -):    3f7e9a124b5c4d6e8f1a2b3c4d5e6f7a
URN:               urn:uuid:3f7e9a12-4b5c-4d6e-8f1a-2b3c4d5e6f7a
Braced:            {3f7e9a12-4b5c-4d6e-8f1a-2b3c4d5e6f7a}

=== Valores Especiais ===
Nil UUID: 00000000-0000-0000-0000-000000000000
Max UUID: ffffffff-ffff-ffff-ffff-ffffffffffff
Nil é nil? true
Max é max? true

=== Gerador de IDs ===
Pedido: PED_3f7e9a124b5c4d6e8f1a2b3c4d5e6f7a
Pedido: PED_a1b2c3d4e5f64a7b8c9de0f1a2b3c4d5
Nota:   NF_11223344556647788899bbccddeeff00
Curto:  PED_3f7e9a12
Curto:  PED_a1b2c3d4

UUID v4 vs v7

VersãoBaseado emOrdenávelUso ideal
v4AleatórioNaoIDs genéricos, tokens
v7Timestamp + aleatórioSimChaves primárias de banco, logs

UUIDv7 e recomendado para chaves primárias de banco de dados porque a ordenação por tempo melhora a performance de insercao em indices B-tree. Se nao precisa de ordenacao temporal, use UUIDv4.

Veja Também