1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#[macro_export]
macro_rules! make_set_type {
	($name:ident ($internal:ident) / $type:ident) => {
		use std::ops::*;
		#[doc = "A bit set of for filtering and/or smaller costs of storage."]
		#[derive(Clone, Copy, Default, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
		pub struct $name($internal);
		impl $name {
			pub fn new() -> Self {
				$name(0)
			}
			#[doc = "Self contains type"]
			pub fn has<T: Into<$type>>(self, other: T) -> bool {
				let amp = self.0 & (1 << other.into() as u8);
				amp != 0
			}
			#[doc = "Self is contained in part by other"]
			pub fn contains<T: Into<Self>>(self, other: T) -> bool {
				(self & other.into()).0 != 0
			}
			#[doc = "Self is contained in full by other"]
			pub fn contained<T: Into<Self>>(self, other: T) -> bool {
				(self & other.into()) == self
			}
		}
		#[doc = "Utility for converting a single type into a set of itself"]
		impl<T: Into<$type>> From<T> for $name {
			fn from(val: T) -> Self {
				$name(1 << val.into() as u8)
			}
		}
		#[doc = "Utility for converting an optional type into a set of itself (with full state if none)"]
		impl<T: Into<$name>> From<Option<T>> for $name {
			fn from(val: Option<T>) -> Self {
				if let Some(v) = val { v.into() }
				else { $name($internal::max_value()) }
			}
		}
		#[doc = "Utility for converting a list of type-alike into a set of type"]
		impl<T: Into<$type>> From<Vec<T>> for $name {
			fn from(list: Vec<T>) -> Self {
				let mut data = $name(0);
				for child in list {
					data += child.into();
				}
				data
			}
		}
		#[doc = "Utility for the opposite of this set"]
		impl Not for $name {
			type Output = Self;
			fn not(self) -> Self {
				$name(!self.0)
			}
		}
		// Somehow clippy finds this suspicious but not the other ones.
		#[allow(clippy::suspicious_op_assign_impl)]
		#[doc = "Utility for adding type to this bit set"]
		impl AddAssign<$type> for $name {
			fn add_assign(&mut self, rhs: $type) {
				self.0 |= 1 << rhs as u8;
			}
		}
		#[doc = "Utility for removing type from this bit set"]
		impl SubAssign<$type> for $name {
			fn sub_assign(&mut self, rhs: $type) {
				self.0 &= !(1 << rhs as u8);
			}
		}
		#[doc = "Utility for combining two sets"]
		impl BitOrAssign for $name {
			fn bitor_assign(&mut self, rhs: Self) {
				self.0 |= rhs.0;
			}
		}
		#[doc = "Utility for the difference of two sets"]
		impl BitXor for $name {
			type Output = Self;
			fn bitxor(self, rhs: Self) -> Self {
				$name(self.0 ^ rhs.0)
			}
		}
		#[doc = "Utility for combining two sets"]
		impl BitOr for $name {
			type Output = Self;
			fn bitor(self, rhs: Self) -> Self {
				$name(self.0 | rhs.0)
			}
		}
		#[doc = "Utility for the intersection of two sets"]
		impl BitAnd for $name {
			type Output = Self;
			fn bitand(self, rhs: Self) -> Self {
				$name(self.0 & rhs.0)
			}
		}
	};
}