Crate nonzero_lit[][src]

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.