enumset/repr/
primitive.rs1use crate::repr::EnumSetTypeRepr;
2
3pub trait Primitive {
4 fn leading_zeros(&self) -> u32;
5 fn trailing_zeros(&self) -> u32;
6}
7
8macro_rules! prim {
9 ($name:ty, $width:expr, $preferred_array_len:expr) => {
10 const _: () = {
11 fn lo(v: $name) -> u64 {
12 v as u64
13 }
14 fn hi(v: $name) -> u64 {
15 ((v as u128) >> 64) as u64
16 }
17
18 impl EnumSetTypeRepr for $name {
19 const PREFERRED_ARRAY_LEN: usize = $preferred_array_len;
20 const WIDTH: u32 = $width;
21 const EMPTY: Self = 0;
22
23 #[inline(always)]
24 fn is_empty(&self) -> bool {
25 *self == 0
26 }
27
28 #[inline(always)]
29 fn add_bit(&mut self, bit: u32) {
30 *self |= 1 << bit as $name;
31 }
32 #[inline(always)]
33 fn remove_bit(&mut self, bit: u32) {
34 *self &= !(1 << bit as $name);
35 }
36 #[inline(always)]
37 fn has_bit(&self, bit: u32) -> bool {
38 (self & (1 << bit as $name)) != 0
39 }
40
41 #[inline(always)]
42 fn count_ones(&self) -> u32 {
43 (*self).count_ones()
44 }
45
46 #[inline(always)]
47 fn and_not(&self, other: Self) -> Self {
48 (*self) & !other
49 }
50
51 type Iter = PrimitiveIter<Self>;
52 #[inline]
53 fn iter(self) -> Self::Iter {
54 PrimitiveIter(self)
55 }
56
57 #[inline(always)]
58 fn from_u8(v: u8) -> Self {
59 v as $name
60 }
61 #[inline(always)]
62 fn from_u16(v: u16) -> Self {
63 v as $name
64 }
65 #[inline(always)]
66 fn from_u32(v: u32) -> Self {
67 v as $name
68 }
69 #[inline(always)]
70 fn from_u64(v: u64) -> Self {
71 v as $name
72 }
73 #[inline(always)]
74 fn from_u128(v: u128) -> Self {
75 v as $name
76 }
77 #[inline(always)]
78 fn from_usize(v: usize) -> Self {
79 v as $name
80 }
81
82 #[inline(always)]
83 fn to_u8(&self) -> u8 {
84 (*self) as u8
85 }
86 #[inline(always)]
87 fn to_u16(&self) -> u16 {
88 (*self) as u16
89 }
90 #[inline(always)]
91 fn to_u32(&self) -> u32 {
92 (*self) as u32
93 }
94 #[inline(always)]
95 fn to_u64(&self) -> u64 {
96 (*self) as u64
97 }
98 #[inline(always)]
99 fn to_u128(&self) -> u128 {
100 (*self) as u128
101 }
102 #[inline(always)]
103 fn to_usize(&self) -> usize {
104 (*self) as usize
105 }
106
107 #[inline(always)]
108 fn from_u8_opt(v: u8) -> Option<Self> {
109 v.try_into().ok()
110 }
111 #[inline(always)]
112 fn from_u16_opt(v: u16) -> Option<Self> {
113 v.try_into().ok()
114 }
115 #[inline(always)]
116 fn from_u32_opt(v: u32) -> Option<Self> {
117 v.try_into().ok()
118 }
119 #[inline(always)]
120 fn from_u64_opt(v: u64) -> Option<Self> {
121 v.try_into().ok()
122 }
123 #[inline(always)]
124 fn from_u128_opt(v: u128) -> Option<Self> {
125 v.try_into().ok()
126 }
127 #[inline(always)]
128 fn from_usize_opt(v: usize) -> Option<Self> {
129 v.try_into().ok()
130 }
131
132 #[inline(always)]
133 fn to_u8_opt(&self) -> Option<u8> {
134 (*self).try_into().ok()
135 }
136 #[inline(always)]
137 fn to_u16_opt(&self) -> Option<u16> {
138 (*self).try_into().ok()
139 }
140 #[inline(always)]
141 fn to_u32_opt(&self) -> Option<u32> {
142 (*self).try_into().ok()
143 }
144 #[inline(always)]
145 fn to_u64_opt(&self) -> Option<u64> {
146 (*self).try_into().ok()
147 }
148 #[inline(always)]
149 fn to_u128_opt(&self) -> Option<u128> {
150 (*self).try_into().ok()
151 }
152 #[inline(always)]
153 fn to_usize_opt(&self) -> Option<usize> {
154 (*self).try_into().ok()
155 }
156
157 #[inline(always)]
158 fn to_u64_array<const O: usize>(&self) -> [u64; O] {
159 let mut array = [0; O];
160 if O > 0 {
161 array[0] = lo(*self);
162 }
163 if O > 1 && $preferred_array_len == 2 {
164 array[1] = hi(*self);
165 }
166 array
167 }
168 #[inline(always)]
169 fn to_u64_array_opt<const O: usize>(&self) -> Option<[u64; O]> {
170 if O == 0 && *self != 0 {
171 None
172 } else if O == 1 && hi(*self) != 0 {
173 None
174 } else {
175 Some(self.to_u64_array())
176 }
177 }
178
179 #[inline(always)]
180 fn from_u64_array<const O: usize>(v: [u64; O]) -> Self {
181 if O == 0 {
182 0
183 } else if O > 1 && $preferred_array_len == 2 {
184 Self::from_u128(v[0] as u128 | ((v[1] as u128) << 64))
185 } else {
186 Self::from_u64(v[0])
187 }
188 }
189 #[inline(always)]
190 fn from_u64_array_opt<const O: usize>(v: [u64; O]) -> Option<Self> {
191 if O == 0 {
192 Some(0)
193 } else if O == 1 {
194 Self::from_u64_opt(v[0])
195 } else {
196 for i in 2..O {
197 if v[i] != 0 {
198 return None;
199 }
200 }
201 Self::from_u128_opt(v[0] as u128 | ((v[1] as u128) << 64))
202 }
203 }
204
205 #[inline(always)]
206 fn to_u64_slice(&self, out: &mut [u64]) {
207 if out.len() > 0 {
208 out[0] = lo(*self);
209 }
210 if out.len() > 1 && $preferred_array_len == 2 {
211 out[1] = hi(*self);
212 }
213 for i in $preferred_array_len..out.len() {
214 out[i] = 0;
215 }
216 }
217 #[inline(always)]
218 fn to_u64_slice_opt(&self, out: &mut [u64]) -> Option<()> {
219 if out.len() == 0 && *self != 0 {
220 None
221 } else if out.len() == 1 && hi(*self) != 0 {
222 None
223 } else {
224 self.to_u64_slice(out);
225 Some(())
226 }
227 }
228
229 #[inline(always)]
230 fn from_u64_slice(v: &[u64]) -> Self {
231 if v.len() == 0 {
232 0
233 } else if v.len() > 1 && $preferred_array_len == 2 {
234 Self::from_u128(v[0] as u128 | ((v[1] as u128) << 64))
235 } else {
236 Self::from_u64(v[0])
237 }
238 }
239 #[inline(always)]
240 fn from_u64_slice_opt(v: &[u64]) -> Option<Self> {
241 if v.len() == 0 {
242 Some(0)
243 } else if v.len() == 1 {
244 Self::from_u64_opt(v[0])
245 } else {
246 for i in 2..v.len() {
247 if v[i] != 0 {
248 return None;
249 }
250 }
251 Self::from_u128_opt(v[0] as u128 | ((v[1] as u128) << 64))
252 }
253 }
254 }
255 impl Primitive for $name {
256 #[inline(always)]
257 fn leading_zeros(&self) -> u32 {
258 (*self).leading_zeros()
259 }
260 #[inline(always)]
261 fn trailing_zeros(&self) -> u32 {
262 (*self).trailing_zeros()
263 }
264 }
265 };
266 };
267}
268prim!(u8, 8, 1);
269prim!(u16, 16, 1);
270prim!(u32, 32, 1);
271prim!(u64, 64, 1);
272prim!(u128, 128, 2);
273
274#[derive(Copy, Clone, Debug)]
275#[repr(transparent)]
276pub struct PrimitiveIter<T: EnumSetTypeRepr + Primitive>(pub T);
277
278impl<T: EnumSetTypeRepr + Primitive> Iterator for PrimitiveIter<T> {
279 type Item = u32;
280
281 fn next(&mut self) -> Option<Self::Item> {
282 if self.0.is_empty() {
283 None
284 } else {
285 let bit = self.0.trailing_zeros();
286 self.0.remove_bit(bit);
287 Some(bit)
288 }
289 }
290
291 fn size_hint(&self) -> (usize, Option<usize>) {
292 let left = self.0.count_ones() as usize;
293 (left, Some(left))
294 }
295}
296
297impl<T: EnumSetTypeRepr + Primitive> DoubleEndedIterator for PrimitiveIter<T> {
298 fn next_back(&mut self) -> Option<Self::Item> {
299 if self.0.is_empty() {
300 None
301 } else {
302 let bit = T::WIDTH - 1 - self.0.leading_zeros();
303 self.0.remove_bit(bit);
304 Some(bit)
305 }
306 }
307}
308
309impl<T: EnumSetTypeRepr + Primitive> ExactSizeIterator for PrimitiveIter<T> {}