bit_collection/lib.rs
1//! Iterate over a collection of bits.
2//!
3//! # Usage
4//!
5//! This crate is available [on crates.io][crate] and can be used by adding the
6//! following to your project's `Cargo.toml`:
7//!
8//! ```toml
9//! [dependencies]
10//! bit_collection = "0.2.3"
11//! ```
12//!
13//! and this to your crate root:
14//!
15//! ```
16//! #[macro_use]
17//! extern crate bit_collection;
18//! # fn main() {}
19//! ```
20//!
21//! # `#[bit]` Attribute
22//!
23//! The `#[bit]` attribute is composed of three parts, two of which are optional
24//! in some cases. The components can be provided in any order.
25//!
26//! ## Type:
27//!
28//! The type used to represent individual bits. This part is required.
29//!
30//! ```rust,ignore
31//! #[bit(Type, ...)]
32//! ```
33//!
34//! ## Mask:
35//! A mask indicating the valid bits of the collection. This should be a
36//! constant expression.
37//!
38//! If not provided, the mask is assumed to have all bits set (i.e. `!0`).
39//!
40//! [`BitCollection::FULL`][FULL] returns this value.
41//!
42//! **Attention:** Please read the section on [safety](#safety) to ensure
43//! that this is used in a _correct_ and _safe_ manner.
44//!
45//! ```rust,ignore
46//! #[bit(..., mask = "0b11", ...)]
47//! ```
48//!
49//! ## Retriever:
50//! The suffix for retrieving the inner integer value of the bit type. It
51//! expands to `$value.$retr`. Because of this, the provided retriever must be
52//! visible where the derive is located.
53//!
54//! If not provided, the bit type is assumed to be an `enum` that can be
55//! casted to an integer.
56//!
57//! ```rust,ignore
58//! #[bit(..., retr = "inner", ...)]
59//! ```
60//!
61//! ## Iterator:
62//! The iterator for a given [`BitCollection`]. If [`BitIter`] isn't imported
63//! as-is, this option allows for specifying its module path.
64//!
65//! ```rust,ignore
66//! extern crate bit_collection as bc;
67//!
68//! #[bit(..., iter = "bc::BitIter", ...)]
69//! ```
70//!
71//! # Examples
72//!
73//! In computer chess, one popular way of representing the occupants of a board
74//! is through a [`Bitboard`][bitboard] type. In this type, each individual bit
75//! is a square on a chess board.
76//!
77//! ```
78//! # include!("../templates/imports.rs");
79//! #[derive(Copy, Clone)]
80//! pub struct Square(u8);
81//!
82//! /// A set of sixty-four `Square`s.
83//! #[bit(Square, mask = "!0", retr = "0")]
84//! #[derive(BitCollection)]
85//! pub struct Bitboard(u64);
86//!
87//! # fn main() {}
88//! ```
89//!
90//! We can also represent castle rights this way.
91//!
92//! ```
93//! # include!("../templates/imports.rs");
94//! #[derive(Copy, Clone)]
95//! pub enum CastleRight {
96//! WhiteKingside,
97//! BlackKingside,
98//! WhiteQueenside,
99//! BlackQueenside,
100//! }
101//!
102//! /// A set of `CastleRight`s.
103//! #[bit(CastleRight, mask = "0b1111")]
104//! #[derive(BitCollection)]
105//! pub struct CastleRights {
106//! bits: u8
107//! }
108//!
109//! fn iterate_over(rights: CastleRights) {
110//! for right in rights {
111//! match right {
112//! CastleRight::WhiteKingside => { /* ... */ },
113//! CastleRight::BlackKingside => { /* ... */ },
114//! CastleRight::WhiteQueenside => { /* ... */ },
115//! CastleRight::BlackQueenside => { /* ... */ },
116//! }
117//! }
118//! }
119//!
120//! # fn main() {}
121//! ```
122//!
123//! # Safety
124//! This crate makes certain assumptions that, if unmet, may have unsafe and
125//! unexpected results.
126//!
127//! The [`mask`](#mask) option for [`#[bit]`](#bit-attribute) _must_ have the
128//! correct bits set. It _must not_ have bits set that correspond to invalid
129//! instances of the bit type.
130//!
131//! Similarly, the bit type must be defined such that corresponding bit patterns
132//! from `mask` provide legitimate values. Ask yourself, do `1 << item` and its
133//! reversal (undo) operations, `pop_{lsb,msb}`, make sense in terms of the
134//! provided mask?
135//!
136//! [crate]: https://crates.io/crates/bit_collection
137//! [`BitCollection`]: trait.BitCollection.html
138//! [`BitIter`]: struct.BitIter.html
139//! [FULL]: trait.BitCollection.html#associatedconstant.FULL
140//! [bitboard]: https://chessprogramming.wikispaces.com/Bitboards
141
142#![cfg_attr(not(feature = "std"), no_std)]
143
144#[cfg(feature = "std")]
145extern crate core;
146
147use core::borrow::{Borrow, BorrowMut};
148use core::cmp::Ordering;
149use core::iter::FromIterator;
150use core::ops;
151
152// Reexport derive macro.
153#[allow(unused_imports)]
154#[macro_use]
155extern crate bit_collection_derive;
156#[doc(hidden)]
157pub use bit_collection_derive::*;
158
159/// A type that represents a collection of bits that can be iterated over.
160pub trait BitCollection: From<<Self as IntoIterator>::Item>
161 + From<BitIter<Self>>
162 + IntoIterator<IntoIter=BitIter<Self>>
163 + FromIterator<<Self as IntoIterator>::Item>
164 + Extend<<Self as IntoIterator>::Item>
165 + ops::Not<Output=Self>
166 + ops::BitAnd<Output=Self>
167 + ops::BitAndAssign
168 + ops::BitOr<Output=Self>
169 + ops::BitOrAssign
170 + ops::BitXor<Output=Self>
171 + ops::BitXorAssign
172 + ops::Sub<Output=Self>
173 + ops::SubAssign
174{
175 /// A full instance with all bits set.
176 const FULL: Self;
177
178 /// An empty instance with no bits set.
179 const EMPTY: Self;
180
181 /// Returns the number of bits set in `self`.
182 ///
183 /// If checking whether `self` has zero, one, or multiple bits set, use
184 /// [`quantity`](#method.quantity).
185 fn len(&self) -> usize;
186
187 /// Returns whether `self` is empty.
188 fn is_empty(&self) -> bool;
189
190 /// Returns whether `self` has multiple bits set.
191 fn has_multiple(&self) -> bool;
192
193 /// Returns the quantity of bits set.
194 ///
195 /// For an exact measurement of the number of bits set, use
196 /// [`len`](#tymethod.len).
197 ///
198 /// This is much more optimal than matching [`len`](#tymethod.len) against
199 /// `0`, `1`, and `_`.
200 #[inline]
201 fn quantity(&self) -> Quantity {
202 use self::Quantity::*;
203 if self.is_empty() {
204 None
205 } else if self.has_multiple() {
206 Multiple
207 } else {
208 Single
209 }
210 }
211
212 /// Returns `self` as an iterator over itself.
213 ///
214 /// # Examples
215 ///
216 /// This method is useful for partially iterating over a `BitCollection`
217 /// in-place, and thus mutating it.
218 ///
219 /// ```
220 /// # include!("../templates/imports.rs");
221 /// # include!("../templates/castle_rights.rs");
222 /// # fn main() {
223 /// let mut rights = CastleRights::FULL;
224 /// assert_eq!(rights.len(), 4);
225 ///
226 /// for right in rights.as_iter().take(3) { /* ... */ }
227 /// assert_eq!(rights.len(), 1);
228 /// # }
229 /// ```
230 #[inline]
231 fn as_iter(&mut self) -> &mut BitIter<Self> {
232 unsafe { &mut *(self as *mut _ as *mut _) }
233 }
234
235 /// Converts `self` into the only bit set.
236 #[inline]
237 fn into_bit(mut self) -> Option<Self::Item> {
238 let bit = self.pop_lsb();
239 if self.is_empty() { bit } else { None }
240 }
241
242 /// Returns the least significant bit in `self` if `self` is not empty.
243 #[inline]
244 fn lsb(&self) -> Option<Self::Item> {
245 if self.is_empty() { None } else {
246 unsafe { Some(self.lsb_unchecked()) }
247 }
248 }
249
250 /// Returns the most significant bit in `self` if `self` is not empty.
251 #[inline]
252 fn msb(&self) -> Option<Self::Item> {
253 if self.is_empty() { None } else {
254 unsafe { Some(self.msb_unchecked()) }
255 }
256 }
257
258 /// Returns the least significant bit in `self` without checking whether
259 /// `self` is empty.
260 unsafe fn lsb_unchecked(&self) -> Self::Item;
261
262 /// Returns the most significant bit in `self` without checking whether
263 /// `self` is empty.
264 unsafe fn msb_unchecked(&self) -> Self::Item;
265
266 /// Removes the least significant bit from `self`.
267 fn remove_lsb(&mut self);
268
269 /// Removes the most significant bit from `self`.
270 fn remove_msb(&mut self);
271
272 /// Removes the least significant bit from `self` and returns it.
273 fn pop_lsb(&mut self) -> Option<Self::Item>;
274
275 /// Removes the most significant bit from `self` and returns it.
276 fn pop_msb(&mut self) -> Option<Self::Item>;
277
278 /// Returns whether `self` contains the value.
279 fn contains<T: Into<Self>>(&self, T) -> bool;
280
281 /// Returns the result of removing the value from `self`.
282 #[inline]
283 fn removing<T: Into<Self>>(self, other: T) -> Self {
284 self - other.into()
285 }
286
287 /// Returns the result of inserting the value into `self`.
288 #[inline]
289 fn inserting<T: Into<Self>>(self, other: T) -> Self {
290 self | other.into()
291 }
292
293 /// Returns the result of toggling the bits of the value in `self`.
294 #[inline]
295 fn toggling<T: Into<Self>>(self, other: T) -> Self {
296 self ^ other.into()
297 }
298
299 /// Returns the result of intersecting the bits of the value with `self`.
300 #[inline]
301 fn intersecting<T: Into<Self>>(self, other: T) -> Self {
302 self & other.into()
303 }
304
305 /// Returns the result of setting the bits of the value in `self` based on
306 /// `condition`.
307 #[inline]
308 fn setting<T: Into<Self>>(self, other: T, condition: bool) -> Self {
309 if condition {
310 self.inserting(other)
311 } else {
312 self.removing(other)
313 }
314 }
315
316 /// Removes the value from `self`.
317 #[inline]
318 fn remove<T: Into<Self>>(&mut self, other: T) -> &mut Self {
319 *self -= other.into();
320 self
321 }
322
323 /// Inserts the value into `self`.
324 #[inline]
325 fn insert<T: Into<Self>>(&mut self, other: T) -> &mut Self {
326 *self |= other.into();
327 self
328 }
329
330 /// Toggles bits of the value in `self`.
331 #[inline]
332 fn toggle<T: Into<Self>>(&mut self, other: T) -> &mut Self {
333 *self ^= other.into();
334 self
335 }
336
337 /// Intersects the bits of the value with `self`.
338 #[inline]
339 fn intersect<T: Into<Self>>(&mut self, other: T) -> &mut Self {
340 *self &= other.into();
341 self
342 }
343
344 /// Sets the bits of the value in `self` based on `condition`.
345 #[inline]
346 fn set<T: Into<Self>>(&mut self, other: T, condition: bool) -> &mut Self {
347 if condition {
348 self.insert(other)
349 } else {
350 self.remove(other)
351 }
352 }
353}
354
355/// An iterator over the bits of a [`BitCollection`](trait.BitCollection.html).
356#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
357pub struct BitIter<C: BitCollection>(pub C);
358
359impl<C: BitCollection> From<C> for BitIter<C> {
360 #[inline(always)]
361 fn from(bits: C) -> Self { BitIter(bits) }
362}
363
364impl<C: BitCollection> AsRef<C> for BitIter<C> {
365 #[inline(always)]
366 fn as_ref(&self) -> &C { &self.0 }
367}
368
369impl<C: BitCollection> AsMut<C> for BitIter<C> {
370 #[inline(always)]
371 fn as_mut(&mut self) -> &mut C { &mut self.0 }
372}
373
374impl<C: BitCollection> Borrow<C> for BitIter<C> {
375 #[inline(always)]
376 fn borrow(&self) -> &C { self.as_ref() }
377}
378
379impl<C: BitCollection> BorrowMut<C> for BitIter<C> {
380 #[inline(always)]
381 fn borrow_mut(&mut self) -> &mut C { self.as_mut() }
382}
383
384impl<C: BitCollection> Iterator for BitIter<C> {
385 type Item = C::Item;
386
387 #[inline]
388 fn next(&mut self) -> Option<Self::Item> {
389 self.0.pop_lsb()
390 }
391
392 #[inline]
393 fn size_hint(&self) -> (usize, Option<usize>) {
394 let len = self.len();
395 (len, Some(len))
396 }
397
398 #[inline]
399 fn count(self) -> usize {
400 self.len()
401 }
402
403 #[inline]
404 fn last(self) -> Option<Self::Item> {
405 self.0.msb()
406 }
407}
408
409impl<C: BitCollection> DoubleEndedIterator for BitIter<C> {
410 #[inline]
411 fn next_back(&mut self) -> Option<Self::Item> {
412 self.0.pop_msb()
413 }
414}
415
416impl<C: BitCollection> ExactSizeIterator for BitIter<C> {
417 #[inline]
418 fn len(&self) -> usize {
419 self.0.len()
420 }
421}
422
423/// How many bits are set in a [`BitCollection`](trait.BitCollection.html) as
424/// returned by [`quantity`](trait.BitCollection.html#method.quantity).
425#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
426pub enum Quantity {
427 // NOTE: The variant order is optimized for the quantity method
428 /// Multiple bits set.
429 Multiple,
430 /// Single bit set.
431 Single,
432 /// No bits set.
433 None,
434}
435
436impl PartialOrd for Quantity {
437 #[inline]
438 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
439 Some(self.cmp(other))
440 }
441
442 #[inline]
443 fn lt(&self, other: &Self) -> bool { (*self as usize) > (*other as usize) }
444
445 #[inline]
446 fn gt(&self, other: &Self) -> bool { (*self as usize) < (*other as usize) }
447
448 #[inline]
449 fn le(&self, other: &Self) -> bool { (*self as usize) >= (*other as usize) }
450
451 #[inline]
452 fn ge(&self, other: &Self) -> bool { (*self as usize) <= (*other as usize) }
453}
454
455impl Ord for Quantity {
456 #[inline]
457 fn cmp(&self, other: &Self) -> Ordering {
458 use Ordering::*;
459 match (*self as usize).cmp(&(*other as usize)) {
460 Equal => Equal,
461 Greater => Less,
462 Less => Greater,
463 }
464 }
465}