flag_set/
lib.rs

1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(dead_code)]
4
5//! [![Crate](https://img.shields.io/crates/v/flag_set)](https://crates.io/crates/flag_set) [![doc.rs](https://img.shields.io/docsrs/flag_set/0.1.6)](https://docs.rs/flag_set/)<br>
6//! `HashSet` only implements the normal set. `HashSet` can not represent its complementary set when the complementary set is an infinite set.
7//! 
8//! `FlagSet` implemented as a tuple of a `HashSet` and a  `bool` value. When the `bool` value is true, `FlagSet` represents the `HashSet`.  When the `bool` value is true, `FlagSet` represents the the complementary set of `HashSet`.
9//! 
10//! As with the [`HashSet`](https://doc.rust-lang.org/std/collections/struct.HashSet.html) type, a `FlagSet` requires that the elements implement the [`Eq`](https://doc.rust-lang.org/std/cmp/trait.Eq.html) and [`Hash`](https://doc.rust-lang.org/std/hash/trait.Hash.html) traits. In addition to operations of `FlagSet`, the elements also implement the  [`Clone`](https://doc.rust-lang.org/std/clone/trait.Clone.html) trait.
11//! 
12//! `FlagSet` also defines five kinds of operations of sets based on  [`Binary Operations`](http://www.unicode.org/reports/tr18/#Resolving_Character_Ranges_with_Strings).
13//! 
14//! 
15//! A ∪B -> A + B 
16//! 
17//! A ∩ B -> A & B
18//! 
19//! A - B -> A - B
20//! 
21//! A Xor B -> A ^ B
22//! 
23//! C<sub>u</sub>A -> !A
24//! 
25//! # Examples
26//! 
27//! ```rust
28//! use std::collections::HashSet;
29//! use flag_set::FlagSet;
30//! 
31//! let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
32//! let b: HashSet<_> = vec![2, 3, 4].into_iter().collect();
33//! 
34//! let flag_ap = FlagSet(a.clone(), true);
35//! let flag_an = FlagSet(a.clone(), false);
36//! let flag_bp = FlagSet(b.clone(), true);
37//! let flag_bn = FlagSet(b.clone(), false);
38//! 
39//! // 用new方法创建实例
40//! // use new method create an instance
41//! assert_eq!(flag_bn, FlagSet::new(vec![2, 3, 4], false));
42//! 
43//! // 测试并
44//! // test union
45//! assert_eq!(FlagSet::new(vec![1, 2, 3, 4], true), flag_ap.clone() + flag_bp.clone());
46//! assert_eq!(FlagSet::new(vec![4], false), flag_ap.clone() + flag_bn.clone());
47//! assert_eq!(FlagSet::new(vec![1], false), flag_an.clone() + flag_bp.clone());
48//! assert_eq!(FlagSet::new(vec![2, 3], false), flag_an.clone() + flag_bn.clone());
49//! 
50//! // 测试交
51//! // test intersection
52//! assert_eq!(FlagSet::new(vec![2, 3], true), flag_ap.clone() & flag_bp.clone());
53//! assert_eq!(FlagSet::new(vec![1], true), flag_ap.clone() & flag_bn.clone());
54//! assert_eq!(FlagSet::new(vec![4], true), flag_an.clone() & flag_bp.clone());
55//! assert_eq!(FlagSet::new(vec![1, 2, 3, 4], false), flag_an.clone() & flag_bn.clone());
56//! 
57//! // 测试减
58//! // test substraction
59//! assert_eq!(FlagSet::new(vec![1], true), flag_ap.clone() - flag_bp.clone());
60//! assert_eq!(FlagSet::new(vec![2, 3], true), flag_ap.clone() - flag_bn.clone());
61//! assert_eq!(FlagSet::new(vec![1, 2, 3, 4], false), flag_an.clone() - flag_bp.clone());
62//! assert_eq!(FlagSet::new(vec![4], true), flag_an.clone() - flag_bn.clone());
63//! 
64//! // 测试否
65//! // test not
66//! assert_eq!(FlagSet(a.clone(), true), !flag_an.clone());
67//! 
68//! // 测试对称差
69//! // test symmetric difference
70//! assert_eq!(FlagSet::new(vec![1, 4], true), flag_ap.clone() ^ flag_bp.clone());
71//! ```
72//! 
73
74#[cfg(test)]
75mod tests {
76    #[test]
77    fn it_works() {
78
79        use std::collections::HashSet;
80        use super::FlagSet;
81        
82        let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
83        let b: HashSet<_> = vec![2, 3, 4].into_iter().collect();
84
85        let flag_ap = FlagSet(a.clone(), true);
86        let flag_an = FlagSet(a.clone(), false);
87        let flag_bp = FlagSet(b.clone(), true);
88        let flag_bn = FlagSet(b.clone(), false);
89        
90        // 用new方法创建实例
91        // use new method create an instance
92        assert_eq!(flag_bn, FlagSet::new(vec![2, 3, 4], false));
93
94        // 测试contains方法
95        // test contains
96        assert!(flag_an.contains(4));
97
98        // 测试并
99        // test union
100        assert_eq!(FlagSet::new(vec![1, 2, 3, 4], true), flag_ap.clone() + flag_bp.clone());
101        assert_eq!(FlagSet::new(vec![4], false), flag_ap.clone() + flag_bn.clone());
102        assert_eq!(FlagSet::new(vec![1], false), flag_an.clone() + flag_bp.clone());
103        assert_eq!(FlagSet::new(vec![2, 3], false), flag_an.clone() + flag_bn.clone());
104
105        // 测试交
106        // test intersection
107        assert_eq!(FlagSet::new(vec![2, 3], true), flag_ap.clone() & flag_bp.clone());
108        assert_eq!(FlagSet::new(vec![1], true), flag_ap.clone() & flag_bn.clone());
109        assert_eq!(FlagSet::new(vec![4], true), flag_an.clone() & flag_bp.clone());
110        assert_eq!(FlagSet::new(vec![1, 2, 3, 4], false), flag_an.clone() & flag_bn.clone());
111
112        // 测试减
113        // test substraction
114        assert_eq!(FlagSet::new(vec![1], true), flag_ap.clone() - flag_bp.clone());
115        assert_eq!(FlagSet::new(vec![2, 3], true), flag_ap.clone() - flag_bn.clone());
116        assert_eq!(FlagSet::new(vec![1, 2, 3, 4], false), flag_an.clone() - flag_bp.clone());
117        assert_eq!(FlagSet::new(vec![4], true), flag_an.clone() - flag_bn.clone());
118
119        // 测试否
120        // test not
121        assert_eq!(FlagSet(a.clone(), true), !flag_an.clone());
122
123        // 测试对称差
124        // test symmetric difference
125        assert_eq!(FlagSet::new(vec![1, 4], true), flag_ap.clone() ^ flag_bp.clone());
126    }
127}
128
129use std::collections::HashSet;
130use std::hash::Hash;
131
132#[derive(Debug, Clone, Eq, PartialEq)]
133pub struct FlagSet<T: Eq + Hash>(HashSet<T>, bool);
134
135// impl Default
136impl<T: Eq + Hash> Default for FlagSet<T> {
137    /// 空集。<br>
138    /// Creating an empty set.
139    fn default() -> Self {
140        Self(HashSet::<T>::with_capacity(0), true)
141    }
142
143}
144
145// 实现了contains方法
146// impl contains method
147impl<'a, T: Eq + Hash + Clone> FlagSet<T> {
148
149    /// 用vector和bool新建实例。<br>
150    /// Ccreating an instance with a vector and a boolean value.
151    pub fn new(vector: Vec<T>, flag: bool) -> Self {
152        Self(vector.into_iter().collect(), flag)
153    }
154    /// 判断集合是否包含值。<br>
155    /// Identifying whether set contains value
156    pub fn contains(&self, value: T) -> bool {
157        !(self.0.contains(&value) ^ self.1)
158    }
159}
160
161use std::ops::{Add, BitAnd, Not, Sub, BitXor};
162
163// 并
164// union
165impl<T: Eq + Hash + Clone> Add for FlagSet<T> {
166    type Output = Self;
167    /// A + B<br>
168    /// A和B会销毁,所以用希望保留A和B的话,请使用A.clone() + B.clone()。<br>
169    /// A and B will be consumed. If you want to reserve A and B, using A.clone() + B.clone() instead of A + B.
170    fn add(self, other: Self) -> Self::Output {
171        match (self, other) {
172
173            (FlagSet(A, true), FlagSet(B, true)) => Self(&A | &B, true),
174            (FlagSet(A, true), FlagSet(B, false)) => Self(&B - &A, false),
175            (FlagSet(A, false), FlagSet(B, true)) => Self(&A - &B, false),
176            (FlagSet(A, false), FlagSet(B, false)) => Self(&A & &B, false),
177        }
178    }
179}
180
181// 交
182// intersection
183impl<T: Eq + Hash + Clone> BitAnd for FlagSet<T> {
184    type Output = Self;
185    /// A & B<br>
186    /// A和B会销毁,所以用希望保留A和B的话,请使用A.clone() & B.clone()。<br>
187    /// A and B will be consumed. If you want to reserve A and B, using A.clone() & B.clone() instead of A & B.
188    fn bitand(self, other: Self) -> Self::Output {
189        match (self, other) {
190
191            (FlagSet(A, true), FlagSet(B, true)) => Self(&A & &B, true),
192            (FlagSet(A, true), FlagSet(B, false)) => Self(&A - &B, true),
193            (FlagSet(A, false), FlagSet(B, true)) => Self(&B - &A, true),
194            (FlagSet(A, false), FlagSet(B, false)) => Self(&A | &B, false),
195        }
196    }
197}
198
199
200// 差
201// subtraction
202impl<T: Eq + Hash + Clone> Sub for FlagSet<T> {
203    type Output = Self;
204    /// A - B<br>
205    /// A和B会销毁,所以用希望保留A和B的话,请使用A.clone() - B.clone()。<br>
206    /// A and B will be consumed. If you want to reserve A and B, using A.clone() - B.clone() instead of A - B.
207    fn sub(self, other: Self) -> Self::Output {
208        match (self, other) {
209
210            (FlagSet(A, true), FlagSet(B, true)) => Self(&A - &B, true),
211            (FlagSet(A, true), FlagSet(B, false)) => Self(&A & &B, true),
212            (FlagSet(A, false), FlagSet(B, true)) => Self(&A | &B, false),
213            (FlagSet(A, false), FlagSet(B, false)) => Self(&B - &A, true),
214        }
215    }
216}
217
218// 对称差
219// symmetric difference
220impl<T: Eq + Hash + Clone> BitXor for FlagSet<T> {
221    type Output = Self;
222    /// A ^ B<br>
223        /// A和B会销毁,所以用希望保留A和B的话,请使用A.clone() ^ B.clone()。<br>
224    /// A and B will be consumed. If you want to reserve A and B, using A.clone() ^ B.clone() instead of A ^ B.
225    fn bitxor(self, other: Self) -> Self::Output {
226        (self.clone() + other.clone()) - (self & other)
227    }
228}
229
230// 否
231// not
232impl<T: Eq + Hash + Clone> Not for FlagSet<T> {
233    type Output = Self;
234    /// !A<br>
235    /// 不同于二(次)元操作,A不会销毁,只转换了A的布尔值。<br>
236    /// ! operation differs from the above binary operations. A only transforms its bool value. A is not destroyed.
237    fn not(mut self) -> Self::Output {
238        self.1 = !self.1;
239        self
240    }
241}