Loading page…
Rust walkthroughs
Loading page…
strum::IntoStaticStr and Into<&'static str> for compile-time string conversion?strum::IntoStaticStr is a derive macro trait that converts enum variants to their associated static string representations at compile time through associated constants, while Into<&'static str> is a generic standard library trait for any type that can be converted into a static string reference. IntoStaticStr works specifically with enums and generates &'static str values based on derive attributes like strum(to_str = "..."), making it explicit what string each variant maps to. Into<&'static str> requires implementing the trait manually for your type and is not derive-driven. The key distinction: IntoStaticStr provides compile-time guarantees for enum-to-string conversion through a macro, while Into<&'static str> is a general-purpose conversion trait that could produce the string at runtime.
use strum::IntoStaticStr;
#[derive(IntoStaticStr)]
enum Status {
Active,
Inactive,
Pending,
}
fn basic_usage() {
// IntoStaticStr provides into_static_str method
let status: Status = Status::Active;
// Convert to static str
let static_str: &'static str = status.into_static_str();
println!("Status: {}", static_str);
// Output: Status: Active
// The returned string is &'static str - valid for 'static lifetime
let inactive: &'static str = Status::Inactive.into_static_str();
println!("Inactive: {}", inactive);
// Output: Inactive: Inactive
}IntoStaticStr provides into_static_str() method that returns a static string for each variant.
use strum::IntoStaticStr;
#[derive(IntoStaticStr)]
enum HttpStatus {
#[strum(to_str = "200 OK")]
Ok,
#[strum(to_str = "201 Created")]
Created,
#[strum(to_str = "404 Not Found")]
NotFound,
#[strum(to_str = "500 Internal Server Error")]
InternalServerError,
}
fn custom_strings() {
let status: &'static str = HttpStatus::Ok.into_static_str();
println!("HTTP: {}", status);
// Output: HTTP: 200 OK
let error: &'static str = HttpStatus::NotFound.into_static_str();
println!("Error: {}", error);
// Output: Error: 404 Not Found
}strum(to_str = "...") customizes the output string for each variant.
// Into<&'static str> is a standard library trait
// You implement it manually for your types
enum HttpStatus {
Ok,
Created,
NotFound,
InternalServerError,
}
impl Into<&'static str> for HttpStatus {
fn into(self) -> &'static str {
match self {
HttpStatus::Ok => "200 OK",
HttpStatus::Created => "201 Created",
HttpStatus::NotFound => "404 Not Found",
HttpStatus::InternalServerError => "500 Internal Server Error",
}
}
}
fn into_trait_usage() {
let status: HttpStatus = HttpStatus::Ok;
let static_str: &'static str = status.into();
println!("HTTP: {}", static_str);
// Output: HTTP: 200 OK
// Works the same way, but implemented manually
}Into<&'static str> requires manual implementation; IntoStaticStr generates it via derive.
use strum::IntoStaticStr;
// IntoStaticStr: Derive macro generates implementation
#[derive(IntoStaticStr)]
enum Status1 {
Active, // Automatically maps to "Active"
Inactive, // Automatically maps to "Inactive"
}
// Into<&'static str>: Manual implementation required
enum Status2 {
Active,
Inactive,
}
impl Into<&'static str> for Status2 {
fn into(self) -> &'static str {
match self {
Status2::Active => "Active",
Status2::Inactive => "Inactive",
}
}
}
fn compare_approaches() {
// IntoStaticStr - derive-generated method
let s1: &'static str = Status1::Active.into_static_str();
// Into<&'static str> - manually implemented trait
let s2: &'static str = Status2::Active.into();
// Both produce &'static str, but:
// - IntoStaticStr: derive macro, variant name as default
// - Into<&'static str>: manual match expression required
}IntoStaticStr reduces boilerplate through derive; Into<&'static str> requires explicit matching.
use strum::IntoStaticStr;
// IntoStaticStr uses associated constants
// The strings are determined at compile time
#[derive(IntoStaticStr)]
enum Color {
Red,
Green,
Blue,
#[strum(to_str = "CustomColor")]
Custom,
}
fn compile_time_strings() {
// Each variant's string is known at compile time
// The derive macro generates associated constants
// Generated code approximately:
// impl IntoStaticStr for Color {
// fn into_static_str(self) -> &'static str {
// match self {
// Color::Red => "Red",
// Color::Green => "Green",
// Color::Blue => "Blue",
// Color::Custom => "CustomColor",
// }
// }
// }
// No runtime string allocation
let color: &'static str = Color::Red.into_static_str();
assert_eq!(color, "Red");
}Both approaches produce &'static str with compile-time guarantees; IntoStaticStr generates via macro.
use strum::IntoStaticStr;
// IntoStaticStr can also provide associated constants
// through the strum_macros crate
#[derive(IntoStaticStr, strum::EnumString, strum::Display)]
enum Direction {
North,
South,
East,
West,
}
fn associated_constants() {
// Each variant has a corresponding &'static str
// Accessible through into_static_str()
let north: &'static str = Direction::North.into_static_str();
let south: &'static str = Direction::South.into_static_str();
// Useful for:
// - API responses
// - Configuration serialization
// - Debug output
// The static str can be stored anywhere:
static DEFAULT_DIRECTION: &str = "North";
let direction_str: &'static str = Direction::North.into_static_str();
// Both have 'static lifetime, can be stored anywhere
}The returned strings have 'static lifetime and can be stored in static variables.
use strum::IntoStaticStr;
#[derive(IntoStaticStr)]
enum Animal {
Dog,
Cat,
Bird,
}
// Implementing Into<&'static str> alongside IntoStaticStr
impl Into<&'static str> for Animal {
fn into(self) -> &'static str {
self.into_static_str() // Delegate to IntoStaticStr
}
}
fn method_names() {
let animal = Animal::Dog;
// IntoStaticStr: specific method name
let str1: &'static str = animal.into_static_str();
// Into<&'static str>: requires .into() method
// Note: animal moved above, need new instance
let str2: &'static str = Animal::Cat.into();
// Both produce same result
assert_eq!(Animal::Bird.into_static_str(), "Bird");
assert_eq!(Animal::Bird.into(), "Bird");
}into_static_str() is explicit; into() is generic but requires the Into trait.
use strum::{IntoStaticStr, Display, EnumString};
#[derive(IntoStaticStr, Display, EnumString)]
enum Priority {
#[strum(to_str = "high_priority", serialize = "high", display = "HIGH")]
High,
#[strum(to_str = "low_priority", serialize = "low", display = "LOW")]
Low,
}
fn strum_traits() {
// IntoStaticStr: returns &'static str
let static_str: &'static str = Priority::High.into_static_str();
println!("Static: {}", static_str); // "high_priority"
// Display: returns String (via to_string)
let display_str: String = Priority::High.to_string();
println!("Display: {}", display_str); // "HIGH"
// EnumString: parses from string
let parsed: Priority = "high".parse().unwrap();
println!("Parsed: {:?}", parsed); // Priority::High
// Each strum trait serves different purposes:
// - IntoStaticStr: compile-time static string
// - Display: human-readable display
// - EnumString: parsing from string
}IntoStaticStr works alongside other strum traits with different purposes.
use strum::IntoStaticStr;
#[derive(IntoStaticStr)]
enum Status {
Active,
Inactive,
}
// IntoStaticStr is a trait from strum
// pub trait IntoStaticStr {
// fn into_static_str(self) -> &'static str;
// }
// Into<&'static str> is a standard library trait
// pub trait Into<T> {
// fn into(self) -> T;
// }
fn trait_differences() {
// IntoStaticStr: explicit trait for static strings
// Self-contained, specific purpose
// Into<&'static str>: generic trait
// Could have multiple Into impls for different types
// If you only need static str conversion:
// - IntoStaticStr is cleaner (derive)
// - Into<&'static str> is more standard but manual
// If you need multiple Into implementations:
// - Can't use Into for both &str and String
// - Would need From instead for automatic Into
}IntoStaticStr is a purpose-built trait; Into<&'static str> is a generic conversion.
use strum::IntoStaticStr;
#[derive(IntoStaticStr)]
enum Level {
Debug,
Info,
Warning,
Error,
}
fn performance() {
// Both IntoStaticStr and Into<&'static str> produce:
// - &'static str: no allocation
// - Compile-time constant string
// - Zero-cost at runtime
let level: &'static str = Level::Error.into_static_str();
// This is equivalent to:
let hardcoded: &'static str = "Error";
// Both compile to:
// - Static string in binary
// - Pointer return value
// - No heap allocation
// IntoStaticStr has same performance as manual implementation
// The derive macro just writes the match expression for you
}Both approaches have identical runtime performance: return a pointer to a static string.
use strum::IntoStaticStr;
// Use IntoStaticStr when:
// 1. You're already using strum for other derive macros
// 2. You want automatic variant name -> string mapping
// 3. You want to customize strings with attributes
// 4. You're working with enums specifically
#[derive(IntoStaticStr, strum::Display)]
enum ApiStatus {
#[strum(to_str = "success")]
Success,
#[strum(to_str = "error")]
Error,
#[strum(to_str = "pending")]
Pending,
}
fn use_into_static_str() {
let status_str: &'static str = ApiStatus::Success.into_static_str();
println!("API status: {}", status_str);
}
// Use Into<&'static str> when:
// 1. You don't want to add strum dependency
// 2. You need the Into trait specifically (interoperability)
// 3. You're implementing for types other than enums
// 4. You want standard library traits only
enum LogLevel {
Debug,
Info,
Warning,
Error,
}
impl Into<&'static str> for LogLevel {
fn into(self) -> &'static str {
match self {
LogLevel::Debug => "DEBUG",
LogLevel::Info => "INFO",
LogLevel::Warning => "WARNING",
LogLevel::Error => "ERROR",
}
}
}
fn use_into_trait() {
let level: &'static str = LogLevel::Error.into();
println!("Level: {}", level);
}Choose IntoStaticStr for convenience with enums; Into<&'static str> for standard library compatibility.
use strum::IntoStaticStr;
#[derive(IntoStaticStr)]
enum Result {
#[strum(to_str = "ok")]
Ok,
#[strum(to_str = "error")]
Err,
}
fn edge_cases() {
// IntoStaticStr consumes self (takes ownership)
let result = Result::Ok;
let str1: &'static str = result.into_static_str();
// result is now moved, cannot use again
// If you need the enum after:
let result2 = Result::Ok;
let str2: &'static str = result2.into_static_str();
// Use str2, result2 is consumed
// To keep the enum, use Clone or reference:
let result3 = Result::Ok;
let str3: &'static str = result3.clone().into_static_str();
// result3 still usable
// Or use Display trait for &self:
let result4 = Result::Ok;
let str4: String = result4.to_string(); // Display trait
// result4 still usable
}into_static_str() takes ownership; use clone() or Display if you need to keep the enum.
Key differences:
| Aspect | IntoStaticStr | Into<&'static str> |
|--------|-----------------|---------------------|
| Source | strum crate | Standard library |
| Implementation | Derive macro | Manual |
| Type support | Enums only | Any type |
| Method name | into_static_str() | into() |
| Customization | #[strum(to_str = "...")] | Manual match arms |
| Interoperability | strum ecosystem | Standard trait |
Code generation comparison:
// IntoStaticStr derive generates:
impl IntoStaticStr for Status {
fn into_static_str(self) -> &'static str {
match self {
Status::Active => "Active",
Status::Inactive => "Inactive",
}
}
}
// Manual Into<&'static str>:
impl Into<&'static str> for Status {
fn into(self) -> &'static str {
match self {
Status::Active => "Active",
Status::Inactive => "Inactive",
}
}
}
// Same result, different source of implementationWhen to choose:
// Choose IntoStaticStr when:
// - Working with enums
// - Using strum for other traits (Display, EnumString, etc.)
// - Want automatic string generation from variant names
// - Prefer derive macros over boilerplate
// Choose Into<&'static str> when:
// - Need standard library trait compatibility
// - Implementing for non-enum types
// - Can't add strum dependency
// - Want full control over implementationKey insight: strum::IntoStaticStr is a convenience derive macro that generates the same code you'd write manually for Into<&'static str>, but specifically tailored for enums. The derive macro inspects variant names and attributes to generate a match expression that returns static strings. Into<&'static str> is the general-purpose standard library approach that works for any type but requires manual implementation. For enums, IntoStaticStr reduces boilerplate and integrates with strum's ecosystem of derive macros. For other types or when avoiding dependencies, Into<&'static str> provides equivalent functionality with manual control.