use crate::optimized_core::OptimizationLevel;
#[derive(Debug, Clone)]
pub struct FeatureConfig {
pub optimization_level: OptimizationLevel,
pub enable_parallel: bool,
pub enable_advanced_simd: bool,
pub enable_platform_optimizations: bool,
}
impl Default for FeatureConfig {
fn default() -> Self {
Self {
optimization_level: OptimizationLevel::best_available(),
enable_parallel: true,
enable_advanced_simd: true,
enable_platform_optimizations: true,
}
}
}
impl FeatureConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_optimization_level(level: OptimizationLevel) -> Self {
Self {
optimization_level: level,
enable_parallel: true,
enable_advanced_simd: true,
enable_platform_optimizations: true,
}
}
pub fn security_optimized() -> Self {
Self {
optimization_level: OptimizationLevel::Reference,
enable_parallel: false,
enable_advanced_simd: false,
enable_platform_optimizations: false,
}
}
pub fn performance_optimized() -> Self {
Self {
optimization_level: OptimizationLevel::Maximum,
enable_parallel: true,
enable_advanced_simd: true,
enable_platform_optimizations: true,
}
}
pub fn compatibility_optimized() -> Self {
Self {
optimization_level: OptimizationLevel::Basic,
enable_parallel: false,
enable_advanced_simd: false,
enable_platform_optimizations: true,
}
}
pub fn parallel_available(&self) -> bool {
self.enable_parallel &&
cfg!(all(feature = "simd", keccak_portable_simd)) &&
self.optimization_level != OptimizationLevel::Reference
}
pub fn advanced_simd_available(&self) -> bool {
self.enable_advanced_simd &&
cfg!(all(feature = "simd", keccak_portable_simd)) &&
self.optimization_level != OptimizationLevel::Reference
}
pub fn platform_optimizations_available(&self) -> bool {
self.enable_platform_optimizations &&
self.optimization_level != OptimizationLevel::Reference
}
pub fn effective_optimization_level(&self) -> OptimizationLevel {
if !self.enable_platform_optimizations {
return OptimizationLevel::Reference;
}
if !self.enable_advanced_simd && self.optimization_level == OptimizationLevel::Maximum {
return OptimizationLevel::Advanced;
}
self.optimization_level
}
pub fn description(&self) -> &'static str {
let _level = self.effective_optimization_level();
if self.parallel_available() &&
self.advanced_simd_available() &&
self.platform_optimizations_available()
{
"maximum optimization with all features"
} else if self.parallel_available() && self.platform_optimizations_available() {
"advanced optimization with parallel processing"
} else if self.platform_optimizations_available() {
"basic optimization with platform features"
} else {
"reference implementation"
}
}
}
static GLOBAL_CONFIG: spin::RwLock<Option<FeatureConfig>> = spin::RwLock::new(None);
pub fn set_global_config(config: FeatureConfig) {
*GLOBAL_CONFIG.write() = Some(config);
}
pub fn get_global_config() -> FeatureConfig {
GLOBAL_CONFIG.read().clone().unwrap_or_default()
}
pub fn reset_global_config() {
*GLOBAL_CONFIG.write() = None;
}
pub mod detection {
use super::*;
pub fn detect_available_features() -> FeatureReport {
FeatureReport {
x86_64: cfg!(target_arch = "x86_64"),
avx2: cfg!(all(target_arch = "x86_64", target_feature = "avx2")),
avx512f: cfg!(all(target_arch = "x86_64", target_feature = "avx512f")),
aarch64: cfg!(target_arch = "aarch64"),
sha3_intrinsics: cfg!(all(
target_arch = "aarch64",
feature = "arm64_sha3",
target_feature = "sha3",
not(cross_compile)
)),
simd_support: cfg!(all(feature = "simd", keccak_portable_simd)),
nightly_features: cfg!(feature = "nightly"),
}
}
pub fn best_available_optimization() -> OptimizationLevel {
OptimizationLevel::best_available()
}
pub fn is_optimization_available(level: OptimizationLevel) -> bool {
level.is_available()
}
}
#[derive(Debug, Clone)]
pub struct FeatureReport {
pub x86_64: bool,
pub avx2: bool,
pub avx512f: bool,
pub aarch64: bool,
pub sha3_intrinsics: bool,
pub simd_support: bool,
pub nightly_features: bool,
}
impl FeatureReport {
pub fn summary(&self) -> &'static str {
if self.avx512f {
"Available features: x86_64, AVX2, AVX-512, SIMD, nightly features"
} else if self.avx2 {
"Available features: x86_64, AVX2, SIMD, nightly features"
} else if self.sha3_intrinsics {
"Available features: AArch64, SHA3 intrinsics, SIMD, nightly features"
} else if self.x86_64 {
"Available features: x86_64, SIMD, nightly features"
} else if self.aarch64 {
"Available features: AArch64, SIMD, nightly features"
} else if self.simd_support {
"Available features: SIMD, nightly features"
} else if self.nightly_features {
"Available features: nightly features"
} else {
"No special features available"
}
}
pub fn recommended_optimization_level(&self) -> OptimizationLevel {
if self.avx512f && OptimizationLevel::Maximum.is_available() {
OptimizationLevel::Maximum
} else if self.avx2 && OptimizationLevel::Advanced.is_available() {
OptimizationLevel::Advanced
} else if self.sha3_intrinsics && OptimizationLevel::Basic.is_available() {
OptimizationLevel::Basic
} else {
OptimizationLevel::Reference
}
}
}
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "std")]
fn test_feature_config_default() {
use crate::FeatureConfig;
let config = FeatureConfig::default();
assert!(config.optimization_level.is_available());
assert!(config.enable_parallel);
assert!(config.enable_advanced_simd);
assert!(config.enable_platform_optimizations);
}
#[test]
#[cfg(feature = "std")]
fn test_feature_config_security_optimized() {
use crate::{
FeatureConfig,
OptimizationLevel,
};
let config = FeatureConfig::security_optimized();
assert_eq!(config.optimization_level, OptimizationLevel::Reference);
assert!(!config.enable_parallel);
assert!(!config.enable_advanced_simd);
assert!(!config.enable_platform_optimizations);
}
#[test]
#[cfg(feature = "std")]
fn test_feature_config_performance_optimized() {
use crate::{
FeatureConfig,
OptimizationLevel,
};
let config = FeatureConfig::performance_optimized();
assert_eq!(config.optimization_level, OptimizationLevel::Maximum);
assert!(config.enable_parallel);
assert!(config.enable_advanced_simd);
assert!(config.enable_platform_optimizations);
}
#[test]
#[cfg(feature = "std")]
fn test_feature_detection() {
use super::detection;
let report = detection::detect_available_features();
assert!(!report.summary().is_empty());
let recommended = report.recommended_optimization_level();
assert!(recommended.is_available());
}
#[test]
#[cfg(feature = "std")]
fn test_global_config() {
use crate::{
FeatureConfig,
OptimizationLevel,
get_global_config,
reset_global_config,
set_global_config,
};
let config = FeatureConfig::security_optimized();
set_global_config(config.clone());
let retrieved = get_global_config();
assert_eq!(retrieved.optimization_level, config.optimization_level);
reset_global_config();
let default = get_global_config();
assert_eq!(
default.optimization_level,
OptimizationLevel::best_available()
);
}
}