1use std::collections::HashMap;
7
8pub struct Features;
10
11impl Features {
12 pub const fn has_std() -> bool {
14 cfg!(feature = "std")
15 }
16
17 pub const fn has_no_std() -> bool {
19 cfg!(feature = "no_std")
20 }
21
22 pub const fn has_serde() -> bool {
24 cfg!(feature = "serde")
25 }
26
27 pub const fn has_binary() -> bool {
29 cfg!(feature = "binary")
30 }
31
32 pub const fn has_arrow() -> bool {
34 cfg!(feature = "arrow")
35 }
36
37 pub const fn has_simd() -> bool {
39 cfg!(feature = "simd")
40 }
41
42 pub const fn has_parallel() -> bool {
44 cfg!(feature = "parallel")
45 }
46
47 pub const fn has_mmap() -> bool {
49 cfg!(feature = "mmap")
50 }
51
52 pub const fn has_async() -> bool {
54 cfg!(feature = "async_support")
55 }
56
57 pub const fn has_streaming() -> bool {
59 cfg!(feature = "streaming")
60 }
61
62 pub const fn has_gpu() -> bool {
64 cfg!(feature = "gpu_support")
65 }
66
67 pub const fn has_distributed() -> bool {
69 cfg!(feature = "distributed")
70 }
71
72 pub const fn has_linear_models() -> bool {
74 cfg!(feature = "linear_models")
75 }
76
77 pub const fn has_tree_models() -> bool {
78 cfg!(feature = "tree_models")
79 }
80
81 pub const fn has_neural_networks() -> bool {
82 cfg!(feature = "neural_networks")
83 }
84
85 pub const fn has_clustering() -> bool {
86 cfg!(feature = "clustering")
87 }
88
89 pub const fn has_dimensionality_reduction() -> bool {
90 cfg!(feature = "dimensionality_reduction")
91 }
92
93 pub const fn has_ensemble_methods() -> bool {
94 cfg!(feature = "ensemble_methods")
95 }
96
97 pub const fn has_validation() -> bool {
99 cfg!(feature = "validation")
100 }
101
102 pub const fn has_metrics() -> bool {
103 cfg!(feature = "metrics")
104 }
105
106 pub const fn has_preprocessing() -> bool {
107 cfg!(feature = "preprocessing")
108 }
109
110 pub const fn has_model_selection() -> bool {
111 cfg!(feature = "model_selection")
112 }
113
114 pub const fn has_debug_assertions() -> bool {
116 cfg!(feature = "debug_assertions")
117 }
118
119 pub const fn has_profiling() -> bool {
120 cfg!(feature = "profiling")
121 }
122
123 pub const fn has_benchmarking() -> bool {
124 false
126 }
127
128 pub fn enabled_features() -> HashMap<&'static str, bool> {
130 let mut features = HashMap::new();
131
132 features.insert("std", Self::has_std());
134 features.insert("no_std", Self::has_no_std());
135
136 features.insert("serde", Self::has_serde());
138 features.insert("binary", Self::has_binary());
139
140 features.insert("arrow", Self::has_arrow());
142
143 features.insert("simd", Self::has_simd());
145 features.insert("parallel", Self::has_parallel());
146 features.insert("mmap", Self::has_mmap());
147
148 features.insert("linear_models", Self::has_linear_models());
150 features.insert("tree_models", Self::has_tree_models());
151 features.insert("neural_networks", Self::has_neural_networks());
152 features.insert("clustering", Self::has_clustering());
153 features.insert(
154 "dimensionality_reduction",
155 Self::has_dimensionality_reduction(),
156 );
157 features.insert("ensemble_methods", Self::has_ensemble_methods());
158
159 features.insert("async_support", Self::has_async());
161 features.insert("streaming", Self::has_streaming());
162 features.insert("gpu_support", Self::has_gpu());
163 features.insert("distributed", Self::has_distributed());
164
165 features.insert("validation", Self::has_validation());
167 features.insert("metrics", Self::has_metrics());
168 features.insert("preprocessing", Self::has_preprocessing());
169 features.insert("model_selection", Self::has_model_selection());
170
171 features.insert("debug_assertions", Self::has_debug_assertions());
173 features.insert("profiling", Self::has_profiling());
174 features.insert("benchmarking", Self::has_benchmarking());
175
176 features
177 }
178
179 pub fn print_enabled_features() {
181 println!("Enabled features:");
182 for (feature, enabled) in Self::enabled_features() {
183 if enabled {
184 println!(" - {feature}");
185 }
186 }
187 }
188
189 pub fn feature_summary() -> FeatureSummary {
191 FeatureSummary {
192 core: CoreFeatures {
193 std: Self::has_std(),
194 no_std: Self::has_no_std(),
195 },
196 serialization: SerializationFeatures {
197 serde: Self::has_serde(),
198 binary: Self::has_binary(),
199 },
200 data_formats: DataFormatFeatures {
201 arrow: Self::has_arrow(),
202 },
203 performance: PerformanceFeatures {
204 simd: Self::has_simd(),
205 parallel: Self::has_parallel(),
206 mmap: Self::has_mmap(),
207 },
208 algorithms: AlgorithmFeatures {
209 linear_models: Self::has_linear_models(),
210 tree_models: Self::has_tree_models(),
211 neural_networks: Self::has_neural_networks(),
212 clustering: Self::has_clustering(),
213 dimensionality_reduction: Self::has_dimensionality_reduction(),
214 ensemble_methods: Self::has_ensemble_methods(),
215 },
216 advanced: AdvancedFeatures {
217 async_support: Self::has_async(),
218 streaming: Self::has_streaming(),
219 gpu_support: Self::has_gpu(),
220 distributed: Self::has_distributed(),
221 },
222 utilities: UtilityFeatures {
223 validation: Self::has_validation(),
224 metrics: Self::has_metrics(),
225 preprocessing: Self::has_preprocessing(),
226 model_selection: Self::has_model_selection(),
227 },
228 development: DevelopmentFeatures {
229 debug_assertions: Self::has_debug_assertions(),
230 profiling: Self::has_profiling(),
231 benchmarking: Self::has_benchmarking(),
232 },
233 }
234 }
235}
236
237#[derive(Debug, Clone)]
239pub struct FeatureSummary {
240 pub core: CoreFeatures,
241 pub serialization: SerializationFeatures,
242 pub data_formats: DataFormatFeatures,
243 pub performance: PerformanceFeatures,
244 pub algorithms: AlgorithmFeatures,
245 pub advanced: AdvancedFeatures,
246 pub utilities: UtilityFeatures,
247 pub development: DevelopmentFeatures,
248}
249
250#[derive(Debug, Clone)]
252pub struct CoreFeatures {
253 pub std: bool,
254 pub no_std: bool,
255}
256
257#[derive(Debug, Clone)]
259pub struct SerializationFeatures {
260 pub serde: bool,
261 pub binary: bool,
262}
263
264#[derive(Debug, Clone)]
266pub struct DataFormatFeatures {
267 pub arrow: bool,
268}
269
270#[derive(Debug, Clone)]
272pub struct PerformanceFeatures {
273 pub simd: bool,
274 pub parallel: bool,
275 pub mmap: bool,
276}
277
278#[derive(Debug, Clone)]
280pub struct AlgorithmFeatures {
281 pub linear_models: bool,
282 pub tree_models: bool,
283 pub neural_networks: bool,
284 pub clustering: bool,
285 pub dimensionality_reduction: bool,
286 pub ensemble_methods: bool,
287}
288
289impl AlgorithmFeatures {
290 pub fn any_enabled(&self) -> bool {
292 self.linear_models
293 || self.tree_models
294 || self.neural_networks
295 || self.clustering
296 || self.dimensionality_reduction
297 || self.ensemble_methods
298 }
299
300 pub fn count_enabled(&self) -> usize {
302 [
303 self.linear_models,
304 self.tree_models,
305 self.neural_networks,
306 self.clustering,
307 self.dimensionality_reduction,
308 self.ensemble_methods,
309 ]
310 .iter()
311 .filter(|&&enabled| enabled)
312 .count()
313 }
314
315 pub fn enabled_categories(&self) -> Vec<&'static str> {
317 let mut categories = Vec::new();
318 if self.linear_models {
319 categories.push("linear_models");
320 }
321 if self.tree_models {
322 categories.push("tree_models");
323 }
324 if self.neural_networks {
325 categories.push("neural_networks");
326 }
327 if self.clustering {
328 categories.push("clustering");
329 }
330 if self.dimensionality_reduction {
331 categories.push("dimensionality_reduction");
332 }
333 if self.ensemble_methods {
334 categories.push("ensemble_methods");
335 }
336 categories
337 }
338}
339
340#[derive(Debug, Clone)]
342pub struct AdvancedFeatures {
343 pub async_support: bool,
344 pub streaming: bool,
345 pub gpu_support: bool,
346 pub distributed: bool,
347}
348
349#[derive(Debug, Clone)]
351pub struct UtilityFeatures {
352 pub validation: bool,
353 pub metrics: bool,
354 pub preprocessing: bool,
355 pub model_selection: bool,
356}
357
358#[derive(Debug, Clone)]
360pub struct DevelopmentFeatures {
361 pub debug_assertions: bool,
362 pub profiling: bool,
363 pub benchmarking: bool,
364}
365
366pub mod validation {
368 use super::Features;
369
370 pub const fn validate_features() -> Result<(), &'static str> {
372 if Features::has_std() && Features::has_no_std() {
376 }
379
380 if Features::has_binary() && !Features::has_serde() {
383 return Err("'binary' feature requires 'serde' feature");
384 }
385
386 if Features::has_streaming() && !Features::has_async() {
389 return Err("'streaming' feature requires 'async_support' feature");
390 }
391
392 if Features::has_distributed() && !Features::has_async() {
393 return Err("'distributed' feature requires 'async_support' feature");
394 }
395
396 if !Features::has_std() && !Features::has_no_std() {
398 }
401
402 Ok(())
403 }
404
405 pub const fn assert_valid_features() {
407 match validate_features() {
408 Ok(()) => {}
409 Err(_) => panic!("Invalid feature combination detected"),
410 }
411 }
412}
413
414pub struct FeatureConfig {
416 enabled_features: HashMap<String, bool>,
417}
418
419impl FeatureConfig {
420 pub fn from_compile_time() -> Self {
422 let enabled = Features::enabled_features()
423 .into_iter()
424 .map(|(k, v)| (k.to_string(), v))
425 .collect();
426
427 Self {
428 enabled_features: enabled,
429 }
430 }
431
432 pub fn is_enabled(&self, feature: &str) -> bool {
434 self.enabled_features.get(feature).copied().unwrap_or(false)
435 }
436
437 pub fn enabled_features(&self) -> Vec<&str> {
439 self.enabled_features
440 .iter()
441 .filter_map(|(k, &v)| if v { Some(k.as_str()) } else { None })
442 .collect()
443 }
444
445 #[cfg(feature = "serde")]
447 pub fn to_json(&self) -> Result<String, serde_json::Error> {
448 serde_json::to_string_pretty(&self.enabled_features)
449 }
450
451 #[cfg(feature = "serde")]
453 pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
454 let enabled_features = serde_json::from_str(json)?;
455 Ok(Self { enabled_features })
456 }
457}
458
459#[macro_export]
461macro_rules! cfg_feature {
462 ($feature:literal, $code:block) => {
463 #[cfg(feature = $feature)]
464 $code
465 };
466 ($feature:literal, $code:block, else $else_code:block) => {
467 #[cfg(feature = $feature)]
468 $code
469 #[cfg(not(feature = $feature))]
470 $else_code
471 };
472}
473
474#[macro_export]
476macro_rules! cfg_type {
477 ($feature:literal, $type_def:item) => {
478 #[cfg(feature = $feature)]
479 $type_def
480 };
481}
482
483#[macro_export]
485macro_rules! cfg_impl {
486 ($feature:literal, impl $trait_name:ident for $type:ty { $($item:item)* }) => {
487 #[cfg(feature = $feature)]
488 impl $trait_name for $type {
489 $($item)*
490 }
491 };
492}
493
494#[allow(non_snake_case)]
495#[cfg(test)]
496mod tests {
497 use super::*;
498
499 #[test]
500 fn test_feature_detection() {
501 let summary = Features::feature_summary();
503
504 assert!(summary.core.std || summary.core.no_std);
506
507 Features::print_enabled_features();
509 }
510
511 #[test]
512 fn test_feature_config() {
513 let config = FeatureConfig::from_compile_time();
514
515 assert!(!config.enabled_features().is_empty());
517
518 let has_std = config.is_enabled("std");
520 assert_eq!(has_std, Features::has_std());
521 }
522
523 #[test]
524 fn test_algorithm_features() {
525 let algo_features = Features::feature_summary().algorithms;
526
527 let count = algo_features.count_enabled();
529 let categories = algo_features.enabled_categories();
530
531 assert_eq!(count, categories.len());
532 }
533
534 #[test]
535 fn test_feature_validation() {
536 validation::assert_valid_features();
538
539 assert!(validation::validate_features().is_ok());
541 }
542
543 #[cfg(feature = "serde")]
544 #[test]
545 fn test_feature_serialization() {
546 let config = FeatureConfig::from_compile_time();
547
548 let json = config.to_json().unwrap_or_default();
550 assert!(!json.is_empty());
551
552 let config2 = FeatureConfig::from_json(&json).expect("valid JSON");
554 assert_eq!(
555 config.enabled_features().len(),
556 config2.enabled_features().len()
557 );
558 }
559
560 #[test]
561 fn test_feature_macros() {
562 cfg_feature!("std", {
564 println!("std feature is enabled");
565 });
566
567 cfg_feature!("gpu_support", {
569 println!("gpu_support feature is enabled");
570 }, else {
571 println!("gpu_support is not enabled (expected in most builds)");
572 });
573 }
574}