How does uuid::Uuid::parse_str handle hyphenated vs non-hyphenated UUID formats?
Uuid::parse_str accepts both hyphenated (standard) and non-hyphenated (simple) UUID string formats, normalizing either into the same binary UUID representation. It handles format variations transparently while rejecting invalid characters or malformed inputs.
UUID String Formats
use uuid::Uuid;
fn formats() {
// Standard hyphenated format (36 characters with hyphens)
let hyphenated = "550e8400-e29b-41d4-a716-446655440000";
// Simple format (32 characters, no hyphens)
let simple = "550e8400e29b41d4a716446655440000";
// Both parse to the same UUID
let uuid1 = Uuid::parse_str(hyphenated).unwrap();
let uuid2 = Uuid::parse_str(simple).unwrap();
assert_eq!(uuid1, uuid2);
// parse_str handles both formats transparently
}parse_str accepts both hyphenated and simple formats without requiring separate methods.
The parse_str Method
use uuid::Uuid;
fn parse_str_signature() {
// Signature:
// pub fn parse_str(input: &str) -> Result<Uuid, Error>
// Accepts:
// - Hyphenated: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
// - Simple: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
// - URN format: "urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
// - Braced: "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
let uuid1 = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
let uuid2 = Uuid::parse_str("550e8400e29b41d4a716446655440000").unwrap();
let uuid3 = Uuid::parse_str("urn:uuid:550e8400-e29b-41d4-a716-446655440000").unwrap();
// All produce the same UUID
assert_eq!(uuid1, uuid2);
assert_eq!(uuid2, uuid3);
}parse_str handles multiple common UUID string representations.
Hyphenated Format Details
use uuid::Uuid;
fn hyphenated_format() {
// Hyphenated format: 8-4-4-4-12 characters
// Total: 36 characters (32 hex + 4 hyphens)
let uuid = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
// Format breakdown:
// 550e8400 - time_low (8 hex chars)
// e29b - time_mid (4 hex chars)
// 41d4 - time_hi_and_version (4 hex chars)
// a716 - clock_seq_hi_and_res + clock_seq_low (4 hex chars)
// 446655440000 - node ID (12 hex chars)
// Hyphens must be in positions 8, 13, 18, 23
// Invalid hyphen positions will cause an error
let result = Uuid::parse_str("550e-8400-e29b-41d4-a716-446655440000");
assert!(result.is_err()); // Hyphens in wrong positions
}The hyphenated format follows RFC 4122 with hyphens at specific positions.
Simple Format Details
use uuid::Uuid;
fn simple_format() {
// Simple format: 32 hexadecimal characters, no hyphens
// All 32 hex digits concatenated directly
let uuid = Uuid::parse_str("550e8400e29b41d4a716446655440000").unwrap();
// Equivalent to hyphenated:
let uuid_hyphen = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
assert_eq!(uuid, uuid_hyphen);
// Case-insensitive
let uuid_upper = Uuid::parse_str("550E8400E29B41D4A716446655440000").unwrap();
let uuid_lower = Uuid::parse_str("550e8400e29b41d4a716446655440000").unwrap();
assert_eq!(uuid_upper, uuid_lower);
}The simple format omits hyphens but represents the same binary data.
Error Handling
use uuid::Uuid;
fn error_handling() {
// Invalid characters
let result = Uuid::parse_str("550e8400e29b41d4a71644665544000g");
assert!(result.is_err()); // 'g' is not valid hex
// Wrong length (hyphenated)
let result = Uuid::parse_str("550e8400-e29b-41d4-a716-44665544000");
assert!(result.is_err()); // Too short
// Wrong length (simple)
let result = Uuid::parse_str("550e8400e29b41d4a71644665544000");
assert!(result.is_err()); // Too short
// Hyphens in wrong positions
let result = Uuid::parse_str("550e84-00e29b-41d4a716446655440000");
assert!(result.is_err()); // Hyphens at wrong positions
// Empty string
let result = Uuid::parse_str("");
assert!(result.is_err());
// Nil UUID is valid
let uuid = Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap();
assert!(uuid.is_nil());
}parse_str validates format and content, returning errors for invalid inputs.
Valid Format Variations
use uuid::Uuid;
fn format_variations() {
// All these formats are valid:
// 1. Standard hyphenated (lowercase)
let uuid1 = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
// 2. Standard hyphenated (uppercase)
let uuid2 = Uuid::parse_str("550E8400-E29B-41D4-A716-446655440000").unwrap();
// 3. Mixed case
let uuid3 = Uuid::parse_str("550e8400-E29B-41d4-A716-446655440000").unwrap();
// 4. Simple format (lowercase)
let uuid4 = Uuid::parse_str("550e8400e29b41d4a716446655440000").unwrap();
// 5. Simple format (uppercase)
let uuid5 = Uuid::parse_str("550E8400E29B41D4A716446655440000").unwrap();
// 6. URN format
let uuid6 = Uuid::parse_str("urn:uuid:550e8400-e29b-41d4-a716-446655440000").unwrap();
// 7. Braced format
let uuid7 = Uuid::parse_str("{550e8400-e29b-41d4-a716-446655440000}").unwrap();
// All produce the same UUID
assert_eq!(uuid1, uuid2);
assert_eq!(uuid2, uuid3);
assert_eq!(uuid3, uuid4);
assert_eq!(uuid4, uuid5);
assert_eq!(uuid5, uuid6);
assert_eq!(uuid6, uuid7);
}parse_str handles case and format variations transparently.
Output Formats
use uuid::Uuid;
fn output_formats() {
let uuid = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
// Hyphenated (Display trait)
let hyphenated = uuid.to_string(); // "550e8400-e29b-41d4-a716-446655440000"
// Simple (no hyphens)
let simple = uuid.simple().to_string(); // "550e8400e29b41d4a716446655440000"
// URN format
let urn = uuid.urn().to_string(); // "urn:uuid:550e8400-e29b-41d4-a716-446655440000"
// Braced
let braced = uuid.braced().to_string(); // "{550e8400-e29b-41d4-a716-446655440000}"
// Note: parse_str accepts all these formats, but to_string produces hyphenated
}The Uuid type provides methods to output in different formats.
Comparison Table
use uuid::Uuid;
fn comparison() {
// ┌─────────────────────────────────────────────────────────────────────────┐
// │ Format │ Input Length │ Example │
// ├─────────────────────────────────────────────────────────────────────────┤
// │ Hyphenated │ 36 chars │ "550e8400-e29b-41d4-a716-446655440000" │
// │ Simple │ 32 chars │ "550e8400e29b41d4a716446655440000" │
// │ URN │ 45 chars │ "urn:uuid:550e8400-..." │
// │ Braced │ 38 chars │ "{550e8400-e29b-41d4-a716-446655440000}" │
// └─────────────────────────────────────────────────────────────────────────┘
// parse_str accepts all formats and normalizes to the same binary UUID
}All accepted formats normalize to the same internal representation.
Parsing vs Creating
use uuid::Uuid;
fn parsing_vs_creating() {
// Parsing from string
let parsed = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
// Creating from bytes (no parsing)
let bytes: [u8; 16] = [
0x55, 0x0e, 0x84, 0x00,
0xe2, 0x9b,
0x41, 0xd4,
0xa7, 0x16,
0x44, 0x66, 0x55, 0x44, 0x00, 0x00,
];
let from_bytes = Uuid::from_bytes(bytes);
// Creating from fields (hyphenated parts)
let from_fields = Uuid::from_fields(
0x550e8400, // time_low
0xe29b, // time_mid
0x41d4, // time_hi_and_version
&[0xa7, 0x16], // clock_seq
&[0x44, 0x66, 0x55, 0x44, 0x00, 0x00], // node
);
assert_eq!(parsed, from_bytes);
assert_eq!(from_bytes, from_fields);
}parse_str is the string parsing method; other constructors create UUIDs directly.
Use Cases
use uuid::Uuid;
fn use_cases() {
// Hyphenated format is common in:
// - JSON APIs
// - Database string representations
// - Configuration files
// - Human-readable output
let from_api = r#""550e8400-e29b-41d4-a716-446655440000""#;
let uuid = Uuid::parse_str(&from_api[1..37]).unwrap();
// Simple format is common in:
// - URL-safe representations
// - Compact storage
// - Systems that strip formatting
let from_url = "550e8400e29b41d4a716446655440000";
let uuid = Uuid::parse_str(from_url).unwrap();
// Both formats parse correctly regardless of source
}Both formats appear in different contexts; parse_str handles them uniformly.
Performance Considerations
use uuid::Uuid;
fn performance() {
// Hyphenated format requires parsing and validating hyphen positions
// Simple format is slightly faster to parse (fewer characters)
// However, the difference is minimal for most use cases
let hyphenated = "550e8400-e29b-41d4-a716-446655440000";
let simple = "550e8400e29b41d4a716446655440000";
// Both parse in ~microseconds
let uuid1 = Uuid::parse_str(hyphenated).unwrap();
let uuid2 = Uuid::parse_str(simple).unwrap();
// For maximum performance, use from_bytes with pre-parsed bytes
let bytes: [u8; 16] = [/* ... */];
let uuid = Uuid::from_bytes(bytes); // No parsing overhead
}Both formats parse efficiently; use from_bytes for maximum performance.
Validation Behavior
use uuid::Uuid;
fn validation() {
// Valid inputs
let valid = [
"550e8400-e29b-41d4-a716-446655440000", // Standard
"550E8400-E29B-41D4-A716-446655440000", // Uppercase
"550e8400e29b41d4a716446655440000", // Simple
"URN:UUID:550e8400-e29b-41d4-a716-446655440000", // URN
"{550e8400-e29b-41d4-a716-446655440000}", // Braced
];
for input in valid {
assert!(Uuid::parse_str(input).is_ok());
}
// Invalid inputs
let invalid = [
"550e8400e29b41d4a71644665544000", // Too short (31 chars)
"550e8400e29b41d4a7164466554400000", // Too long (33 chars)
"550e8400e29b41d4a71644665544000g", // Invalid hex char 'g'
"550e8400-e29b-41d4-a716446655440000", // Missing hyphen
"550e84-00e29b-41d4-a716-446655440000", // Hyphens wrong position
];
for input in invalid {
assert!(Uuid::parse_str(input).is_err());
}
}parse_str validates length, characters, and format structure.
Complete Example
use uuid::Uuid;
fn main() {
// Parsing hyphenated format
let hyphenated = "550e8400-e29b-41d4-a716-446655440000";
let uuid1 = Uuid::parse_str(hyphenated).unwrap();
println!("Hyphenated: {}", uuid1);
// Parsing simple format
let simple = "550e8400e29b41d4a716446655440000";
let uuid2 = Uuid::parse_str(simple).unwrap();
println!("Simple: {}", uuid2);
// Both parse to the same UUID
assert_eq!(uuid1, uuid2);
// Parsing URN format
let urn = "urn:uuid:550e8400-e29b-41d4-a716-446655440000";
let uuid3 = Uuid::parse_str(urn).unwrap();
assert_eq!(uuid1, uuid3);
// Output in different formats
println!("Default (hyphenated): {}", uuid1);
println!("Simple: {}", uuid1.simple());
println!("URN: {}", uuid1.urn());
println!("Braced: {}", uuid1.braced());
// Error handling
match Uuid::parse_str("invalid-uuid") {
Ok(uuid) => println!("Valid: {}", uuid),
Err(e) => println!("Error: {}", e),
}
// Case insensitivity
let lower = Uuid::parse_str("550e8400e29b41d4a716446655440000").unwrap();
let upper = Uuid::parse_str("550E8400E29B41D4A716446655440000").unwrap();
assert_eq!(lower, upper);
println!("Case insensitive: {} == {}", lower, upper);
}Summary
use uuid::Uuid;
fn summary() {
// ┌─────────────────────────────────────────────────────────────────────────┐
// │ Aspect │ Hyphenated │ Simple │
// ├─────────────────────────────────────────────────────────────────────────┤
// │ Length │ 36 chars │ 32 chars │
// │ Format │ 8-4-4-4-12 with hyphens │ 32 hex digits │
// │ Readability │ Human-friendly │ Compact │
// │ Example │ "550e8400-e29b-..." │ "550e8400e29b..." │
// │ parse_str │ Accepted │ Accepted │
// │ to_string │ Produces this │ Use .simple().to_string()│
// └─────────────────────────────────────────────────────────────────────────┘
// Key points:
// 1. parse_str accepts both hyphenated and simple formats
// 2. Case-insensitive parsing
// 3. Also accepts URN and braced formats
// 4. Validates hyphen positions for hyphenated format
// 5. All formats produce the same binary UUID
// 6. Default Display output is hyphenated format
}Key insight: Uuid::parse_str is format-agnostic, accepting hyphenated, simple, URN, and braced UUID string representations without requiring format specification. This flexibility simplifies code that handles UUIDs from various sources (databases, APIs, config files), while the consistent output methods (to_string, simple(), urn(), braced()) allow converting to the desired format for display or serialization.
