quark/
lib.rs

1#![deny(missing_docs)]
2
3//! Types for manipulating numeric primitives at the bit level.
4//!
5//! The `quark` crate provides traits for accessing parts of numeric primitives and adds new types
6//! to represent numbers using bit counts that aren't included in the standard library.
7//!
8//! # Bit Indexing
9//!
10//! Accessing a bit or range of bits in a numeric primitive can be awkward and less than readable
11//! using shifts and masks:
12//!
13//! ```
14//! # let big: u16 = 0x35;
15//! let small = big >> 2 & 0x1f;
16//! # assert_eq!(small, 0xd);
17//! ```
18//!
19//! At a glance, it's not easy to parse things like:
20//!
21//!  - How many bits are contributing to the resulting value and which ones are definitely zero?
22//!  - Which bits in the original value are in the result?
23//!
24//! Using the `BitIndex` trait, the above example can be written as:
25//!
26//! ```
27//! # use quark::BitIndex;
28//! # let big: u16 = 0x35;
29//! let small = big.bits(2..7);
30//! # assert_eq!(small, 0xd);
31//! ```
32//!
33//! # Bit Masks
34//!
35//! The `BitMask` trait allows for easily generating a bit mask using just the length and apply
36//! masks:
37//!
38//! ```
39//! # use quark::BitMask;
40//! let mask = u32::mask(8);
41//! assert_eq!(mask, 0xff);
42//!
43//! let value: u32 = 0x1234_5678;
44//! assert_eq!(value.mask_to(16), 0x5678);
45//! ```
46//!
47//! # Bit Sizes
48//!
49//! When implementing a trait on numeric types, sometimes the number of bits of a type will be
50//! required. One way around this is adding a `bit_size()` or `bit_length()` method to the trait in
51//! order to return a constant for each type. The `BitSize` trait adds a `BIT_SIZE` constant to the
52//! numeric types that can be used in implementing traits without needing another method.
53//!
54//! # Sign Extension
55//!
56//! 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:
57//!
58//! ```
59//! # use quark::Signs;
60//! # let unsigned = 0x00ff_ffffu32;
61//! let signed = unsigned.sign_extend(8);
62//! # assert_eq!(signed, 0xffff_ffff);
63//! ```
64//!
65//! # Why `quark`?
66//!
67//! Because our programs are primitives at the very lowest level, types like `i32`, `u8`, and
68//! `usize` are like atomic pieces of data. The `quark` crate goes to the next level down, and
69//! quarks are at that next level w.r.t. atoms.
70//!
71//! Also, I have an affinity for names with a 'Q' because my last name starts with one.
72
73mod bit_index;
74mod bit_mask;
75mod bit_size;
76mod signs;
77
78pub use self::bit_index::*;
79pub use self::bit_mask::*;
80pub use self::bit_size::*;
81pub use self::signs::*;