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;