1#![cfg_attr(not(test), no_std)]
2#![doc = include_str!("../README.md")]
3
4use core::{
5 hash::{Hash, Hasher},
6 ops::*,
7};
8
9use bitmaps::{BitOps, Bitmap, Bits, BitsImpl};
10
11#[derive(Clone, Copy, Default, Eq, PartialEq)]
20pub struct CpuMask<const SIZE: usize>
21where
22 BitsImpl<{ SIZE }>: Bits,
23{
24 value: Bitmap<{ SIZE }>,
25}
26
27impl<const SIZE: usize> core::fmt::Debug for CpuMask<{ SIZE }>
28where
29 BitsImpl<{ SIZE }>: Bits,
30{
31 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32 write!(f, "cpumask: [")?;
33 for cpu in self.into_iter() {
34 write!(f, "{}, ", cpu)?;
35 }
36 write!(f, "]")
37 }
38}
39
40impl<const SIZE: usize> Hash for CpuMask<{ SIZE }>
41where
42 BitsImpl<{ SIZE }>: Bits,
43 <BitsImpl<{ SIZE }> as Bits>::Store: Hash,
44{
45 fn hash<H: Hasher>(&self, state: &mut H) {
46 self.value.as_value().hash(state)
47 }
48}
49
50impl<const SIZE: usize> PartialOrd for CpuMask<{ SIZE }>
51where
52 BitsImpl<{ SIZE }>: Bits,
53 <BitsImpl<{ SIZE }> as Bits>::Store: PartialOrd,
54{
55 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
56 self.value.as_value().partial_cmp(other.value.as_value())
57 }
58}
59
60impl<const SIZE: usize> Ord for CpuMask<{ SIZE }>
61where
62 BitsImpl<{ SIZE }>: Bits,
63 <BitsImpl<{ SIZE }> as Bits>::Store: Ord,
64{
65 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
66 self.value.as_value().cmp(other.value.as_value())
67 }
68}
69
70impl<const SIZE: usize> CpuMask<{ SIZE }>
71where
72 BitsImpl<SIZE>: Bits,
73{
74 #[inline]
76 pub fn new() -> Self {
77 Self::default()
78 }
79
80 #[inline]
82 pub fn full() -> Self {
83 Self {
84 value: Bitmap::mask(SIZE),
85 }
86 }
87
88 #[inline]
91 pub fn mask(bits: usize) -> Self {
92 debug_assert!(bits <= SIZE);
93 Self {
94 value: Bitmap::mask(bits),
95 }
96 }
97
98 #[inline]
100 pub fn from_value(data: <BitsImpl<SIZE> as Bits>::Store) -> Self {
101 Self {
102 value: Bitmap::from_value(data),
103 }
104 }
105
106 pub fn from_raw_bits(value: usize) -> Self {
109 assert!(value >> SIZE == 0);
110
111 let mut bit_map = Bitmap::new();
112 let mut i = 0;
113 while i < SIZE {
114 if value & (1 << i) != 0 {
115 bit_map.set(i, true);
116 }
117 i += 1;
118 }
119
120 Self { value: bit_map }
121 }
122
123 pub fn one_shot(index: usize) -> Self {
126 assert!(index < SIZE);
127 let mut bit_map = Bitmap::new();
128 bit_map.set(index, true);
129 Self { value: bit_map }
130 }
131
132 #[inline]
134 pub fn into_value(self) -> <BitsImpl<SIZE> as Bits>::Store {
135 self.value.into_value()
136 }
137
138 #[inline]
140 pub fn as_value(&self) -> &<BitsImpl<SIZE> as Bits>::Store {
141 self.value.as_value()
142 }
143
144 #[inline]
146 pub fn as_bytes(&self) -> &[u8] {
147 self.value.as_bytes()
148 }
149
150 #[inline]
152 pub fn len(self) -> usize {
153 self.value.len()
154 }
155
156 #[inline]
158 pub fn is_empty(self) -> bool {
159 self.first_index().is_none()
160 }
161
162 #[inline]
164 pub fn is_full(self) -> bool {
165 self.first_false_index().is_none()
166 }
167
168 #[inline]
170 pub fn get(self, index: usize) -> bool {
171 debug_assert!(index < SIZE);
172 <BitsImpl<SIZE> as Bits>::Store::get(&self.into_value(), index)
173 }
174
175 #[inline]
179 pub fn set(&mut self, index: usize, value: bool) -> bool {
180 debug_assert!(index < SIZE);
181 self.value.set(index, value)
182 }
183
184 #[inline]
186 pub fn first_index(self) -> Option<usize> {
187 <BitsImpl<SIZE> as Bits>::Store::first_index(&self.into_value())
188 }
189
190 #[inline]
192 pub fn last_index(self) -> Option<usize> {
193 <BitsImpl<SIZE> as Bits>::Store::last_index(&self.into_value())
194 }
195
196 #[inline]
198 pub fn next_index(self, index: usize) -> Option<usize> {
199 <BitsImpl<SIZE> as Bits>::Store::next_index(&self.into_value(), index)
200 }
201
202 #[inline]
204 pub fn prev_index(self, index: usize) -> Option<usize> {
205 <BitsImpl<SIZE> as Bits>::Store::prev_index(&self.into_value(), index)
206 }
207
208 #[inline]
210 pub fn first_false_index(self) -> Option<usize> {
211 <BitsImpl<SIZE> as Bits>::corrected_first_false_index(&self.into_value())
212 }
213
214 #[inline]
216 pub fn last_false_index(self) -> Option<usize> {
217 <BitsImpl<SIZE> as Bits>::corrected_last_false_index(&self.into_value())
218 }
219
220 #[inline]
222 pub fn next_false_index(self, index: usize) -> Option<usize> {
223 <BitsImpl<SIZE> as Bits>::corrected_next_false_index(&self.into_value(), index)
224 }
225
226 #[inline]
228 pub fn prev_false_index(self, index: usize) -> Option<usize> {
229 <BitsImpl<SIZE> as Bits>::Store::prev_false_index(&self.into_value(), index)
230 }
231
232 #[inline]
234 pub fn invert(&mut self) {
235 self.value.invert();
236 }
237}
238
239impl<'a, const SIZE: usize> IntoIterator for &'a CpuMask<{ SIZE }>
240where
241 BitsImpl<{ SIZE }>: Bits,
242{
243 type Item = usize;
244 type IntoIter = Iter<'a, { SIZE }>;
245
246 fn into_iter(self) -> Self::IntoIter {
247 Iter {
248 head: None,
249 tail: Some(SIZE + 1),
250 data: self,
251 }
252 }
253}
254
255impl<const SIZE: usize> BitAnd for CpuMask<{ SIZE }>
256where
257 BitsImpl<{ SIZE }>: Bits,
258{
259 type Output = Self;
260 fn bitand(self, rhs: Self) -> Self::Output {
261 Self {
262 value: self.value.bitand(rhs.value),
263 }
264 }
265}
266
267impl<const SIZE: usize> BitOr for CpuMask<{ SIZE }>
268where
269 BitsImpl<{ SIZE }>: Bits,
270{
271 type Output = Self;
272 fn bitor(self, rhs: Self) -> Self::Output {
273 Self {
274 value: self.value.bitor(rhs.value),
275 }
276 }
277}
278
279impl<const SIZE: usize> BitXor for CpuMask<{ SIZE }>
280where
281 BitsImpl<{ SIZE }>: Bits,
282{
283 type Output = Self;
284 fn bitxor(self, rhs: Self) -> Self::Output {
285 Self {
286 value: self.value.bitxor(rhs.value),
287 }
288 }
289}
290
291impl<const SIZE: usize> Not for CpuMask<{ SIZE }>
292where
293 BitsImpl<{ SIZE }>: Bits,
294{
295 type Output = Self;
296 fn not(self) -> Self::Output {
297 Self {
298 value: self.value.not(),
299 }
300 }
301}
302
303impl<const SIZE: usize> BitAndAssign for CpuMask<{ SIZE }>
304where
305 BitsImpl<{ SIZE }>: Bits,
306{
307 fn bitand_assign(&mut self, rhs: Self) {
308 self.value.bitand_assign(rhs.value)
309 }
310}
311
312impl<const SIZE: usize> BitOrAssign for CpuMask<{ SIZE }>
313where
314 BitsImpl<{ SIZE }>: Bits,
315{
316 fn bitor_assign(&mut self, rhs: Self) {
317 self.value.bitor_assign(rhs.value)
318 }
319}
320
321impl<const SIZE: usize> BitXorAssign for CpuMask<{ SIZE }>
322where
323 BitsImpl<{ SIZE }>: Bits,
324{
325 fn bitxor_assign(&mut self, rhs: Self) {
326 self.value.bitxor_assign(rhs.value)
327 }
328}
329
330impl From<[u128; 2]> for CpuMask<256> {
331 fn from(data: [u128; 2]) -> Self {
332 CpuMask { value: data.into() }
333 }
334}
335
336impl From<[u128; 3]> for CpuMask<384> {
337 fn from(data: [u128; 3]) -> Self {
338 CpuMask { value: data.into() }
339 }
340}
341
342impl From<[u128; 4]> for CpuMask<512> {
343 fn from(data: [u128; 4]) -> Self {
344 CpuMask { value: data.into() }
345 }
346}
347
348impl From<[u128; 5]> for CpuMask<640> {
349 fn from(data: [u128; 5]) -> Self {
350 CpuMask { value: data.into() }
351 }
352}
353
354impl From<[u128; 6]> for CpuMask<768> {
355 fn from(data: [u128; 6]) -> Self {
356 CpuMask { value: data.into() }
357 }
358}
359
360impl From<[u128; 7]> for CpuMask<896> {
361 fn from(data: [u128; 7]) -> Self {
362 CpuMask { value: data.into() }
363 }
364}
365
366impl From<[u128; 8]> for CpuMask<1024> {
367 fn from(data: [u128; 8]) -> Self {
368 CpuMask { value: data.into() }
369 }
370}
371
372impl From<CpuMask<256>> for [u128; 2] {
373 fn from(cpumask: CpuMask<256>) -> Self {
374 cpumask.into_value()
375 }
376}
377
378impl From<CpuMask<384>> for [u128; 3] {
379 fn from(cpumask: CpuMask<384>) -> Self {
380 cpumask.into_value()
381 }
382}
383
384impl From<CpuMask<512>> for [u128; 4] {
385 fn from(cpumask: CpuMask<512>) -> Self {
386 cpumask.into_value()
387 }
388}
389
390impl From<CpuMask<640>> for [u128; 5] {
391 fn from(cpumask: CpuMask<640>) -> Self {
392 cpumask.into_value()
393 }
394}
395
396impl From<CpuMask<768>> for [u128; 6] {
397 fn from(cpumask: CpuMask<768>) -> Self {
398 cpumask.into_value()
399 }
400}
401
402impl From<CpuMask<896>> for [u128; 7] {
403 fn from(cpumask: CpuMask<896>) -> Self {
404 cpumask.into_value()
405 }
406}
407
408impl From<CpuMask<1024>> for [u128; 8] {
409 fn from(cpumask: CpuMask<1024>) -> Self {
410 cpumask.into_value()
411 }
412}
413
414#[derive(Clone, Debug)]
431pub struct Iter<'a, const SIZE: usize>
432where
433 BitsImpl<SIZE>: Bits,
434{
435 head: Option<usize>,
436 tail: Option<usize>,
437 data: &'a CpuMask<{ SIZE }>,
438}
439
440impl<'a, const SIZE: usize> Iterator for Iter<'a, SIZE>
441where
442 BitsImpl<{ SIZE }>: Bits,
443{
444 type Item = usize;
445
446 fn next(&mut self) -> Option<Self::Item> {
447 let result;
448
449 match self.head {
450 None => {
451 result = self.data.first_index();
452 }
453 Some(index) => {
454 if index >= SIZE {
455 result = None
456 } else {
457 result = self.data.next_index(index);
458 }
459 }
460 }
461
462 if let Some(index) = result {
463 if let Some(tail) = self.tail {
464 if tail < index {
465 self.head = Some(SIZE + 1);
466 self.tail = None;
467 return None;
468 }
469 } else {
470 self.head = Some(SIZE + 1);
472 return None;
473 }
474
475 self.head = Some(index);
476 } else {
477 self.head = Some(SIZE + 1);
478 }
479
480 result
481 }
482}
483
484impl<'a, const SIZE: usize> DoubleEndedIterator for Iter<'a, SIZE>
485where
486 BitsImpl<{ SIZE }>: Bits,
487{
488 fn next_back(&mut self) -> Option<Self::Item> {
489 let result;
490
491 match self.tail {
492 None => {
493 result = None;
494 }
495 Some(index) => {
496 if index >= SIZE {
497 result = self.data.last_index();
498 } else {
499 result = self.data.prev_index(index);
500 }
501 }
502 }
503
504 if let Some(index) = result {
505 if let Some(head) = self.head
506 && head > index
507 {
508 self.head = Some(SIZE + 1);
509 self.tail = None;
510 return None;
511 }
512
513 self.tail = Some(index);
514 } else {
515 self.tail = None;
516 }
517
518 result
519 }
520}