devela/code/util/asserts/static/const.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
// devela::code::util::asserts::static::const
//
//! Compile-time assertions.
//
/// Asserts various comparisons on constants.
#[macro_export]
#[cfg_attr(cargo_primary_package, doc(hidden))]
macro_rules! const_assert {
(
// Asserts that a single expression evaluates to `true`.
$x:expr $(,)?) => {
const _: $crate::True = $crate::num::const_bool!($x);
};
(
// Asserts that constants are equal in value.
eq $x:expr, $($y:expr),+ $(,)?) => {
$crate::const_assert!($($x == $y)&&+);
};
(
// Asserts that byte slice buffers are equal in value.
eq_buf $buf:expr, $($other:expr),+ $(,)?) => {
$( $crate::const_assert!($crate::Slice::<u8>::eq($buf, $other)); )+
};
(
// Asserts that string slices are equal in value.
eq_str $str:expr, $($other:expr),+ $(,)?) => {
$(
$crate::const_assert!($crate::Slice::<u8>::eq({$str}.as_bytes(), {$other}.as_bytes()));
)+
};
(
// Asserts that constants of type `usize` are equal in value.
// (Allows for inspecting the values in error messages).
eq_usize $x:expr, $($y:expr),+ $(,)?) => {
$(const _: [(); $x] = [(); $y];)+
};
(
// Asserts that constants are not equal in value.
ne $x:expr, $($y:expr),+ $(,)?) => {
$crate::const_assert!($($x != $y)&&+);
};
(
// Asserts that constants are less than each other.
lt $x:expr, $($y:expr),+ $(,)?) => {
$crate::const_assert!(@build $x, $($y),+; <);
};
(
// Asserts that constants are less than or equal to each other.
le $x:expr, $($y:expr),+ $(,)?) => {
$crate::const_assert!(@build $x, $($y),+; <=);
};
(
// Asserts that constants are greater than each other.
gt $x:expr, $($y:expr),+ $(,)?) => {
$crate::const_assert!(@build $x, $($y),+; >);
};
(
// Asserts that constants are greater than or equal to each other.
ge $x:expr, $($y:expr),+ $(,)?) => {
$crate::const_assert!(@build $x, $($y),+; >=);
};
// receives the expressions and the operator, and performs the appropriate comparison.
(
/* private arms*/
@build $x:expr, $($y:expr),+; $op:tt) => {
$crate::const_assert!($x $op $crate::code::capture_first!(expr $($y),+)); // keep code path
$crate::const_assert!(@build $($y),+; $op);
};
// terminates recursion when there’s only one expression left.
(
@build $x:expr; $op:tt) => {};
}
#[doc(inline)]
pub use const_assert;
#[cfg(test)]
mod tests {
pub use super::*;
#[test]
const fn const_assert() {
const_assert!(true && (true != false));
const_assert!((true && true) != false);
const_assert!(eq false, false);
const_assert!(ne true, false);
#[allow(dead_code)]
const FIVE: usize = 5;
const_assert!(FIVE * 2 == 10);
const_assert!(FIVE > 2);
const_assert!(le 1, 1, 2, 3, 4, 4);
const_assert!(lt 1, 2, 3);
const_assert!(ge 4, 4, 3, 2, 1, 1);
const_assert!(gt 4, 3, 2, 1);
}
}