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
#![deny(missing_docs)]

//! Types for manipulating numeric primitives at the bit level.
//!
//! The `quark` crate provides traits for accessing parts of numeric primitives and adds new types
//! to represent numbers using bit counts that aren't included in the standard library.
//!
//! # Bit Indexing
//!
//! Accessing a bit or range of bits in a numeric primitive can be awkward and less than readable
//! using shifts and masks:
//!
//! ```
//! # let big: u16 = 0x35;
//! let small = big >> 2 & 0x1f;
//! # assert_eq!(small, 0xd);
//! ```
//!
//! At a glance, it's not easy to parse things like:
//!
//!  - How many bits are contributing to the resulting value and which ones are definitely zero?
//!  - Which bits in the original value are in the result?
//!
//! Using the `BitIndex` trait, the above example can be written as:
//!
//! ```
//! # use quark::BitIndex;
//! # let big: u16 = 0x35;
//! let small = big.bits(2..7);
//! # assert_eq!(small, 0xd);
//! ```
//!
//! # Bit Masks
//!
//! The `BitMask` trait allows for easily generating a bit mask using just the length and apply
//! masks:
//!
//! ```
//! # use quark::BitMask;
//! let mask = u32::mask(8);
//! assert_eq!(mask, 0xff);
//!
//! let value: u32 = 0x1234_5678;
//! assert_eq!(value.mask_to(16), 0x5678);
//! ```
//!
//! # Bit Sizes
//!
//! When implementing a trait on numeric types, sometimes the number of bits of a type will be
//! required. One way around this is adding a `bit_size()` or `bit_length()` method to the trait in
//! order to return a constant for each type. The `BitSize` trait adds a `BIT_SIZE` constant to the
//! numeric types that can be used in implementing traits without needing another method.
//!
//! # Sign Extension
//!
//! The `Signs` trait adds methods for checking the sign bit on unsigned primitives (and signed ones) and for sign-extending values an arbitrary number of bits:
//!
//! ```
//! # use quark::Signs;
//! # let unsigned = 0x00ff_ffffu32;
//! let signed = unsigned.sign_extend(8);
//! # assert_eq!(signed, 0xffff_ffff);
//! ```
//!
//! # Why `quark`?
//!
//! Because our programs are primitives at the very lowest level, types like `i32`, `u8`, and
//! `usize` are like atomic pieces of data. The `quark` crate goes to the next level down, and
//! quarks are at that next level w.r.t. atoms.
//!
//! Also, I have an affinity for names with a 'Q' because my last name starts with one.

mod bit_index;
mod bit_mask;
mod bit_size;
mod signs;

pub use self::bit_index::*;
pub use self::bit_mask::*;
pub use self::bit_size::*;
pub use self::signs::*;