TNID
UUID-compatible IDs with names and compile-time type safety.
TNIDs are UUIDv8-compatible identifiers that include a human-readable name and can be strictly typed at compile time.
use ;
;
// Create a time-ordered ID (like UUIDv7)
let user_id = TNID::new_time_ordered;
println!; // user.Br2flcNDfF6LYICnT
// Or a high-entropy ID (like UUIDv4)
let session_id = TNID::new_high_entropy;
Why TNIDs?
- Type-safe:
TNID<User>andTNID<Post>are different types. Accidentally passing a post ID to a user function? Compile error! - Named: IDs include a human-readable name prefix. See
user.Br2flcNDfF6LYICnTin your logs and instantly know what it is. - UUID-compatible: TNIDs are valid UUIDv8s that work directly with Postgres UUID columns and UUID-expecting APIs.
- Compile-time validated: Try to create a TNID with name "INVALID"? Your code won't even compile.
- Sortable strings: Unlike UUID hex (case-insensitive mess), TNID strings sort correctly and have exactly one representation.
Status
⚠️ Beta: The TNID spec is still being finalized and shouldn't be relied on for production use yet. This implementation tracks the evolving spec.
A full specification site will be available at tnid.info.
Installation
Examples
Creating TNIDs
use ;
;
// Time-ordered (v0) - sorts by creation time
let id = TNID::new_v0;
// High-entropy (v1) - maximum randomness
let id = TNID::new_v1;
String Representations
// TNID string format - human-readable, sortable, unambiguous
let tnid_str = id.as_tnid_string;
// "post.Br2flcNDfF6LYICnT" - you can SEE it's a post ID!
// UUID hex format - for databases and APIs that expect UUIDs
let uuid_str = id.to_uuid_string_cased;
// "cab1952a-f09d-86d9-928e-96ea03dc6af3" - works in Postgres, MySQL, etc.
// Time-ordered IDs sort correctly in BOTH representations!
let id1 = TNID::new_v0;
sleep;
let id2 = TNID::new_v0;
assert!; // Sorts correctly!
assert!; // In all representations!
Parsing
// Parse from TNID string
let id = TNID::parse_tnid_string.unwrap;
// Parse from UUID string
let id = TNID::parse_uuid_string.unwrap;
// From raw u128
let id = TNID::from_u128.unwrap;
Type Safety in Action
;
;
let user_id = TNID::new_v0;
let post_id = TNID::new_v0;
delete_user; // Works!
delete_post; // Works!
// delete_user(post_id); // Compile error! Can't pass a Post ID to a User function
// delete_post(user_id); // Compile error! Type mismatch caught at compile time
Features
| Feature | Default | Description |
|---|---|---|
time |
✓ | Time-based v0 TNID generation (like UUIDv7) |
rand |
✓ | Random v1 TNID generation (like UUIDv4) |
encryption |
Encrypt v0 to v1 to hide timestamps from clients, decrypt on the backend | |
uuid |
Convert to/from the uuid crate's Uuid type |
Documentation
See the API documentation for complete details.
License
MIT