#![no_std]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
)]
#![warn(clippy::pedantic)]
#[macro_export]
macro_rules! cpubits {
( 16 => { $( $tokens:tt )* } ) => {
$crate::cpubits! {
16 => { $( $tokens )* },
32 | 64 => { }
}
};
( 32 => { $( $tokens:tt )* } ) => {
$crate::cpubits! {
16 => { }
32 => { $( $tokens )* }
64 => { }
}
};
( 64 => { $( $tokens:tt )* } ) => {
$crate::cpubits! {
16 | 32 => { }
64 => { $( $tokens )* }
}
};
( 16 | 32 => { $( $tokens:tt )* } ) => {
$crate::cpubits! {
16 => { $( $tokens )* }
32 => { $( $tokens )* }
64 => { }
}
};
( 32 | 64 => { $( $tokens:tt )* } ) => {
$crate::cpubits! {
16 => { }
32 => { $( $tokens )* }
64 => { $( $tokens )* }
}
};
(
16 => { $( $tokens16:tt )* }
32 => { $( $tokens32:tt )* }
) => {
$crate::cpubits! {
16 => { $( $tokens16 )* }
32 => { $( $tokens32 )* }
64 => { }
}
};
(
32 => { $( $tokens32:tt )* }
64 => { $( $tokens64:tt )* }
) => {
$crate::cpubits! {
16 => { }
32 => { $( $tokens32 )* }
64 => { $( $tokens64 )* }
}
};
(
16 => { $( $tokens16:tt )* }
32 | 64 => { $( $tokens32:tt )* }
) => {
$crate::cpubits! {
16 => { $( $tokens16 )* }
32 => { $( $tokens32 )* }
64 => { $( $tokens32 )* }
}
};
(
16 | 32 => { $( $tokens32:tt )* }
64 => { $( $tokens64:tt )* }
) => {
$crate::cpubits! {
16 => { $( $tokens32 )* }
32 => { $( $tokens32 )* }
64 => { $( $tokens64 )* }
}
};
(
16 => { $( $tokens16:tt )* }
32 => { $( $tokens32:tt )* }
64 => { $( $tokens64:tt )* }
) => {
$crate::cpubits! {
#[cfg(enable_64_bit = any(
// ARMv7
all(target_arch = "arm", target_feature = "v7"),
// WASM
target_arch = "wasm32",
))]
16 => { $( $tokens16 )* }
32 => { $( $tokens32 )* }
64 => { $( $tokens64 )* }
}
};
(
#[cfg(enable_64_bit = $($enable_64_bit:tt)+ )]
16 => { $( $tokens16:tt )* }
32 => { $( $tokens32:tt )* }
64 => { $( $tokens64:tt )* }
) => {
$crate::cfg_if! {
@__items () ;
(
( cpubits = "16" )
( $( $tokens16 )* )
),
(
( cpubits = "32" )
( $( $tokens32 )* )
),
(
( cpubits = "64" )
( $( $tokens64 )* )
),
(
( target_pointer_width = "16" )
( $( $tokens16 )* )
),
(
( all(target_pointer_width = "32", not($( $enable_64_bit )+)) )
( $( $tokens32 )* )
),
(
( any(target_pointer_width = "64", $( $enable_64_bit )+) )
( $( $tokens64 )* )
),
(
()
( compile_error!("unsupported target pointer width") )
),
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! cfg_if {
(
if #[cfg( $($i_meta:tt)+ )] { $( $i_tokens:tt )* }
$(
else if #[cfg( $($ei_meta:tt)+ )] { $( $ei_tokens:tt )* }
)*
$(
else { $( $e_tokens:tt )* }
)?
) => {
$crate::cfg_if! {
@__items () ;
(( $($i_meta)+ ) ( $( $i_tokens )* )),
$(
(( $($ei_meta)+ ) ( $( $ei_tokens )* )),
)*
$(
(() ( $( $e_tokens )* )),
)?
}
};
(@__items ( $( ($($_:tt)*) , )* ) ; ) => {};
(
@__items ( $( ($($no:tt)+) , )* ) ;
(( $( $($yes:tt)+ )? ) ( $( $tokens:tt )* )),
$( $rest:tt , )*
) => {
#[cfg(all(
$( $($yes)+ , )?
not(any( $( $($no)+ ),* ))
))]
$crate::cfg_if! { @__temp_group $( $tokens )* }
$crate::cfg_if! {
@__items ( $( ($($no)+) , )* $( ($($yes)+) , )? ) ;
$( $rest , )*
}
};
(@__temp_group $( $tokens:tt )* ) => {
$( $tokens )*
};
}
pub const CPUBITS: u32 = {
cpubits! {
16 => { 16 }
32 => { 32 }
64 => { 64 }
}
};
#[cfg(test)]
mod tests {
use super::CPUBITS;
#[cfg(not(any(cpubits = "16", cpubits = "32", cpubits = "64")))]
fn expected_bits() -> u32 {
if cfg!(any(
all(target_arch = "arm", target_feature = "v7"),
target_arch = "wasm32"
)) {
64
} else {
usize::BITS
}
}
#[cfg(not(any(cpubits = "16", cpubits = "32", cpubits = "64")))]
#[test]
fn cpubits_works() {
assert_eq!(CPUBITS, expected_bits());
}
#[cfg(all(target_arch = "arm", target_feature = "v7"))]
#[test]
fn cpubits_on_armv7_is_64bit() {
assert_eq!(CPUBITS, 64);
}
#[cfg(target_arch = "wasm32")]
#[test]
fn cpubits_on_wasm_is_64bit() {
assert_eq!(CPUBITS, 64);
}
#[cfg(not(any(cpubits = "16", cpubits = "32", cpubits = "64")))]
#[test]
fn cpubits_16_or_32_vs_64() {
const BITS: u32 = {
cpubits! {
16 | 32 => { 32 }
64 => { 64 }
}
};
match expected_bits() {
16 | 32 => assert_eq!(32, BITS),
64 => assert_eq!(64, BITS),
bits => unreachable!("#{bits}-bits should be one of: 16, 32, 64"),
}
}
#[cfg(cpubits = "32")]
#[test]
fn cpubits_32_bit_override() {
assert_eq!(CPUBITS, 32);
}
}