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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
#![no_std]
//! Aint is a crate implementing integers of non-standard bit widths between
//! 1 and 127. These integer types are represented by the next largest built-in
//! Rust integer, but are bounded to the range and behaviors of the advertised
//! bit width. That is, `T::MIN` and `T::MAX`, are what would be expected for
//! the integer `T` with `N` bits, and similarly, wrapping, saturating, and
//! overflow behaviors match what would be expected for a hypothetical built-in
//! integer `T` with `N` bits.
//!
//! # Example
//! ```
//! # use aint::*;
//! fn add(a: i13, b: i13) -> i13 {
//! a + b
//! }
//!
//! let x = i13!(100);
//! let y = add(x, i13!(-42));
//! assert_eq!(y, i13!(58));
//! ```
//!
//! The core implementation type is [`Aint<R, const WIDTH: u32>`](Aint), which
//! accepts a representation type, `R`, and a bit width, `WIDTH`. [`Aint`] is
//! intended to primarily be an implementation detail, not to be used directly.
//! Instead, it is preferred to use the type aliases provided by this crate.
//!
//! If [`Aint`] is used directly, it will only permit generic parameters that
//! match one of the existing type aliases provided by this crate. For example,
//! the type [`i24`](type@i24) is an alias of `Aint<i32, 24>`. In theory,
//! `Aint<i64, 24>` would be equivalent in functionality, but will result in a
//! compile time error if instantiated. This prevents the existence multiple
//! [`Aint`]s that are functionally the same but are incompatible types to the
//! compiler.
//!
//! # Byte Wide Types
//! Integer types that have an exact byte width provide additional methods and
//! functionality that other integer types do not. These are types whose width
//! is a multiple of 8, such as [`i24`](type@i24) (3 bytes), [`u56`](type@u56)
//! (7 bytes), and [`u120`](type@u120) (15 bytes). Such types provide the byte
//! and endianness manipulation APIs that built-in Rust integers provide, such
//! as `T::from_be_bytes`, `T::swap_bytes`, and `T::to_le`. Other integer types
//! do not implement these methods since their meaning becomes ambiguous or
//! perhaps even nonsensical.
//!
//! # Conversions
//! All integer types provided by this crate implement traits to convert to and
//! from all built-in Rust integer types. A conversion will be implemented as
//! [`From`] when the conversion is infallible, and [`TryFrom`] when the
//! conversion can fail. For example, converting from [`i4`](type@i4) to
//! [`i8`](prim@i8) is implemented as `impl From<i4> for i8`, but the reverse
//! conversion is implemented as `impl TryFrom<i8> for i4`.
//!
//! Unfortunately, this crate does not provide the same conversions between
//! each of the pairs of types provided, such as [`i4`](type@i4) to
//! [`i13`](type@i13). Existing blanket implmentations on the standard conversion
//! traits prevent a generic implementation of these traits that would cover all
//! the types provided by this crate, and implementing conversions for each pair
//! of types individually is infeasible due to extreme compiliation times, since
//! each pair would result on the order of 128<sup>2</sup> trait implementations.
//!
//! This crate also provides two alternate conversion traits that perform
//! infallible, but potentially lossy, conversions:
//! [`WrappingFrom`]/[`WrappingInto`] and [`SaturatingFrom`]/[`SaturatingInto`].
//! These are implemented for all combinations of built-in integers and integers
//! provided by this crate. See each trait's documentation for more details.
//!
//! # Concatenation and Splitting
//! This crate also provides two traits for concatenating and spliting integers
//! bitwise: [`BitConcat`] and [`BitSplit`]. Any pair of two integer types can
//! be concatenated as long as their combined bit width is at most 128, and
//! any integer can be split bitwise into any two integers whose combined bit
//! width equals the bit width of the original integer.
//!
//! ```
//! # use aint::*;
//! let x: u16 = 0b0101010100101_101;
//! let (x1, x2): (i13, u3) = x.bit_split();
//! let y = u16::bit_concat(x1, x2);
//!
//! assert_eq!(x, y);
//! assert_eq!(x1, i13!(0b0101010100101));
//! assert_eq!(x2, u3!(0b101));
//! ```
//!
//! # Macros
//! Each integer type provided by this crate comes with macro for constructing
//! these types from literals. Built-in integers can have typed literals, such
//! as `42u8` or `-7i64`. The macros provided by this crate perform a similar
//! function. `u13!(100)` is essentially a [`u13`](type@u13) literal with the
//! value `100`. The values provided to these macros are also checked at compile
//! time to ensure that they are valid for the type. For example, `u4!(100)`,
//! would result in a compile time error, because [`u4`](type@u4) can only
//! represent values from `0` to `15`, inclusive.
//!
//! # Features
//! This crate has two non-default features, `serde` and `num`, which enable
//! compaitbility with the `serde` and `num` crates.
//!
//! Enabling the `serde` feature will provide implementations of
//! [`serde::Serialize`](::serde::Serialize) and
//! [`serde::Deserialize`](::serde::Deserialize) for each integer type in
//! this crate.
//!
//! Enabling the `num` feature will provide implementations of all appropriate
//! traits from the [`num_traits`] and [`num_integer`] crates under the `num`
//! family of crates.
//!
//! ```toml
//! [dependencies]
//! aint = { version = "0.1", features = [ "serde", "num" ] }
//! ```
//!
//! # `no_std`
//! This crate is also `#![no_std]`. Unlike some other crates, this crate does
//! not have a `std` (or `no_std`) feature - it simply never uses or needs
//! `libstd`. Additionally, this crate does not use `alloc` either. `libcore`
//! is the only required dependency, and the crates pulled in by the `serde`
//! and `num` features are also `no_std` compatible.
mod aint;
mod bit_concat;
mod bit_split;
mod convs;
pub(crate) mod int;
mod macros;
mod misc;
pub(crate) mod non_prim;
#[cfg(feature = "num")]
mod num;
mod ops;
pub(crate) mod prim;
mod saturating;
pub(crate) mod sealed;
#[cfg(feature = "serde")]
mod serde;
mod shifts;
#[cfg(test)]
mod test;
pub(crate) mod tybit;
mod typedefs;
pub(crate) mod width;
mod wrapping;
pub use aint::*;
pub use bit_concat::*;
pub use bit_split::*;
pub use saturating::*;
pub use typedefs::*;
pub use wrapping::*;