userspace/macros/enums/
flag.rs

1/// A macro that defines an error type and error handling for syscalls.
2///
3/// This macro generates:
4/// 1. An Error enum with the specified variants and their associated discriminant values
5/// 2. ErrorTrait implementation for the Error type with proper discriminant mapping
6/// 3. An discriminant module with standard Linux error constants
7/// 4. Into<isize> implementation for the Error type
8/// 5. A handle_result function that maps arch errors to syscall errors
9///
10/// # Arguments
11///
12/// * `$enum_identifier` - The name of the error enum (usually Error)
13/// * `$variant` - The variant name in the crate::result::Error enum (e.g., Open, Read, Write)
14/// * `$label` - String slice with the syscall name
15/// * A list of error variants with their descriptions, discriminant values and Linux standard constant names
16///   [VariantName, discriminant_value, "description", "LINUX_CONSTANT"]
17///
18/// # Example
19///
20/// ```
21/// $enum_identifier:ident,
22/// $variant:ty,
23/// $label:expr,
24/// [
25///     $(
26///         [
27///             $discriminant:expr;
28///             $identifier:ident;
29///             $const_identifier:ident;
30///             $acronym:expr;
31///             $description:expr
32///         ]
33///     ),* $(,)?
34/// ]
35/// ```
36#[macro_export]
37#[rustfmt::skip]
38macro_rules! enum_flag {
39    (
40        $enum_identifier:ident,
41        $variant:ty,
42        $label:expr,
43        [
44            $(
45                [
46                    $discriminant:expr;
47                    $identifier:ident;
48                    $const_identifier:ident;
49                    $acronym:expr;
50                    $description:expr
51                ]
52            ),* $(,)?
53        ]
54    ) => {
55        // Define Linux standard error constants in an discriminant module with standard names
56        pub mod constants {
57            $(
58                pub const $const_identifier: $variant = $discriminant;
59            )*
60        }
61
62        #[repr(C)]
63        #[derive(Copy, Clone, Eq, PartialEq)]
64        pub enum $enum_identifier {
65            $($identifier = $discriminant,)*
66            TODO,
67        }
68
69        impl $enum_identifier {
70            pub fn from(discriminant: $variant) -> Self {
71                match discriminant {
72                    $($discriminant => Self::$identifier,)*
73                    _ => Self::TODO,
74                }
75            }
76
77            pub fn to(&self) -> $variant {
78                match *self {
79                    $(Self::$identifier => $discriminant,)*
80                    _ => <$variant>::MAX
81                }
82            }
83
84            pub fn str(&self) -> &str {
85                match self {
86                    $(Self::$identifier => $description,)*
87                    _ => "TODO"
88                }
89            }
90
91            pub fn acronym(&self) -> &str {
92                match *self {
93                    $(Self::$identifier => $acronym,)*
94                    _ => "Unknown error",
95                }
96            }
97        }
98
99
100
101        impl core::ops::BitOr for $enum_identifier {
102            type Output = usize;
103            fn bitor(self, rhs: Self) -> Self::Output {
104                self.to() | rhs.to()
105            }
106        }
107
108        impl core::ops::Add for $enum_identifier {
109            type Output = Self;
110
111            fn add(self, rhs: Self) -> Self::Output {
112                $enum_identifier::from(self.to() | rhs.to())
113            }
114        }
115
116        impl core::ops::Sub for $enum_identifier {
117            type Output = Self;
118
119            fn sub(self, rhs: Self) -> Self::Output {
120                $enum_identifier::from(self.to() & !rhs.to())
121            }
122        }
123
124        impl core::fmt::Display for $enum_identifier {
125            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
126                write!(f, "{}:{}",self.to(), self.str())
127            }
128        }
129
130        impl core::fmt::Debug for $enum_identifier {
131            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
132                write!(f, "{}:{}",self.to(), self.acronym())
133            }
134        }
135    };
136}
137pub use enum_flag;