1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4#[must_use]
8pub fn contains_member<T>(set: &[T], value: &T) -> bool
9where
10 T: PartialEq,
11{
12 set.contains(value)
13}
14
15#[must_use]
17pub fn is_subset<T>(left: &[T], right: &[T]) -> bool
18where
19 T: PartialEq,
20{
21 left.iter().all(|value| right.contains(value))
22}
23
24#[must_use]
26pub fn are_disjoint<T>(left: &[T], right: &[T]) -> bool
27where
28 T: PartialEq,
29{
30 left.iter().all(|value| !right.contains(value))
31}
32
33#[must_use]
35pub fn set_union<T>(left: &[T], right: &[T]) -> Vec<T>
36where
37 T: Clone + PartialEq,
38{
39 let mut values = Vec::new();
40
41 append_unique(&mut values, left);
42 append_unique(&mut values, right);
43
44 values
45}
46
47#[must_use]
49pub fn set_intersection<T>(left: &[T], right: &[T]) -> Vec<T>
50where
51 T: Clone + PartialEq,
52{
53 let mut values = Vec::new();
54
55 for value in left {
56 if right.contains(value) {
57 push_unique(&mut values, value);
58 }
59 }
60
61 values
62}
63
64#[must_use]
66pub fn set_difference<T>(left: &[T], right: &[T]) -> Vec<T>
67where
68 T: Clone + PartialEq,
69{
70 let mut values = Vec::new();
71
72 for value in left {
73 if !right.contains(value) {
74 push_unique(&mut values, value);
75 }
76 }
77
78 values
79}
80
81#[must_use]
83pub fn set_symmetric_difference<T>(left: &[T], right: &[T]) -> Vec<T>
84where
85 T: Clone + PartialEq,
86{
87 let mut values = set_difference(left, right);
88
89 for value in right {
90 if !left.contains(value) {
91 push_unique(&mut values, value);
92 }
93 }
94
95 values
96}
97
98fn append_unique<T>(target: &mut Vec<T>, source: &[T])
99where
100 T: Clone + PartialEq,
101{
102 for value in source {
103 push_unique(target, value);
104 }
105}
106
107fn push_unique<T>(target: &mut Vec<T>, value: &T)
108where
109 T: Clone + PartialEq,
110{
111 if !target.contains(value) {
112 target.push(value.clone());
113 }
114}
115
116pub mod prelude;
117
118#[cfg(test)]
119mod tests {
120 use super::{
121 are_disjoint, contains_member, is_subset, set_difference, set_intersection,
122 set_symmetric_difference, set_union,
123 };
124
125 #[test]
126 fn evaluates_membership_and_relations() {
127 let left = [1, 2, 2, 3];
128 let right = [2, 3, 4];
129 let subset = [2, 2, 3];
130
131 assert!(contains_member(&left, &2));
132 assert!(!contains_member(&left, &5));
133 assert!(is_subset(&subset, &right));
134 assert!(!is_subset(&left, &right));
135 assert!(are_disjoint(&[7, 8], &right));
136 assert!(!are_disjoint(&left, &right));
137 }
138
139 #[test]
140 fn computes_order_preserving_set_operations() {
141 let left = [1, 2, 2, 3];
142 let right = [3, 4, 2, 5];
143
144 assert_eq!(set_union(&left, &right), vec![1, 2, 3, 4, 5]);
145 assert_eq!(set_intersection(&left, &right), vec![2, 3]);
146 assert_eq!(set_difference(&left, &right), vec![1]);
147 assert_eq!(set_symmetric_difference(&left, &right), vec![1, 4, 5]);
148 }
149}