# Integers types which cannot be their minimum/maximum value. ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/stijnh/nonminmax/Rust) [![Crates.io](https://img.shields.io/crates/v/nonminmax)](https://crates.io/crates/nonminmax) [![Rustdoc](https://docs.rs/mio/badge.svg)](https://docs.rs/nonminmax/) [![GitHub](https://img.shields.io/github/license/stijnh/nonminmax)](https://github.com/stijnh/nonminmax) The standard library contains a collection of `std::num::NonZeroX` types: integer types which cannot be zero. This crate extends this idea further by providing `NonMinX`/`NonMaxX`: integer types which cannot be their minimum/maximum value. ```Rust // Create a regular NonMinU32 let x = 123 as i32; let y = NonMinI32::new(x).unwrap(); assert_eq!(y.get(), 123); // -2147483648 is the minimum value for a 32-bit integer. let z = NonMinI32::new(-2147483648); assert_eq!(z, None); ``` # Memory optimization Similar to `NonZeroX` types, these `NonMinX`/`NonMaxX` types allow for the niche filling optimization. This means that types such as `Option`/`Option` takes up the same amount of space as `X`, while a regular `Option` takes up twice the size of `X` due to the need of storing the variant tag. ```Rust // Option is larger than a regular u32 assert!(size_of::>() == 2 * size_of::()); // Option/Option is the same size as a regular u32. assert!(size_of::>() == size_of::()); assert!(size_of::>() == size_of::()); ``` While this may seem like a micro-optimization, it becomes important when frequently passing an `Option` around or when creating a large array of `Option`. ```Rust // 1000 x u32 takes up 4000 bytes assert!(size_of::<[u32; 1000]>() == 4000); // 1000 x Option takes up 8000 bytes, ouch assert!(size_of::<[Option; 1000]>() == 8000); // 1000 x Option takes up only 4000 bytes assert!(size_of::<[Option; 1000]>() == 4000); ``` # Internal details Internally, these types work by wrapping the existing `NonZeroX` types and xor-ing with a mask when accessing the inner value. This means that there is the cost of a single `xor` instruction each time `get` is called. # Supported types The following types are supported - `i8`/`u8` - `i16`/`u16` - `i32`/`u32` - `i64`/`u64` - `i128` / `u128` - `isize` / `usize`