Skip to main content

kernel_api/detect/
mod.rs

1//! Provides system feature detection
2
3#[cfg(target_arch = "x86_64")]
4mod x86;
5
6#[cfg(target_arch = "x86_64")]
7#[doc(hidden)]
8pub use x86::*;
9
10mod cache;
11
12macro_rules! features_macro {
13    (
14        @TARGET: $target:ident;
15        @CFG: $cfg:meta;
16        @MACRO_NAME: $macro_name:ident;
17        @MACRO_ATTRS: $(#[$macro_attrs:meta])*
18        $(@BIND_FEATURE_NAME: $bind_feature:tt; $feature_impl:tt;)*
19        $(@FEATURE: $feature:ident: $feature_lit:tt: $feature_doc:tt;)*
20    ) => {
21        #[macro_export]
22        $(#[$macro_attrs])*
23        #[doc = "Returns a bool if the current system supports the requested feature"]
24        #[doc = "\n\nThe features available to test are:"]
25        $(#[doc = concat!("- `", $feature_lit, "` - ", $feature_doc, "\n")])*
26        macro_rules! $macro_name {
27            $(
28                ($feature_lit) => {
29                    $crate::detect::__detected::$feature()
30                };
31            )*
32            $(
33                ($bind_feature) => {
34                    $crate::detect::__detected::$feature_impl()
35                };
36            )*
37            ($t:tt,) => {
38                    $crate::$macro_name!($t);
39            };
40            ($t:tt) => {
41                compile_error!(
42                    concat!(
43                        concat!("unknown ", stringify!($target)),
44                        concat!(" target feature: ", $t)
45                    )
46                )
47            };
48        }
49
50        #[doc(hidden)]
51        #[allow(non_camel_case_types)]
52        #[derive(Copy, Clone, Debug)]
53        #[repr(u32)]
54        #[cfg($cfg)]
55        pub enum Feature {
56            $(
57                $feature,
58            )*
59            _last
60        }
61
62        #[cfg($cfg)]
63        impl Feature {
64            pub(crate) fn to_str(self) -> &'static str {
65                match self {
66                    $(Feature::$feature => $feature_lit,)*
67                    Feature::_last => unreachable!(),
68                }
69            }
70        }
71
72        #[doc(hidden)]
73        #[cfg($cfg)]
74        pub mod __detected {
75            $(
76                #[inline]
77                #[doc(hidden)]
78                pub fn $feature() -> bool {
79                    $crate::detect::cache::test($crate::detect::Feature::$feature)
80                }
81            )*
82        }
83    };
84}
85
86pub(crate) use features_macro;
87
88/// Returns an iterator over feature names and their support on the current system
89pub fn features() -> impl Iterator<Item = (&'static str, bool)> {
90    (0_u32..Feature::_last as u32).map(|discriminant: u32| {
91        let f: Feature = unsafe { core::mem::transmute(discriminant) };
92        let name: &'static str = f.to_str();
93        let enabled: bool = cache::test(f);
94        (name, enabled)
95    })
96}