Skip to main content

kernal/collections/partial_eq/
btree.rs

1//! Contains equality-based assertions for [Collection]s with items that implement [Eq] and [Ord],
2//! using the additional constraints to optimize runtime. See [CollectionEqOrdAssertions] for more
3//! details.
4
5use std::borrow::Borrow;
6use std::collections::BTreeSet;
7use std::fmt::Debug;
8
9use crate::AssertThat;
10use crate::collections::Collection;
11use crate::collections::partial_eq::{
12    check_contains_all_of,
13    check_contains_exactly_in_any_order,
14    check_contains_none_of,
15};
16use crate::util::borrow_all;
17use crate::util::multiset::btree::BTreeMultiset;
18
19/// An extension trait to be used on the output of [assert_that](crate::assert_that) with an
20/// argument that implements the [Collection] trait where the [Collection::Item] type implements
21/// [Eq] and [Ord] in addition to the required [Debug] trait. It offers optimized assertions which
22/// benefit from the additional [Ord] constraint in terms of runtime.
23///
24/// Examples:
25///
26/// ```
27/// use kernal::prelude::*;
28/// use kernal::fast_prelude::*;
29///
30/// assert_that!(&[2, 3, 5, 7, 11])
31///     .contains_exactly_in_any_order_using_ord([3, 7, 2, 11, 5])
32///     .contains_none_of_using_ord([4, 6, 8, 10, 12]);
33/// ```
34pub trait CollectionEqOrdAssertions<C>
35where
36    C: Collection,
37{
38    /// Asserts that for each of the given `items`, the tested collection contains an equal element
39    /// according to [Eq] and [Ord]. If the provided iterator contains multiple equal elements, this
40    /// function asserts that the tested collection contains at least that number of equal elements,
41    /// so `[1, 1, 2]` contains all of `[1, 1]`, but not all of `[1, 1, 1]`.
42    ///
43    /// This can be considered a faster alternative to
44    /// [CollectionPartialEqAssertions::contains_all_of](crate::collections::partial_eq::CollectionPartialEqAssertions::contains_all_of)
45    /// with the trade-off of additional trait bounds.
46    fn contains_all_of_using_ord<E, I>(self, items: I) -> Self
47    where
48        E: Borrow<C::Item>,
49        I: IntoIterator<Item = E>;
50
51    /// Asserts that the tested collection contains no element which is equal to one the given
52    /// `items` according to [Eq] and [Ord].
53    ///
54    /// This can be considered a faster alternative to
55    /// [CollectionPartialEqAssertions::contains_none_of](crate::collections::partial_eq::CollectionPartialEqAssertions::contains_none_of)
56    /// with the trade-off of additional trait bounds.
57    fn contains_none_of_using_ord<E, I>(self, items: I) -> Self
58    where
59        E: Borrow<C::Item>,
60        I: IntoIterator<Item = E>;
61
62    /// Asserts that there is a one-to-one matching of the given `items` and the elements of the
63    /// tested collection such that matched elements are equal according to [Eq] and [Ord].
64    ///
65    /// This can be considered a faster alternative to
66    /// [CollectionPartialEqAssertions::contains_exactly_in_any_order](crate::collections::partial_eq::CollectionPartialEqAssertions::contains_exactly_in_any_order)
67    /// with the trade-off of additional trait bounds.
68    fn contains_exactly_in_any_order_using_ord<E, I>(self, items: I) -> Self
69    where
70        E: Borrow<C::Item>,
71        I: IntoIterator<Item = E>;
72}
73
74impl<C> CollectionEqOrdAssertions<C> for AssertThat<C>
75where
76    C: Collection,
77    C::Item: Debug + Eq + Ord,
78{
79    fn contains_all_of_using_ord<E, I>(self, items: I) -> Self
80    where
81        E: Borrow<C::Item>,
82        I: IntoIterator<Item = E>,
83    {
84        let expected_items_unborrowed = items.into_iter().collect::<Vec<_>>();
85        let expected_items: Vec<&C::Item> = borrow_all(&expected_items_unborrowed);
86
87        check_contains_all_of::<_, _, BTreeMultiset<_>>(
88            &self,
89            self.data.iterator(),
90            &expected_items,
91        );
92
93        self
94    }
95
96    fn contains_none_of_using_ord<E, I>(self, items: I) -> Self
97    where
98        E: Borrow<C::Item>,
99        I: IntoIterator<Item = E>,
100    {
101        let unexpected_items_unborrowed = items.into_iter().collect::<Vec<_>>();
102        let unexpected_items: Vec<&C::Item> = borrow_all(&unexpected_items_unborrowed);
103
104        check_contains_none_of::<_, _, BTreeSet<_>>(&self, self.data.iterator(), unexpected_items);
105
106        self
107    }
108
109    fn contains_exactly_in_any_order_using_ord<E, I>(self, items: I) -> Self
110    where
111        E: Borrow<C::Item>,
112        I: IntoIterator<Item = E>,
113    {
114        let expected_items_unborrowed = items.into_iter().collect::<Vec<_>>();
115        let expected_items: Vec<&C::Item> = borrow_all(&expected_items_unborrowed);
116
117        check_contains_exactly_in_any_order::<_, _, BTreeMultiset<_>>(
118            &self,
119            self.data.iterator(),
120            &expected_items,
121        );
122
123        self
124    }
125}
126
127#[cfg(test)]
128mod tests {
129
130    use super::*;
131    use crate::prelude::*;
132    use crate::{
133        assert_fails,
134        test_contains_all_of,
135        test_contains_exactly_in_any_order,
136        test_contains_none_of,
137    };
138
139    test_contains_all_of!(contains_all_of_using_ord);
140
141    test_contains_none_of!(contains_none_of_using_ord);
142
143    test_contains_exactly_in_any_order!(contains_exactly_in_any_order_using_ord);
144}