This code works, but is extremely ugly. This is a question from exercism.org under the Rust track. How can I avoid using try_into().unwrap() everywhere?
What am I doing wrong, and how can I learn to write more idiomatic code?
pub struct Allergies {
score: u32,
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Allergen {
Eggs = 1,
Peanuts = 2,
Shellfish = 4,
Strawberries = 8,
Tomatoes = 16,
Chocolate = 32,
Pollen = 64,
Cats = 128,
}
impl Allergies {
pub fn new(score: u32) -> Self {
Allergies { score }
}
pub fn is_allergic_to(&self, allergen: &Allergen) -> bool {
let mut score = self.score;
score %= 256;
for i in (0..8).rev() {
if 2_i32.pow(i.try_into().unwrap()) != *allergen as i32 && score >= 2_u32.pow(i.try_into().unwrap()) {
score -= 2_u32.pow(i.try_into().unwrap());
} else if 2_i32.pow(i.try_into().unwrap()) == *allergen as i32 && score >= 2_u32.pow(i.try_into().unwrap()) {
return true;
}
}
false
}
pub fn allergies(&self) -> Vec<Allergen> {
let allergens:[Allergen; 8] = [Allergen::Eggs, Allergen::Peanuts, Allergen::Shellfish, Allergen::Strawberries, Allergen::Tomatoes, Allergen::Chocolate, Allergen::Pollen, Allergen::Cats];
let mut allergies = Vec::<Allergen>::new();
for allergen in allergens.iter() {
if self.is_allergic_to(allergen) {
allergies.push(*allergen)
}
}
allergies
}
}
Notice this bit which is terrible:
if 2_i32.pow(i.try_into().unwrap()) != *allergen as i32 && score >= 2_u32.pow(i.try_into().unwrap()) {
score -= 2_u32.pow(i.try_into().unwrap());
} else if 2_i32.pow(i.try_into().unwrap()) == *allergen as i32 && score >= 2_u32.pow(i.try_into().unwrap()) {
return true;
}
How can I rewrite this whole thing to be more beautiful?