4 releases (2 breaking)

0.3.0 Oct 9, 2024
0.2.1 Oct 3, 2024
0.2.0 Oct 3, 2024
0.1.0 Oct 2, 2024

#371 in Rust patterns

Download history 382/week @ 2024-09-28 182/week @ 2024-10-05 29/week @ 2024-10-12 2/week @ 2024-10-19

332 downloads per month

MIT/Apache

55KB
1K SLoC

nonany

crates.io docs msrv

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>>());

Example

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");

Provided types

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

How does it work?

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.

MSRV

The MSRV is fixed at currently 1.56.0, and the intention is to keep it there at least until version 1.0 is released.

Similar libraries

  • 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 the NonMax* 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 the NonMin* type aliases.

License

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.

No runtime deps