#non-zero #integer #traits #extension #type #numbers #literals

no-std nonzero_ext

Extensions and additional traits for non-zero integer types

8 releases

Uses old Rust 2015

0.3.0 Aug 21, 2021
0.2.0 Dec 24, 2019
0.1.5 Mar 10, 2019
0.1.2 Oct 23, 2018
0.0.2 Sep 15, 2018

#671 in Rust patterns

Download history 186894/week @ 2024-07-04 188479/week @ 2024-07-11 187823/week @ 2024-07-18 202169/week @ 2024-07-25 185687/week @ 2024-08-01 229013/week @ 2024-08-08 244304/week @ 2024-08-15 255884/week @ 2024-08-22 245081/week @ 2024-08-29 271795/week @ 2024-09-05 257138/week @ 2024-09-12 265281/week @ 2024-09-19 274786/week @ 2024-09-26 304359/week @ 2024-10-03 298815/week @ 2024-10-10 321521/week @ 2024-10-17

1,260,196 downloads per month
Used in 275 crates (34 directly)

Apache-2.0

16KB
120 lines

nonzero_ext

Traits to represent generic nonzero integer types

Build status Docs

Rust ships with non-zero integer types now, which let programmers promise (memory-savingly!) that a number can never be zero. That's great, but sadly the standard library has not got a whole lot of tools to help you use them ergonomically.

A macro for non-zero constant literals

Creating and handling constant literals is neat, but the standard library (and the rust parser at the moment) have no affordances to easily create values of num::NonZeroU* types from constant literals. This crate ships a nonzero! macro that lets you write nonzero!(20u32), which checks at compile time that the constant being converted is non-zero, instead of the cumbersome (and runtime-checked!) NonZeroU32::new(20).unwrap().

Traits for generic non-zeroness

The stdlib num::NonZeroU* types do not implement any common traits (and neither do their zeroable equivalents). Where this lack of traits in the standard library becomes problematic is if you want to write a function that takes a vector of integers, and that returns a vector of the corresponding non-zero integer types, minus any elements that were zero in the original. You can write that with the standard library quite easily for concrete types:

fn only_nonzeros(v: Vec<u8>) -> Vec<NonZeroU8>
{
    v.into_iter()
        .filter_map(|n| NonZeroU8::new(n))
        .collect::<Vec<NonZeroU8>>()
}
let expected: Vec<NonZeroU8> = vec![nonzero!(20u8), nonzero!(5u8)];
assert_eq!(expected, only_nonzeros(vec![0, 20, 5]));

But what if you want to allow this function to work with any integer type that has a corresponding non-zero type? This crate can help:

fn only_nonzeros<I>(v: Vec<I>) -> Vec<I::NonZero>
where
    I: Sized + NonZeroAble,
{
    v.into_iter()
        .filter_map(|n| n.as_nonzero())
        .collect::<Vec<I::NonZero>>()
}

// It works for `u8`:
let input_u8: Vec<u8> = vec![0, 20, 5];
let expected_u8: Vec<NonZeroU8> = vec![nonzero!(20u8), nonzero!(5u8)];
assert_eq!(expected_u8, only_nonzeros(input_u8));

// And it works for `u32`:
let input_u32: Vec<u32> = vec![0, 20, 5];
let expected_u32: Vec<NonZeroU32> = vec![nonzero!(20u32), nonzero!(5u32)];
assert_eq!(expected_u32, only_nonzeros(input_u32));

License: Apache-2.0

No runtime deps