Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

discriminated_str

API reference on docs.rs: discriminated_str.

Assigns every enum variant one unique string literal. The generated method maps values to strings; a same-name macro maps literals and payloads back to variant constructors.

You write Roughly expands to
#[discriminated_str(name)]
enum Token {
    Ident(String) = "ident",
    End = "end",
}

fn main() {
    let token = Token!("ident", String::from("value"));
    assert_eq!(token.name(), "ident");
    assert!(matches!(Token!("end"), Token::End));
}
enum Token {
    Ident(String),
    End,
}

impl Token {
    const fn name(&self) -> &'static str {
        match self {
            Self::Ident(..) => "ident",
            Self::End => "end",
        }
    }
}

// Generated in the macro namespace:
macro_rules! Token {
    ("ident", $value:expr) => { Token::Ident($value) };
    ("end") => { Token::End };
}

The constructor macro follows the original variant shape:

You write Roughly expands to
#[discriminated_str(code)]
enum Error {
    Io(std::io::Error) = "io",
    Parse { offset: usize } = "parse",
    Unknown = "unknown",
}

fn main() {
    let error = Error!("parse", offset: 17);
    assert_eq!(error.code(), "parse");
}
Error!("io", source)
// Error::Io(source)

Error!("parse", offset: 17)
// Error::Parse { offset: 17 }

Error!("unknown")
// Error::Unknown

Every variant must have a string literal, and literals must be unique. The constructor direction deliberately accepts literals rather than runtime &str values: it selects a constructor during macro expansion and delegates the remaining expressions directly to it. No generated runtime tag type leaks into the user’s namespace.

Generics, lifetimes, visibility, and where clauses remain on the original enum. cfg and cfg_attr are retained on the generated forward match arms.