'How to check enum with values

How do I check if a vector of enum has a certain member with values?

#[derive(PartialEq,Clone,Copy)]
enum TestResult {
    Pass,
    Fail {point: u8},
}
impl TestResult {
    fn is_fail(&self) -> bool {
        match *self {
            TestResult::Fail{point:_} => true,
            _ => false,
        }
    }
}
fn main() {
    let v1 = vec![TestResult::Pass,
                  TestResult::Pass,
                  TestResult::Fail{point:50}];
    if v1.contains(&TestResult::Pass) {
        println!("result contains Pass");
    }
    if v1.iter().any(|&r| r.is_fail()) {
        println!("result contains Fail");
    }
}

This is working but is there a way to do this with Vec::contains()? I want to check if TestResult::Fail is in a vector in the same way as for TestResult::Pass (no pattern matching. easy..)



Solution 1:[1]

There isn't really an easy way to do this, however we can make a simple macro to perform some pattern matching in the if statement.

/// Performs pattern matching contains on an IntoIter type
macro_rules! matches_any {
    ($iterable:expr, $($tokens:tt)+) => {{
        let iter = ::std::iter::IntoIterator::into_iter($iterable);
        iter.any(|x| matches!(x, $($tokens)+))
    }};
}

The trick here is that we can use the matches! macro instead of a full match statement if all we want to know is if something matches a given pattern.

// Without matches!
match self {
    TestResult::Fail {..} => true,
    _ => false,
}

// With matches!
matches!(self, TestResult::Fail {..})

So now we can use this macro instead:

let v1 = vec![TestResult::Pass,
              TestResult::Pass,
              TestResult::Fail { point: 50 }];

if matches_any!(&v1, TestResult::Pass) {
    println!("result contains Pass");
}

if matches_any!(&v1, TestResult::Fail {..}) {
    println!("result contains Fail");
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Locke