nonany provides integer types with customizable niche values in stable rust. The main benefit of integer types with niches is that it enables the compiler to do memory layout optimization, such that an Option
of an integer is the same size as the integer itself:
assert_eq!(
core::mem::size_of::<Option<nonany::NonAnyU32<0xDEADBEEF>>>(),
core::mem::size_of::<nonany::NonAnyU32<0xDEADBEEF>>());
use nonany::NonAnyI8;
assert!(NonAnyI8::<20>::new(100).is_some(), "Values that aren't the niche can be stored");
assert!(NonAnyI8::<20>::new(20).is_none(), "The niche itself cannot be stored");
let foo = NonAnyI8::<20>::new(25).unwrap();
assert_eq!(foo.get(), 25, "The value can be loaded");
nonmax defines generic types with user defined niches for all integer types, as well as type aliases common use cases:
NonAny* |
NonMin* |
NonMax* |
NonZero* |
|
---|---|---|---|---|
i8 |
NonAnyI8 |
NonMinI8 |
NonMaxI8 |
NonZeroI8 |
i16 |
NonAnyI16 |
NonMinI16 |
NonMaxI16 |
NonZeroI16 |
i32 |
NonAnyI32 |
NonMinI32 |
NonMaxI32 |
NonZeroI32 |
i64 |
NonAnyI64 |
NonMinI64 |
NonMaxI64 |
NonZeroI64 |
i128 |
NonAnyI128 |
NonMinI128 |
NonMaxI128 |
NonZeroI128 |
isize |
NonAnyIsize |
NonMinIsize |
NonMaxIsize |
NonZeroIsize |
u8 |
NonAnyU8 |
NonMinU8 |
NonMaxU8 |
NonZeroU8 |
u16 |
NonAnyU16 |
NonMinU16 |
NonMaxU16 |
NonZeroU16 |
u32 |
NonAnyU32 |
NonMinU32 |
NonMaxU32 |
NonZeroU32 |
u64 |
NonAnyU64 |
NonMinU64 |
NonMaxU64 |
NonZeroU64 |
u128 |
NonAnyU128 |
NonMinU128 |
NonMaxU128 |
NonZeroU128 |
usize |
NonAnyUsize |
NonMinUsize |
NonMaxUsize |
NonZeroUsize |
Internally all NonAny*
types use the NonZero*
types from the standard library. When a value is stored in NonAny*
, the value is stored in the internal NonZero*
as an XOR of the value and the niche. Any value XORed with the niche that isn't the niche itself can never be zero, so this works out perfectly.
The upside of this technique is that it works on stable rust. The downside is that it requires an, albeit cheap, XOR operation to load and store the value. Additionally, unlike the NonZero*
types, transmuting NonAny*
types to their underlying integer types results in a value that was XORed with the niche, instead of the value itself.
The MSRV is currently fixed at 1.56.0, and the intention is to keep it there at least until version 1.0 is released.
- nonmax - Uses the same XOR technique to create types with an
<int>::MAX
niche. The equivalent in nonany would be to either use a niche of<int>::MAX
, or theNonMax*
type aliases. - nook - Uses unstable
rustc_
attributes to define balanced integers. The equivalent in nonany would be to either use a niche of<int>::MIN
, or theNonMin*
type aliases.
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.