Crate nonzero_lit

Source
Expand description

A small macro library providing safe, easy, and zero-cost way to construct constant or literal instances of the NonZero* types from core::num.

The parameters to the macro must be constants expressions, but they can be arbitrary arithmetic, calls to const fns, etc. They’re fully evaluated and checked for NonZero-ness at compile time, and thus have truly no cost — even in debug mode.

All misuse is detected at compile time, which can make it much easier to audit and be confident there’s no problems with the complex expression used to initialized one NonZero or another.

§Overview

This crate provides 12 macros for constructing constants, one for each non-zero integral type.

§Features

  • Crate fully supports no_std.
  • All NonZero types are supported.
  • Fully zero cost, even for debug builds (we always evaluate the constant as a const).
  • Input to the macros can be arbitrary constant expressions. This includes const fn calls, which would be more difficult to verify the result as non-zero by hand.
  • Misuse (trying to make a NonZero$Int with a zero value) is always detected at compile time, even when the macro is not being used to initialize a constant.
  • No unsafe code.

§Examples

§Basic usage

let x = nonzero_lit::i32!(4);
assert_eq!(x.get(), 4);

§Constants

§Basic Constants
const FERRIS: core::num::NonZeroU32 = nonzero_lit::u32!(0xf34415);
assert_eq!(FERRIS.get(), 0xf34415);
§Use in const fn

There’s no restriction on use in const fn (as there are with some constant macros):

const fn get_magic() -> core::num::NonZeroU32 {
    nonzero_lit::u32!(25252)
}
assert_eq!(get_magic().get(), 25252)

However, note that the parameters to the macro still must be constants.

§Complex Expressions

Arbitrary constant expressions (including const fns) are allowed.

use core::num::NonZeroU64;

const MASK: NonZeroU64 = nonzero_lit::u64!(0xffff_00ff_00ff_0f0f);
const MASKEE: NonZeroU64 = nonzero_lit::u64!(0xaabb_ccdd_eeff_1122);
// Note: as the complexity increases, it might become less trivial to
// verify that the result of an expression is not zero.
const MASKED: NonZeroU64 = nonzero_lit::u64!(MASK.get() & MASKEE.get());
assert_eq!(MASKED.get(), 0xaabb_00dd_00ff_0102_u64);

§Zero Detection

These tests are deliberately fail to compile, to demonstrate that we detect misuse at compile time.

§Basic Zero Detection

If an attempt to construct a zero NonZero is made, a compile error is emitted.

const OH_NO: core::num::NonZeroU8 = nonzero_lit::i8!(0);
§Complex and Non-const Zero Detection

Zero detection works for complex expressions, even when not initializing a constant (and even both simultaneously).

let shucks = nonzero_lit::i128!(i128::MIN.count_zeros());
§Robust against disabling const_err lint

Zero detection even works in the face of #[allow(const_err)] (which can frequently be used to bypast const evaluation checks of this sort).

#![allow(const_err)]
use core::num::NonZeroU16;

const UH_OH: NonZeroU16 = nonzero_lit::u16!(30 / !0);

Macros§

i8
Create a literal NonZeroI8.
i16
Create a literal NonZeroI16.
i32
Create a literal NonZeroI32.
i64
Create a literal NonZeroI64.
i128
Create a literal NonZeroI128.
isize
Create a literal NonZeroIsize.
u8
Create a literal NonZeroU8.
u16
Create a literal NonZeroU16.
u32
Create a literal NonZeroU32.
u64
Create a literal NonZeroU64.
u128
Create a literal NonZeroU128.
usize
Create a literal NonZeroUsize.