mod sealed {
pub trait Sealed {}
}
pub use sealed::Sealed;
pub trait SimdToken: sealed::Sealed + Copy + Clone + Send + Sync + 'static {
const NAME: &'static str;
#[inline(always)]
fn name(&self) -> &'static str {
Self::NAME
}
const TARGET_FEATURES: &'static str;
const ENABLE_TARGET_FEATURES: &'static str;
const DISABLE_TARGET_FEATURES: &'static str;
fn compiled_with() -> Option<bool>;
#[inline(always)]
#[deprecated(since = "0.6.0", note = "Use compiled_with() instead")]
fn guaranteed() -> Option<bool> {
Self::compiled_with()
}
fn summon() -> Option<Self>;
#[inline(always)]
fn attempt() -> Option<Self> {
Self::summon()
}
#[inline(always)]
#[doc(hidden)]
fn try_new() -> Option<Self> {
Self::summon()
}
#[deprecated(
since = "0.5.0",
note = "Pass tokens through from summon() instead of forging"
)]
unsafe fn forge_token_dangerously() -> Self;
}
mod generated;
pub use generated::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ScalarToken;
impl sealed::Sealed for ScalarToken {}
impl SimdToken for ScalarToken {
const NAME: &'static str = "Scalar";
const TARGET_FEATURES: &'static str = "";
const ENABLE_TARGET_FEATURES: &'static str = "";
const DISABLE_TARGET_FEATURES: &'static str = "";
#[inline(always)]
fn compiled_with() -> Option<bool> {
Some(true)
}
#[inline(always)]
fn summon() -> Option<Self> {
Some(Self)
}
#[allow(deprecated)]
#[inline(always)]
unsafe fn forge_token_dangerously() -> Self {
Self
}
}
impl ScalarToken {
pub fn dangerously_disable_token_process_wide(
_disabled: bool,
) -> Result<(), CompileTimeGuaranteedError> {
Err(CompileTimeGuaranteedError {
token_name: Self::NAME,
target_features: Self::TARGET_FEATURES,
disable_flags: Self::DISABLE_TARGET_FEATURES,
})
}
pub fn manually_disabled() -> Result<bool, CompileTimeGuaranteedError> {
Err(CompileTimeGuaranteedError {
token_name: Self::NAME,
target_features: Self::TARGET_FEATURES,
disable_flags: Self::DISABLE_TARGET_FEATURES,
})
}
}
#[derive(Debug, Clone)]
pub struct CompileTimeGuaranteedError {
pub token_name: &'static str,
pub target_features: &'static str,
pub disable_flags: &'static str,
}
impl core::fmt::Display for CompileTimeGuaranteedError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.target_features.is_empty() {
write!(f, "Cannot disable {} — always available.", self.token_name)
} else {
write!(
f,
"Cannot disable {} — features [{}] are compile-time enabled.\n\n\
To allow runtime disable, recompile with RUSTFLAGS:\n \
\"{}\"\n\n\
Or remove `-Ctarget-cpu` from RUSTFLAGS entirely.",
self.token_name, self.target_features, self.disable_flags
)
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for CompileTimeGuaranteedError {}
#[derive(Debug, Clone)]
pub struct DisableAllSimdError {
pub errors: alloc::vec::Vec<CompileTimeGuaranteedError>,
}
impl core::fmt::Display for DisableAllSimdError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Failed to disable {} token(s):", self.errors.len())?;
for err in &self.errors {
write!(f, "\n - {}", err.token_name)?;
}
Ok(())
}
}
#[cfg(feature = "std")]
impl std::error::Error for DisableAllSimdError {}
pub fn dangerously_disable_tokens_except_wasm(
#[allow(unused)] disabled: bool,
) -> Result<(), DisableAllSimdError> {
#[allow(unused_mut)]
let mut errors = alloc::vec::Vec::new();
#[cfg(target_arch = "x86_64")]
if let Err(e) = X64V2Token::dangerously_disable_token_process_wide(disabled) {
errors.push(e);
}
#[cfg(target_arch = "aarch64")]
if let Err(e) = NeonToken::dangerously_disable_token_process_wide(disabled) {
errors.push(e);
}
if errors.is_empty() {
Ok(())
} else {
Err(DisableAllSimdError { errors })
}
}
pub trait IntoConcreteToken: SimdToken + Sized {
#[inline(always)]
fn as_x64v1(self) -> Option<X64V1Token> {
None
}
#[inline(always)]
fn as_x64v2(self) -> Option<X64V2Token> {
None
}
#[inline(always)]
fn as_x64_crypto(self) -> Option<X64CryptoToken> {
None
}
#[inline(always)]
fn as_x64v3(self) -> Option<X64V3Token> {
None
}
#[inline(always)]
fn as_x64v3_crypto(self) -> Option<X64V3CryptoToken> {
None
}
#[inline(always)]
fn as_x64v4(self) -> Option<X64V4Token> {
None
}
#[inline(always)]
fn as_x64v4x(self) -> Option<X64V4xToken> {
None
}
#[inline(always)]
fn as_avx512_fp16(self) -> Option<Avx512Fp16Token> {
None
}
#[inline(always)]
fn as_neon(self) -> Option<NeonToken> {
None
}
#[inline(always)]
fn as_neon_aes(self) -> Option<NeonAesToken> {
None
}
#[inline(always)]
fn as_neon_sha3(self) -> Option<NeonSha3Token> {
None
}
#[inline(always)]
fn as_neon_crc(self) -> Option<NeonCrcToken> {
None
}
#[inline(always)]
fn as_arm_v2(self) -> Option<Arm64V2Token> {
None
}
#[inline(always)]
fn as_arm_v3(self) -> Option<Arm64V3Token> {
None
}
#[inline(always)]
fn as_wasm128(self) -> Option<Wasm128Token> {
None
}
#[inline(always)]
fn as_wasm128_relaxed(self) -> Option<Wasm128RelaxedToken> {
None
}
#[inline(always)]
fn as_scalar(self) -> Option<ScalarToken> {
None
}
}
impl IntoConcreteToken for ScalarToken {
#[inline(always)]
fn as_scalar(self) -> Option<ScalarToken> {
Some(self)
}
}
impl IntoConcreteToken for X64V1Token {
#[inline(always)]
fn as_x64v1(self) -> Option<X64V1Token> {
Some(self)
}
}
impl IntoConcreteToken for X64V2Token {
#[inline(always)]
fn as_x64v2(self) -> Option<X64V2Token> {
Some(self)
}
}
impl IntoConcreteToken for X64CryptoToken {
#[inline(always)]
fn as_x64_crypto(self) -> Option<X64CryptoToken> {
Some(self)
}
}
impl IntoConcreteToken for X64V3Token {
#[inline(always)]
fn as_x64v3(self) -> Option<X64V3Token> {
Some(self)
}
}
impl IntoConcreteToken for X64V3CryptoToken {
#[inline(always)]
fn as_x64v3_crypto(self) -> Option<X64V3CryptoToken> {
Some(self)
}
}
impl IntoConcreteToken for X64V4Token {
#[inline(always)]
fn as_x64v4(self) -> Option<X64V4Token> {
Some(self)
}
}
impl IntoConcreteToken for X64V4xToken {
#[inline(always)]
fn as_x64v4x(self) -> Option<X64V4xToken> {
Some(self)
}
}
impl IntoConcreteToken for Avx512Fp16Token {
#[inline(always)]
fn as_avx512_fp16(self) -> Option<Avx512Fp16Token> {
Some(self)
}
}
impl IntoConcreteToken for NeonToken {
#[inline(always)]
fn as_neon(self) -> Option<NeonToken> {
Some(self)
}
}
impl IntoConcreteToken for NeonAesToken {
#[inline(always)]
fn as_neon_aes(self) -> Option<NeonAesToken> {
Some(self)
}
}
impl IntoConcreteToken for NeonSha3Token {
#[inline(always)]
fn as_neon_sha3(self) -> Option<NeonSha3Token> {
Some(self)
}
}
impl IntoConcreteToken for NeonCrcToken {
#[inline(always)]
fn as_neon_crc(self) -> Option<NeonCrcToken> {
Some(self)
}
}
impl IntoConcreteToken for Arm64V2Token {
#[inline(always)]
fn as_arm_v2(self) -> Option<Arm64V2Token> {
Some(self)
}
}
impl IntoConcreteToken for Arm64V3Token {
#[inline(always)]
fn as_arm_v3(self) -> Option<Arm64V3Token> {
Some(self)
}
}
impl IntoConcreteToken for Wasm128Token {
#[inline(always)]
fn as_wasm128(self) -> Option<Wasm128Token> {
Some(self)
}
}
impl IntoConcreteToken for Wasm128RelaxedToken {
#[inline(always)]
fn as_wasm128_relaxed(self) -> Option<Wasm128RelaxedToken> {
Some(self)
}
}