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.
nonzero_lit::usize!
, producing acore::num::NonZeroUsize
.nonzero_lit::isize!
, producing acore::num::NonZeroIsize
.nonzero_lit::u128!
, producing acore::num::NonZeroU128
.nonzero_lit::i128!
, producing acore::num::NonZeroI128
.nonzero_lit::u64!
, producing acore::num::NonZeroU64
.nonzero_lit::i64!
, producing acore::num::NonZeroI64
.nonzero_lit::u32!
, producing acore::num::NonZeroU32
.nonzero_lit::i32!
, producing acore::num::NonZeroI32
.nonzero_lit::u16!
, producing acore::num::NonZeroU16
.nonzero_lit::i16!
, producing acore::num::NonZeroI16
.nonzero_lit::u8!
, producing acore::num::NonZeroU8
.nonzero_lit::i8!
, producing acore::num::NonZeroI8
.
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 fn
s) 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 |
i16 | Create a literal |
i32 | Create a literal |
i64 | Create a literal |
i128 | Create a literal |
isize | Create a literal |
u8 | Create a literal |
u16 | Create a literal |
u32 | Create a literal |
u64 | Create a literal |
u128 | Create a literal |
usize | Create a literal |