#bits #collection #iterating #individual #iterate #iterator

no-std bit_collection

A trait for iterating over the individual bits of a collection

6 releases

Uses old Rust 2015

0.2.3 Sep 5, 2017
0.2.2 Aug 25, 2017
0.1.1 Aug 8, 2017

#359 in No standard library

38 downloads per month
Used in zdex

MIT/Apache

17KB
251 lines

bit_collection

A Rust library that allows for iterating over the bits of a collection.

Build Status

Documentation

License

This project is released under either:

at your choosing.


lib.rs:

Iterate over a collection of bits.

Usage

This crate is available on crates.io and can be used by adding the following to your project's Cargo.toml:

[dependencies]
bit_collection = "0.2.3"

and this to your crate root:

#[macro_use]
extern crate bit_collection;

#[bit] Attribute

The #[bit] attribute is composed of three parts, two of which are optional in some cases. The components can be provided in any order.

Type:

The type used to represent individual bits. This part is required.

#[bit(Type, ...)]

Mask:

A mask indicating the valid bits of the collection. This should be a constant expression.

If not provided, the mask is assumed to have all bits set (i.e. !0).

BitCollection::FULL returns this value.

Attention: Please read the section on safety to ensure that this is used in a correct and safe manner.

#[bit(..., mask = "0b11", ...)]

Retriever:

The suffix for retrieving the inner integer value of the bit type. It expands to $value.$retr. Because of this, the provided retriever must be visible where the derive is located.

If not provided, the bit type is assumed to be an enum that can be casted to an integer.

#[bit(..., retr = "inner", ...)]

Iterator:

The iterator for a given BitCollection. If BitIter isn't imported as-is, this option allows for specifying its module path.

extern crate bit_collection as bc;

#[bit(..., iter = "bc::BitIter", ...)]

Examples

In computer chess, one popular way of representing the occupants of a board is through a Bitboard type. In this type, each individual bit is a square on a chess board.

#[derive(Copy, Clone)]
pub struct Square(u8);

/// A set of sixty-four `Square`s.
#[bit(Square, mask = "!0", retr = "0")]
#[derive(BitCollection)]
pub struct Bitboard(u64);

We can also represent castle rights this way.

#[derive(Copy, Clone)]
pub enum CastleRight {
    WhiteKingside,
    BlackKingside,
    WhiteQueenside,
    BlackQueenside,
}

/// A set of `CastleRight`s.
#[bit(CastleRight, mask = "0b1111")]
#[derive(BitCollection)]
pub struct CastleRights {
    bits: u8
}

fn iterate_over(rights: CastleRights) {
    for right in rights {
        match right {
            CastleRight::WhiteKingside  => { /* ... */ },
            CastleRight::BlackKingside  => { /* ... */ },
            CastleRight::WhiteQueenside => { /* ... */ },
            CastleRight::BlackQueenside => { /* ... */ },
        }
    }
}

Safety

This crate makes certain assumptions that, if unmet, may have unsafe and unexpected results.

The mask option for #[bit] must have the correct bits set. It must not have bits set that correspond to invalid instances of the bit type.

Similarly, the bit type must be defined such that corresponding bit patterns from mask provide legitimate values. Ask yourself, do 1 << item and its reversal (undo) operations, pop_{lsb,msb}, make sense in terms of the provided mask?

Dependencies

~1.5MB
~40K SLoC