Dear Rustaceans,
I have a HashMap called apple
, it stores values of different types with a enum called Var
. I want to compare the values of the HashMap with an if statement, for example apple["isRed?"] == true
, to achieve this, I wanted a method to return the value of the enum, for example Var::Bool
, but I cannot get it to work, I tried with a match statement but the compiler expects T
but gets &bool
, for example Self::Bool(out) => out,
.
Hard to explain, here is the playground:
Thank you in advance,
FatGoose
jofas
December 30, 2024, 11:17am
2
See this answer for an outline of your get_value
method:
There's no need for unsafe; trait Any provides downcast_ref to encapsulate the pattern.
pub fn get<T: 'static>(&self) -> Option<&T> {
let x: &dyn Any = match self {
Self::A(x) => x,
Self::B(x) => x,
Self::C(x) => x,
};
x.downcast_ref()
}
1 Like
Note that this is a trigger-happy footgun. Any mistake made in the type and you'll get None
when you expected Some(&T)
.
It's better to use the matches
macro:
if matches!(apple.get("Name"), Some(Var::String(x)) if x == "Pink Lady")
erelde
December 30, 2024, 12:17pm
4
Is there a reason your apple isn't a normal struct? It seems like it would be more naturally expressed as a struct.
Thank you, that helped.
Solution
fn main()
{
let mut apple = std::collections::HashMap::from([
("Name", Var::String("Pink Lady".to_string())),
("Amount", Var::Int(12)),
("Red", Var::Bool(true)),
("Size in cm", Var::Float(3.4)),
("Sellable?", Var::Bool(false)),
]);
if apple["Name"].get_value::<String>().unwrap() == "Pink Lady"
&& *apple["Red"].get_value().unwrap()
&& *apple["Size in cm"].get_value::<f64>().unwrap() >= 1.2
{
*apple.entry("Sellable?").or_insert(Var::Bool(true)) = Var::Bool(true);
println!("The apple is sellable. {}", *apple["Sellable?"].get_value::<bool>().unwrap());
}
}
enum Var
{
Bool(bool),
Int(i32),
Float(f64),
String(String),
}
impl Var
{
fn get_value<T: 'static>(&self) -> Option<&T>
{
let output: &dyn std::any::Any = match self
{
Self::Bool(value) => value,
Self::Int(value) => value,
Self::Float(value) => value,
Self::String(value) => value,
};
if output.downcast_ref::<T>().is_none()
{
panic!("Option<T> should not be 'None'");
}
output.downcast_ref()
}
}
EDIT: fixed mistakes in code.
Hello erelde,
there is the reason, because I will later on implement function, that allows a user to add attributes to the apple.