Skip to main content

kernel_api/detect/
mod.rs

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