entid
A Rust library for generating and validating type-safe, prefixed entity identifiers based on UUIDs and ULIDs.
Features
- Type-safe entity IDs: Create distinct ID types for different entities
- Multiple identifier formats: Support for both UUID and ULID
- Prefix support: Automatically add entity-specific prefixes to IDs
- Performance optimized: Thread-safe caching of string representations
- Serde compatible: Seamless serialization and deserialization
- Comprehensive error handling: Clear error types for all operations
- Zero-cost abstractions: Minimal runtime overhead
- Derive macro for implementing the
Prefixtrait: Optional
Installation
Add this to your Cargo.toml:
[]
= "0.4.1"
To use the derive macro for implementing the Prefix trait, enable the derive feature:
[]
= { = "0.4.1", = ["derive"] }
API Overview
The EntityId type provides several methods for working with entity IDs:
// Create a new EntityId
let user_id = generate;
// Get the full ID string with prefix (e.g., "user_123e4567-e89b-12d3-a456-426614174000")
let full_id = user_id.as_str;
// Get just the identifier part without the prefix (e.g., "123e4567-e89b-12d3-a456-426614174000")
let raw_id = user_id.id_str;
// Get a reference to the underlying identifier object
let identifier = user_id.identifier;
// Get the identifier string directly from the identifier
let id_str = user_id.identifier.as_str;
// Get the prefix for this entity type
let prefix = prefix; // "user"
// Get the delimiter for this entity type
let delimiter = delimiter; // "_"
// For ULID-based IDs, get the timestamp
if let Some = ulid_id.timestamp_ms
Flexible Creation Methods
The library provides multiple ways to create entity IDs:
use ;
// Using the generate method
let user_id1 = generate;
// Using the new method with flexible string types
let id_str = "user_123e4567-e89b-12d3-a456-426614174000";
let user_id2 = new.unwrap;
let user_id3 = new.unwrap;
// Using TryFrom trait
let user_id4 = try_from.unwrap;
let user_id5 = try_from.unwrap;
// Using FromStr trait
let user_id6 = id_str..unwrap;
// Using convenience methods
let uuid = new_v4;
let user_id7 = with_uuid;
let user_id8 = new_v4;
let user_id9 = new_v5;
// Using the builder pattern
let user_id10 = builder.build;
let user_id11 = builder.with_uuid.build;
let user_id12 = builder.with_uuid_v4.build;
let user_id13 = builder.with_uuid_v5.build;
// For ULID-based IDs
let ulid = new;
let post_id1 = with_ulid;
let post_id2 = with_timestamp; // July 1, 2021
let post_id3 = monotonic_from;
// Using the builder pattern for ULID
let post_id4 = builder.with_ulid.build;
let post_id5 = builder.with_timestamp.build;
let post_id6 = builder.with_monotonic_from.build;
Using EntityId in Collections
The EntityId type implements Borrow<str> and AsRef<str>, making it easy to use in collections:
use ;
// Use EntityId as a key in a HashMap
let mut user_map = new;
user_map.insert;
// Look up by string
let user = user_map.get;
// Use EntityId in a HashSet
let mut user_set = new;
user_set.insert;
// Check if a string is in the set
let contains = user_set.contains;
Usage
Basic Example with UUID
use ;
// Define your entity types with custom prefixes
;
;
Using the Derive Macro
With the derive feature enabled, you can use the derive macro to implement the Prefix trait:
use ;
;
;
// The delimiter is optional and defaults to "_"
;
Using ULID Instead of UUID
use ;
;
Using Deterministic UUIDs (v5)
use ;
;
Error Handling
use ;
;
// Parse a raw identifier string
Using with Serde
use ;
use ;
;
Using with Databases
use ;
;
// Example with a hypothetical database library
Advanced Usage
Creating Monotonic ULIDs
use ;
;
Custom Validation
use ;
;
// Extend EntityId with custom validation logic
Choosing Between UUID and ULID
UUID Advantages
- Industry standard with wide adoption
- Multiple versions for different use cases (v1, v3, v4, v5)
- Well-supported in databases and other systems
ULID Advantages
- Lexicographically sortable (sorts by creation time)
- URL-safe (no special characters)
- Shorter string representation (26 characters vs 36 for UUID)
- Built-in timestamp component
Performance Considerations
- String representations are cached using
OnceLockfor thread-safe lazy initialization - The
EntityIdtype implementsHash,PartialEq, andEqfor efficient use in collections - Memory usage is optimized by using
PhantomDatafor type parameters
License
This project is licensed under the MIT License - see the LICENSE file for details.