Skip to main content

lib_q_keccak/
features.rs

1//! Feature configuration and runtime optimization selection
2//!
3//! This module provides runtime feature detection and optimization selection
4//! capabilities, allowing users to choose the best available optimizations
5//! for their specific use case.
6
7use crate::optimized_core::OptimizationLevel;
8
9/// Runtime feature detection and configuration
10///
11/// This struct provides methods to detect available hardware features
12/// and select appropriate optimization levels.
13#[derive(Debug, Clone)]
14pub struct FeatureConfig {
15    /// The selected optimization level
16    pub optimization_level: OptimizationLevel,
17    /// Whether to use parallel processing when available
18    pub enable_parallel: bool,
19    /// Whether to use advanced SIMD features when available
20    pub enable_advanced_simd: bool,
21    /// Whether to use platform-specific optimizations
22    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    /// Create a new feature configuration with automatic detection
38    pub fn new() -> Self {
39        Self::default()
40    }
41
42    /// Create a feature configuration with specific optimization level
43    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    /// Create a feature configuration optimized for security
53    ///
54    /// This configuration prioritizes security over performance by using
55    /// only well-tested reference implementations.
56    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    /// Create a feature configuration optimized for performance
66    ///
67    /// This configuration enables all available optimizations for maximum
68    /// performance, potentially at the cost of some security guarantees.
69    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    /// Create a feature configuration optimized for compatibility
79    ///
80    /// This configuration uses only stable, widely-supported optimizations
81    /// to ensure maximum compatibility across different platforms.
82    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    /// Check if parallel processing is available and enabled
92    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    /// Check if advanced SIMD features are available and enabled
99    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    /// Check if platform-specific optimizations are available and enabled
106    pub fn platform_optimizations_available(&self) -> bool {
107        self.enable_platform_optimizations &&
108            self.optimization_level != OptimizationLevel::Reference
109    }
110
111    /// Get the effective optimization level based on current configuration
112    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    /// Get a human-readable description of the current configuration
125    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
143/// Global feature configuration storage.
144///
145/// Guarded by a [`spin::RwLock`] so concurrent readers and writers from any
146/// thread (including bare-metal `no_std` cores) observe a consistent value
147/// without resorting to `static mut`, which is undefined behaviour under
148/// concurrent access.
149static GLOBAL_CONFIG: spin::RwLock<Option<FeatureConfig>> = spin::RwLock::new(None);
150
151/// Set the global feature configuration.
152///
153/// Subsequent calls to [`get_global_config`] return a clone of `config` until
154/// it is overwritten or cleared by [`reset_global_config`].
155pub fn set_global_config(config: FeatureConfig) {
156    *GLOBAL_CONFIG.write() = Some(config);
157}
158
159/// Get the global feature configuration.
160///
161/// Returns a clone of the currently configured value, or
162/// [`FeatureConfig::default`] if none has been set.
163pub fn get_global_config() -> FeatureConfig {
164    GLOBAL_CONFIG.read().clone().unwrap_or_default()
165}
166
167/// Reset the global feature configuration to its unset state.
168pub fn reset_global_config() {
169    *GLOBAL_CONFIG.write() = None;
170}
171
172/// Runtime feature detection utilities
173pub mod detection {
174    use super::*;
175
176    /// Detect all available hardware features
177    ///
178    /// This function returns a comprehensive report of all available
179    /// hardware features that can be used for optimization.
180    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    /// Get the best available optimization level for the current platform
198    pub fn best_available_optimization() -> OptimizationLevel {
199        OptimizationLevel::best_available()
200    }
201
202    /// Check if a specific optimization level is available
203    pub fn is_optimization_available(level: OptimizationLevel) -> bool {
204        level.is_available()
205    }
206}
207
208/// Comprehensive feature availability report
209#[derive(Debug, Clone)]
210pub struct FeatureReport {
211    /// x86_64 architecture support
212    pub x86_64: bool,
213    /// AVX2 instruction set support
214    pub avx2: bool,
215    /// AVX-512 instruction set support
216    pub avx512f: bool,
217    /// AArch64 architecture support
218    pub aarch64: bool,
219    /// SHA3 intrinsics support (AArch64)
220    pub sha3_intrinsics: bool,
221    /// SIMD support (nightly feature)
222    pub simd_support: bool,
223    /// Nightly Rust features support
224    pub nightly_features: bool,
225}
226
227impl FeatureReport {
228    /// Get a human-readable summary of available features
229    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    /// Get the recommended optimization level based on available features
250    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}