-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Leverages some idiosyncrasies of the Rust type system to define macros which can be used to make compile-time assertions about const generic parameters, working around the "can't use generic parameters from outer item" error which would occur if one simply used `assert_eq`/`assert_ne`
- Loading branch information
Showing
4 changed files
with
80 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
//! Macro definitions which are a part of the public API. | ||
/// Internal implementation detail of [`const_assert_eq`] and [`const_assert_ne`]. | ||
#[doc(hidden)] | ||
#[macro_export] | ||
macro_rules! const_assert_n { | ||
($n:expr, $($arg:tt)*) => {{ | ||
// TODO(tarcieri): gensym a name so it's unique per invocation of the macro? | ||
mod __const_assert { | ||
pub(super) struct Assert<const N: usize>; | ||
|
||
impl<const N: usize> Assert<N> { | ||
pub(super) const ASSERT: () = assert!($($arg)*); | ||
} | ||
} | ||
|
||
__const_assert::Assert::<$n>::ASSERT | ||
}}; | ||
} | ||
|
||
/// Const-friendly assertion that two values are equal. | ||
/// | ||
/// ``` | ||
/// const _: () = crypto_bigint::const_assert_eq!(0, 0, "zero equals zero"); | ||
/// ``` | ||
#[macro_export] | ||
macro_rules! const_assert_eq { | ||
($left:expr, $right:expr $(,)?) => ( | ||
$crate::const_assert_n!($left, $left == $right) | ||
); | ||
($left:expr, $right:expr, $($arg:tt)+) => ( | ||
$crate::const_assert_n!($left, $left == $right, $($arg)+) | ||
); | ||
} | ||
|
||
/// Const-friendly assertion that two values are NOT equal. | ||
/// | ||
/// ``` | ||
/// const _: () = crypto_bigint::const_assert_ne!(0, 1, "zero is NOT equal to one"); | ||
/// ``` | ||
#[macro_export] | ||
macro_rules! const_assert_ne { | ||
($left:expr, $right:expr $(,)?) => ( | ||
$crate::const_assert_n!($left, $left != $right) | ||
); | ||
($left:expr, $right:expr, $($arg:tt)+) => ( | ||
$crate::const_assert_n!($left, $left != $right, $($arg)+) | ||
); | ||
} | ||
|
||
/// Calculate the number of limbs required to represent the given number of bits. | ||
// TODO(tarcieri): replace with `generic_const_exprs` (rust-lang/rust#76560) when stable | ||
#[macro_export] | ||
macro_rules! nlimbs { | ||
($bits:expr) => { | ||
$bits / $crate::Limb::BITS | ||
}; | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
#[cfg(target_pointer_width = "32")] | ||
#[test] | ||
fn nlimbs_for_bits_macro() { | ||
assert_eq!(nlimbs!(64), 2); | ||
assert_eq!(nlimbs!(128), 4); | ||
assert_eq!(nlimbs!(192), 6); | ||
assert_eq!(nlimbs!(256), 8); | ||
} | ||
|
||
#[cfg(target_pointer_width = "64")] | ||
#[test] | ||
fn nlimbs_for_bits_macro() { | ||
assert_eq!(nlimbs!(64), 1); | ||
assert_eq!(nlimbs!(128), 2); | ||
assert_eq!(nlimbs!(192), 3); | ||
assert_eq!(nlimbs!(256), 4); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters