1use crate::optimized_core::OptimizationLevel;
8
9#[derive(Debug, Clone)]
14pub struct FeatureConfig {
15 pub optimization_level: OptimizationLevel,
17 pub enable_parallel: bool,
19 pub enable_advanced_simd: bool,
21 pub enable_platform_optimizations: bool,
23}
24
25impl Default for FeatureConfig {
26 fn default() -> Self {
27 Self {
28 optimization_level: OptimizationLevel::best_available(),
29 enable_parallel: true,
30 enable_advanced_simd: true,
31 enable_platform_optimizations: true,
32 }
33 }
34}
35
36impl FeatureConfig {
37 pub fn new() -> Self {
39 Self::default()
40 }
41
42 pub fn with_optimization_level(level: OptimizationLevel) -> Self {
44 Self {
45 optimization_level: level,
46 enable_parallel: true,
47 enable_advanced_simd: true,
48 enable_platform_optimizations: true,
49 }
50 }
51
52 pub fn security_optimized() -> Self {
57 Self {
58 optimization_level: OptimizationLevel::Reference,
59 enable_parallel: false,
60 enable_advanced_simd: false,
61 enable_platform_optimizations: false,
62 }
63 }
64
65 pub fn performance_optimized() -> Self {
70 Self {
71 optimization_level: OptimizationLevel::Maximum,
72 enable_parallel: true,
73 enable_advanced_simd: true,
74 enable_platform_optimizations: true,
75 }
76 }
77
78 pub fn compatibility_optimized() -> Self {
83 Self {
84 optimization_level: OptimizationLevel::Basic,
85 enable_parallel: false,
86 enable_advanced_simd: false,
87 enable_platform_optimizations: true,
88 }
89 }
90
91 pub fn parallel_available(&self) -> bool {
93 self.enable_parallel &&
94 cfg!(all(feature = "simd", keccak_portable_simd)) &&
95 self.optimization_level != OptimizationLevel::Reference
96 }
97
98 pub fn advanced_simd_available(&self) -> bool {
100 self.enable_advanced_simd &&
101 cfg!(all(feature = "simd", keccak_portable_simd)) &&
102 self.optimization_level != OptimizationLevel::Reference
103 }
104
105 pub fn platform_optimizations_available(&self) -> bool {
107 self.enable_platform_optimizations &&
108 self.optimization_level != OptimizationLevel::Reference
109 }
110
111 pub fn effective_optimization_level(&self) -> OptimizationLevel {
113 if !self.enable_platform_optimizations {
114 return OptimizationLevel::Reference;
115 }
116
117 if !self.enable_advanced_simd && self.optimization_level == OptimizationLevel::Maximum {
118 return OptimizationLevel::Advanced;
119 }
120
121 self.optimization_level
122 }
123
124 pub fn description(&self) -> &'static str {
126 let _level = self.effective_optimization_level();
127
128 if self.parallel_available() &&
129 self.advanced_simd_available() &&
130 self.platform_optimizations_available()
131 {
132 "maximum optimization with all features"
133 } else if self.parallel_available() && self.platform_optimizations_available() {
134 "advanced optimization with parallel processing"
135 } else if self.platform_optimizations_available() {
136 "basic optimization with platform features"
137 } else {
138 "reference implementation"
139 }
140 }
141}
142
143static GLOBAL_CONFIG: spin::RwLock<Option<FeatureConfig>> = spin::RwLock::new(None);
150
151pub fn set_global_config(config: FeatureConfig) {
156 *GLOBAL_CONFIG.write() = Some(config);
157}
158
159pub fn get_global_config() -> FeatureConfig {
164 GLOBAL_CONFIG.read().clone().unwrap_or_default()
165}
166
167pub fn reset_global_config() {
169 *GLOBAL_CONFIG.write() = None;
170}
171
172pub mod detection {
174 use super::*;
175
176 pub fn detect_available_features() -> FeatureReport {
181 FeatureReport {
182 x86_64: cfg!(target_arch = "x86_64"),
183 avx2: cfg!(all(target_arch = "x86_64", target_feature = "avx2")),
184 avx512f: cfg!(all(target_arch = "x86_64", target_feature = "avx512f")),
185 aarch64: cfg!(target_arch = "aarch64"),
186 sha3_intrinsics: cfg!(all(
187 target_arch = "aarch64",
188 feature = "arm64_sha3",
189 target_feature = "sha3",
190 not(cross_compile)
191 )),
192 simd_support: cfg!(all(feature = "simd", keccak_portable_simd)),
193 nightly_features: cfg!(feature = "nightly"),
194 }
195 }
196
197 pub fn best_available_optimization() -> OptimizationLevel {
199 OptimizationLevel::best_available()
200 }
201
202 pub fn is_optimization_available(level: OptimizationLevel) -> bool {
204 level.is_available()
205 }
206}
207
208#[derive(Debug, Clone)]
210pub struct FeatureReport {
211 pub x86_64: bool,
213 pub avx2: bool,
215 pub avx512f: bool,
217 pub aarch64: bool,
219 pub sha3_intrinsics: bool,
221 pub simd_support: bool,
223 pub nightly_features: bool,
225}
226
227impl FeatureReport {
228 pub fn summary(&self) -> &'static str {
230 if self.avx512f {
231 "Available features: x86_64, AVX2, AVX-512, SIMD, nightly features"
232 } else if self.avx2 {
233 "Available features: x86_64, AVX2, SIMD, nightly features"
234 } else if self.sha3_intrinsics {
235 "Available features: AArch64, SHA3 intrinsics, SIMD, nightly features"
236 } else if self.x86_64 {
237 "Available features: x86_64, SIMD, nightly features"
238 } else if self.aarch64 {
239 "Available features: AArch64, SIMD, nightly features"
240 } else if self.simd_support {
241 "Available features: SIMD, nightly features"
242 } else if self.nightly_features {
243 "Available features: nightly features"
244 } else {
245 "No special features available"
246 }
247 }
248
249 pub fn recommended_optimization_level(&self) -> OptimizationLevel {
251 if self.avx512f && OptimizationLevel::Maximum.is_available() {
252 OptimizationLevel::Maximum
253 } else if self.avx2 && OptimizationLevel::Advanced.is_available() {
254 OptimizationLevel::Advanced
255 } else if self.sha3_intrinsics && OptimizationLevel::Basic.is_available() {
256 OptimizationLevel::Basic
257 } else {
258 OptimizationLevel::Reference
259 }
260 }
261}
262
263#[cfg(test)]
264mod tests {
265
266 #[test]
267 #[cfg(feature = "std")]
268 fn test_feature_config_default() {
269 use crate::FeatureConfig;
270
271 let config = FeatureConfig::default();
272 assert!(config.optimization_level.is_available());
273 assert!(config.enable_parallel);
274 assert!(config.enable_advanced_simd);
275 assert!(config.enable_platform_optimizations);
276 }
277
278 #[test]
279 #[cfg(feature = "std")]
280 fn test_feature_config_security_optimized() {
281 use crate::{
282 FeatureConfig,
283 OptimizationLevel,
284 };
285
286 let config = FeatureConfig::security_optimized();
287 assert_eq!(config.optimization_level, OptimizationLevel::Reference);
288 assert!(!config.enable_parallel);
289 assert!(!config.enable_advanced_simd);
290 assert!(!config.enable_platform_optimizations);
291 }
292
293 #[test]
294 #[cfg(feature = "std")]
295 fn test_feature_config_performance_optimized() {
296 use crate::{
297 FeatureConfig,
298 OptimizationLevel,
299 };
300
301 let config = FeatureConfig::performance_optimized();
302 assert_eq!(config.optimization_level, OptimizationLevel::Maximum);
303 assert!(config.enable_parallel);
304 assert!(config.enable_advanced_simd);
305 assert!(config.enable_platform_optimizations);
306 }
307
308 #[test]
309 #[cfg(feature = "std")]
310 fn test_feature_detection() {
311 use super::detection;
312
313 let report = detection::detect_available_features();
314 assert!(!report.summary().is_empty());
315
316 let recommended = report.recommended_optimization_level();
317 assert!(recommended.is_available());
318 }
319
320 #[test]
321 #[cfg(feature = "std")]
322 fn test_global_config() {
323 use crate::{
324 FeatureConfig,
325 OptimizationLevel,
326 get_global_config,
327 reset_global_config,
328 set_global_config,
329 };
330
331 let config = FeatureConfig::security_optimized();
332 set_global_config(config.clone());
333
334 let retrieved = get_global_config();
335 assert_eq!(retrieved.optimization_level, config.optimization_level);
336
337 reset_global_config();
338 let default = get_global_config();
339 assert_eq!(
340 default.optimization_level,
341 OptimizationLevel::best_available()
342 );
343 }
344}