nonmaxunsigned

Crates.iononmaxunsigned
lib.rsnonmaxunsigned
version2.0.0
created_at2025-07-09 19:46:01.411158+00
updated_at2025-07-14 22:09:48.450011+00
descriptionA NonMax integer implementation not relying on NonZero
homepage
repositoryhttps://github.com/Wasabi375/nonmaxunsigned
max_upload_size
id1745371
size92,307
Burkhard Mittelbach (Wasabi375)

documentation

README

NonMax-Unsigned

Crates.io docs.rs Dependency status

This crate provides an implementation for non-max integer types with null-pointer-optimization and ensures that the binary representation of the non-max and the normal integers are the same.

This crate is usable in a no-std environment.

[!WARNING] This crate relies on undefined behaviour in the rust compiler and there is no guarantee that this will continue to work in the future.

Example

use nonmaxunsigned::NonMaxU8;

fn main() {
    let a = NonMaxU8::new(5).unwrap();
    let b = NonMaxU8::new(12).unwrap();

    assert_eq!(NonMaxU8::new(17).unwrap(), a + b);
    assert_eq!(None, NonMaxU8::new(u8::MAX));
}

Maximum Value

The maximum value for the non-max integers is lower than just max - 1. This is neccessary to ensure that the binary representation is the same as the normal integers.

The maximum value for each non-max version is as follows:

Integer Hex Decimal Difference Hex Difference Decimal
u8 0xfe 255 0x1 1
u16 0xfeff 65279 0x100 256
u32 0xfeff_ffff 4278190079 0x100_0000 116777216
u64 0xfeff_ffff_ffff_ffff 18374686479671623679 0x100_0000_0000_0000 72057594037927936

Features

endian-conversion

This feature provides access to little and big endian versions of the non-max integer types as well as conversions between them. The native version for the non-max integers is just a type alias for the correct endianness.

non_max.get() will always return the native endian integer.

#[cfg(feature = "endian-conversion")]
use nonmaxunsigned::{NonMaxU32Le, NonMaxU32Be, NonMaxU32};

#[cfg(feature = "endian-conversion")]
fn main() {
    let native = NonMaxU32::new(37).unwrap();
    let little = native.to_le();
    let big = native.to_be();

    assert_eq!(little.get(), big.get());
    assert_eq!(native.get(), big.get());
    assert_eq!(native.get(), little.get());

    assert_eq!(little.to_native(), native);
    assert_eq!(little.to_be(), big);

    assert_eq!(little.get_underlying(), 37u32.to_le());
    assert_eq!(big.get_underlying(), 37u32.to_be());
}
#[cfg(not(feature = "endian-conversion"))]
fn main() {}

Similar Crates

There are a few similar crates already existing on crates.io:

Unlike those crates this implementation does not NonZero. Those crates store the value as value ^ max which is never 0 as long as value != max. However this means the binary/hex representation of the stored value is hard to parse.

This implementation instead relies on a large enum NonMaxU8Internal which has 254 variants. Such an enum also leads to null-pointer-optimization but does not require the xor trick to prevent 0 values. Instead it relies on core::mem::transmute_copy.

License

Licensed under either of

at your option.

Commit count: 0

cargo fmt