vector_assertions/
lib.rs

1use std::collections::HashMap;
2
3pub fn compare_vec<T: std::fmt::Debug + Eq + std::hash::Hash>(a: &[T], b: &[T]) -> bool {
4    let mut left_values: HashMap<&T, u32> = HashMap::new();
5    for v in a.iter() {
6        match left_values.get_mut(v) {
7            None => {
8                left_values.insert(v, 1);
9            }
10            Some(entry) => *entry += 1,
11        }
12    }
13
14    let mut right_values: HashMap<&T, u32> = HashMap::new();
15    for v in b.iter() {
16        match right_values.get_mut(v) {
17            None => {
18                right_values.insert(v, 1);
19            }
20            Some(entry) => *entry += 1,
21        }
22    }
23    left_values == right_values
24}
25
26/// Asserts that two expressions are equal to each other (using [`PartialEq`, `Hash`]).
27///
28/// On panic, this macro will print the values of the expressions with their
29/// debug representations.
30///
31/// Like [`assert!`], this macro has a second form, where a custom
32/// panic message can be provided.
33///
34/// [`PartialEq`]: cmp/trait.PartialEq.html
35/// [`Hash`]: std/hash/trait.Hash.html
36///
37/// # Examples
38///
39/// ```
40/// # #[macro_use] extern crate vector_assertions;
41/// # fn main() {
42///     let a = vec![1, 2];
43///     let b = vec![2, 1];
44///
45///     assert_vec_eq!(a, b, "we are testing addition with {} and {}", "a", "b");
46/// }
47/// ```
48#[macro_export]
49macro_rules! assert_vec_eq {
50    ($left:expr, $right:expr) => ({
51        match (&$left, &$right) {
52            (left_vec, right_vec) => {
53
54                if !($crate::compare_vec(left_vec, right_vec)) {
55                    // The reborrows below are intentional. Without them, the stack slot for the
56                    // borrow is initialized even before the values are compared, leading to a
57                    // noticeable slow down.
58                    panic!(r#"assertion failed: `(left == right)`
59  left: `{:?}`,
60 right: `{:?}`"#, &*left_vec, &*right_vec)
61                }
62            }
63        }
64    });
65    ($left:expr, $right:expr,) => ({
66        $crate::assert_eq!($left, $right)
67    });
68    ($left:expr, $right:expr, $($arg:tt)+) => ({
69        match (&($left), &($right)) {
70            (left_vec, right_vec) => {
71                if !($crate::compare_vec(left_vec, right_vec)) {
72                    // The reborrows below are intentional. Without them, the stack slot for the
73                    // borrow is initialized even before the values are compared, leading to a
74                    // noticeable slow down.
75                    panic!(r#"assertion failed: `(left == right)`
76  left: `{:?}`,
77 right: `{:?}`: {}"#, &*left_vec, &*right_vec,
78                           std::format_args!($($arg)+))
79                }
80            }
81        }
82    });
83}
84
85#[cfg(test)]
86mod tests {
87    use crate::compare_vec;
88
89    #[test]
90    fn compare_vec_simple() {
91        let a = vec![1, 2];
92        let b = vec![2, 1];
93        let actual = compare_vec(&a, &b);
94        assert!(actual);
95    }
96
97    #[test]
98    fn it_works() {
99        let a = vec![1, 2];
100        let b = vec![2, 1];
101
102        assert_vec_eq!(a, b);
103        assert_vec_eq!(a, b, "we are testing addition with {} and {}", "a", "b");
104    }
105}