LOG 010: 2026/08/07
★ Typed Identifiers
Continued experimenting with the typed identifiers API.
Refactored and deduped the various part types (
Fragment,Word,Segment).Created a
Casetrait to dedupe how we reformat character profiles.Finished adding functionality to convert between different identifiers via the
ConvertCasetrait.Started adding comprehensive integration tests to validate the functionality.
I thought this would be an easy and quick crate, and I’ve grossly underestimated how complicated generalized typed identifiers are.
I’m still not done with this, and it’s still not ready to share. But I can show you what it looks like currently (note: crate is the stand-in for the final crate name, which is currently undecided):
use crate::{casing, delimiter, profile, Ident};
// A lower_snake_case identifier using the Unicode XID profile.
type LowerSnakeIdent = Ident<
casing::Lower,
delimiter::LowLine,
profile::Unicode,
>;
// Only allows lower_snake identifiers.
let ident = LowerSnakeIdent::new("example_snake")?;
assert!(LowerSnakeIdent::new("example-kebab").is_err());
assert!(LowerSnakeIdent::new("exampleCamel").is_err());
// You can easily extract segments of the identifier.
// Prints:
// * Word(Word("example"))
// * Delimiter(LowLine)
// * Word(Word("snake"))
println!("{ident} segments:");
for segment in ident.segments() {
println!("* {segment:?}");
}
// You can also easily convert to other identifiers.
//
// The type here is `IdentBuf<UpperCamel, LowLine, Unicode>`,
// but you can test against strings (`PartialEq` works against `&str`).
assert_eq!(ident.to_upper_camel()?, "ExampleSnake");

