mirror of
https://github.com/kristoferssolo/cipher-workshop.git
synced 2025-12-20 11:04:38 +00:00
78 lines
2.2 KiB
Rust
78 lines
2.2 KiB
Rust
/// Macro to generate a masked, zeroizable integer wrapper type.
|
|
///
|
|
/// Usage:
|
|
/// ```
|
|
/// secret_int! {
|
|
/// /// docs...
|
|
/// pub struct Subkey(u64, 48, 0x0000_FFFF_FFFF_FFFFu64);
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// Optional `clone` token enables an explicit Clone impl:
|
|
/// ```
|
|
/// secret_int! { pub struct Foo(u32, 28, 0x0FFF_FFFFu32, clone); }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! secret_int {
|
|
(
|
|
$(#[$meta:meta])*
|
|
$vis:vis struct $name:ident ( $int:ty, $bits:expr, $mask:expr $(, $opt:ident )? );
|
|
) => {
|
|
$(#[$meta])*
|
|
#[derive(::zeroize::ZeroizeOnDrop, Default, Eq)]
|
|
#[zeroize(drop)]
|
|
$vis struct $name($int);
|
|
|
|
impl $name {
|
|
/// Mask to restrict the underlying integer to valid bits.
|
|
pub const MASK: $int = $mask;
|
|
|
|
/// Create from the given integer.
|
|
#[inline]
|
|
#[must_use]
|
|
pub const fn from_int(key: $int) -> Self {
|
|
Self(key & Self::MASK)
|
|
}
|
|
|
|
/// Return as masked integer value;
|
|
#[inline]
|
|
#[must_use]
|
|
pub const fn as_int(&self) -> $int {
|
|
self.0 & Self::MASK
|
|
}
|
|
}
|
|
|
|
// Optionally add Clone if requested explicitly (discouraged for secrets)
|
|
secret_int!(@maybe_add_clone $( $opt )? ; $name, $int);
|
|
|
|
impl ::std::fmt::Debug for $name {
|
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
|
f.write_str(concat!(stringify!($name), "[REDACTED]"))
|
|
}
|
|
}
|
|
|
|
impl From<$int> for $name {
|
|
fn from(v: $int) -> Self {
|
|
Self::from_int(v)
|
|
}
|
|
}
|
|
|
|
impl PartialEq for $name {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.as_int() == other.as_int()
|
|
}
|
|
}
|
|
};
|
|
|
|
// helper arm: create Clone impl only when "clone" token present
|
|
(@maybe_add_clone clone ; $name:ident, $int:ty) => {
|
|
impl Clone for $name {
|
|
fn clone(&self) -> Self {
|
|
// explicit clone - intentionally duplicating secret
|
|
Self::from_int(self.as_int())
|
|
}
|
|
}
|
|
};
|
|
(@maybe_add_clone ; $name:ident, $int:ty) => {};
|
|
}
|