Crate tnid

Crate tnid 

Source
Expand description

§TNID

Type-checked, Named IDs that are fully compatible with UUIDs.

TNID (“Typed Named ID”, pronounced “tee-nid”) embeds a human-readable name directly into a UUID-compatible 128-bit identifier. Each TNID carries a 1-4 character type name (like “user” or “post”) that’s validated at compile time, preventing you from accidentally mixing up IDs for different entity types.

§Quick Start

use tnid::{Tnid, TnidName, NameStr};

// Define a name type for your entity
struct User;
impl TnidName for User {
    const ID_NAME: NameStr<'static> = NameStr::new_const("user");
}

// Generate IDs
let id = Tnid::<User>::new_v0();  // Time-ordered (like UUIDv7)

// Display as a TNID string
println!("{}", id);  // e.g., "user.Br2flcNDfF6LYICnT"

// Or as a standard UUID for database storage
let uuid_str = id.to_uuid_string_cased(false);
// e.g., "cab1952a-f09d-86d9-928e-96ea03dc6af3"

§Why TNIDs?

TNIDs solve several common problems with plain UUIDs:

  • Type Safety: Tnid<User> and Tnid<Post> are different types. You can’t accidentally pass a post ID where a user ID is expected.
  • Human Readable: The TNID string format (user.Br2flcNDfF6LYICnT) tells you at a glance what kind of entity the ID refers to.
  • UUID Compatible: Every TNID is a valid UUIDv8, so it works with existing UUID columns in databases and UUID-based APIs.

§TNID Variants

Like UUID versions, TNIDs come in different variants:

  • V0 (Tnid::new_v0) - Time-ordered with millisecond precision (like UUIDv7). Use when you want IDs to sort chronologically.
  • V1 (Tnid::new_v1) - High-entropy random (like UUIDv4). Use when you want maximum randomness without time information.

See TnidVariant for details.

§String Representations

TNIDs support two string formats:

  • TNID format (user.Br2flcNDfF6LYICnT): Human-readable, sortable, unambiguous
  • UUID format (cab1952a-f09d-86d9-928e-96ea03dc6af3): Standard UUID hex for compatibility
let id = Tnid::<User>::new_v1();

// TNID string (for APIs, logs, user-facing contexts)
let tnid_str = id.as_tnid_string();

// UUID string (for databases, UUID-based systems)
let uuid_str = id.to_uuid_string_cased(false);

// Parse back
let from_tnid = Tnid::<User>::parse_tnid_string(&tnid_str);
let from_uuid = Tnid::<User>::parse_uuid_string(&uuid_str);

§Feature Flags

FeatureDefaultDescription
timeEnables Tnid::new_v0 with automatic timestamps
randEnables Tnid::new_v0 and Tnid::new_v1 with automatic randomness
encryptionEnables Tnid::encrypt_v0_to_v1 and Tnid::decrypt_v1_to_v0 for hiding timestamps
uuidIntegration with the uuid crate

Without the default features, you can still create TNIDs using explicit components:

§Reliability

This crate is designed to never panic in normal use. All functions that could potentially panic are fuzz tested with randomized inputs to verify they don’t. Extensive unit tests verify correctness of encoding, sorting, and round-trip conversions.

Modules§

encryptionencryption
TNID encryption utilities.

Structs§

NameStr
A validated TNID name string.
Tnid
A type-safe TNID parameterized by name.
UUIDLike
A wrapper for 128-bit values that may or may not be valid TNIDs.

Enums§

TnidVariant
The 4 possible TNID variants.

Traits§

TnidName
Intended to be used on empty structs to create type checked TNID names.