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}