What's the most idiomatic way to test two Options for equality when they contain values which can be tested for equality?

后端 未结 2 1982
栀梦
栀梦 2021-02-19 14:22

I have two types that can be tested for equality. However, once I wrap them in Options, the nicety provided by various PartialEq implementations goes r

2条回答
  •  面向向阳花
    2021-02-19 14:50

    As of Rust 1.40, you can use as_deref() so you don't have to remember what is what:

    assert_eq!(a.as_deref(), b.as_deref());
    

    Before Rust 1.40, I would do something like this:

    match (&a, &b) {
        (Some(a), Some(b)) => assert_eq!(a, b),
        (None, None) => (),
        _ => panic!("a and b not equal"),
    }
    

    Another option is a custom assertion, based on assert_eq!:

    macro_rules! cmp_eq_option {
        ($left:expr, $right:expr) => {{
            match (&$left, &$right) {
                (Some(left_val), Some(right_val)) => *left_val == *right_val,
                (None, None) => true,
                _ => false,
            }
        }};
    }
    
    #[macro_export]
    macro_rules! assert_eq_option {
        ($left:expr, $right:expr) => ({
            if !cmp_eq_option!($left, $right) {
                panic!(r#"assertion failed: `(left == right)`
      left: `{:?}`,
     right: `{:?}`"#, $left, $right)
            }
        });
        ($left:expr, $right:expr,) => ({
            assert_eq_option!($left, $right)
        });
        ($left:expr, $right:expr, $($arg:tt)+) => ({
            if !cmp_eq_option!($left, $right) {
                panic!(r#"assertion failed: `(left == right)`
      left: `{:?}`,
     right: `{:?}`: {}"#, $left, $right, format_args!($($arg)+))
            }
        });
    }
    

提交回复
热议问题