How to create a new instance of an enum from a string and how to convert the enum
instance to a string?
In this example we have a very simple enum
called Animal
that has 3 variants:
enum Animal {
Cat,
Dog,
Fish,
}
We derived it from Debug using the following line in order to allow us to print the value of an instance
using the {:?}
debugging format. (Or the dbg!
macro for that matter.)
#[derive(Debug)]
So we can write this:
println!("{c:?}");
Converting string to enum variant
We wanted to be able to write something like this and let it return Animal::Cat
:
let c = Animal::new("cat");
For this we implemented the new
method for the Animal
enum and mapped each string to the appropriate variant.
This mapping allows us to accept alternatives. For example, I included both "dog" and "hound" to be mapped to "Animal::Dog".
As we are using match
on an &str
string Rust forces us to have an "arm" for each possible value, so we have to provide a catch-all
default case. We could return "Animal::Dog" or any other variant as the default, but here we elected to panic!
.
impl Animal {
fn new(text: &str) -> Self {
match text {
"cat" => Animal::Cat,
"dog" => Animal::Dog,
"fish" => Animal::Fish,
"hound" => Animal::Dog,
// default is required
_ => panic!("No such animal as {text:?}"),
}
}
}
Convert enum variant to string
We also want to be able to convert the variant to a string in order to be able to use this:
println!("{c}");
For this we need to implement the Display trait mapping each variant to the string to display:
impl std::fmt::Display for Animal {
fn fmt(&self, format: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let text = match self {
Animal::Cat => "cat",
Animal::Dog => "dog",
Animal::Fish => "fish",
};
write!(format, "{text}")
}
}
Full example
examples/serialize-deserialize-enum-manually/src/main.rs
#[derive(Debug)]
enum Animal {
Cat,
Dog,
Fish,
}
impl Animal {
fn new(text: &str) -> Self {
match text {
"cat" => Animal::Cat,
"dog" => Animal::Dog,
"fish" => Animal::Fish,
"hound" => Animal::Dog,
// default is required
_ => panic!("No such animal as {text:?}"),
}
}
}
impl std::fmt::Display for Animal {
fn fmt(&self, format: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let text = match self {
Animal::Cat => "cat",
Animal::Dog => "dog",
Animal::Fish => "fish",
};
write!(format, "{text}")
}
}
fn main() {
let c = Animal::new("cat");
println!("{c:?}");
println!("{c}");
let d = Animal::new("hound");
println!("{d}");
let m = Animal::new("mouse");
println!("{m}");
}