osiris/
error.rs

1//! Utility functions and definitions for the kernel.
2#![cfg_attr(feature = "nightly", feature(likely_unlikely))]
3
4use core::fmt::Debug;
5use core::fmt::Display;
6use hal::mem::PhysAddr;
7
8/// These two definitions are copied from https://github.com/rust-lang/hashbrown
9#[cfg(not(feature = "nightly"))]
10#[allow(unused_imports)]
11pub(crate) use core::convert::{identity as likely, identity as unlikely};
12
13#[cfg(feature = "nightly")]
14pub(crate) use core::hint::{likely, unlikely};
15
16pub type Result<T> = core::result::Result<T, Error>;
17
18/// This is a macro that is used to panic when a bug is detected.
19/// It is similar to the BUG() macro in the Linux kernel. Link: [https://www.kernel.org/]()
20#[macro_export]
21macro_rules! bug {
22    () => {
23        panic!("BUG at {}:{}", file!(), line!());
24    };
25    ($fmt:literal $(, $arg:expr)* $(,)?) => {{
26        panic!(concat!("BUG at {}:{}: ", $fmt), file!(), line!() $(, $arg)*);
27    }};
28}
29
30#[macro_export]
31macro_rules! warn {
32    () => {
33        kprintln!("WARN at {}:{}", file!(), line!());
34    };
35    ($fmt:literal $(, $arg:expr)* $(,)?) => {{
36        kprintln!(concat!("WARN at {}:{}: ", $fmt), file!(), line!() $(, $arg)*);
37    }};
38}
39
40/// This is a macro that is used to panic when a condition is true.
41/// It is similar to the BUG_ON() macro in the Linux kernel.  Link: [https://www.kernel.org/]()
42macro_rules! bug_on {
43    ($cond:expr) => {{
44        let cond = $cond;
45        #[allow(unused_unsafe)]
46        if unsafe { $crate::error::unlikely(cond) } {
47            panic!("BUG({}) at {}:{}", stringify!($cond), file!(), line!());
48        }
49    }};
50    ($cond:expr, $fmt:literal $(, $arg:expr)* $(,)?) => {{
51        let cond = $cond;
52        #[allow(unused_unsafe)]
53        if unsafe { $crate::error::unlikely(cond) } {
54            panic!(concat!("BUG({}) at {}:{}: ", $fmt), stringify!($cond), file!(), line!() $(, $arg)*);
55        }
56    }};
57}
58
59#[allow(unused_macros)]
60macro_rules! warn_on {
61    ($cond:expr) => {{
62        let cond = $cond;
63        #[allow(unused_unsafe)]
64        if unsafe { $crate::error::unlikely(cond) } {
65            kprintln!("WARN({}) at {}:{}", stringify!($cond), file!(), line!());
66        }
67    }};
68    ($cond:expr, $fmt:literal $(, $arg:expr)* $(,)?) => {{
69        let cond = $cond;
70        #[allow(unused_unsafe)]
71        if unsafe { $crate::error::unlikely(cond) } {
72            kprintln!(concat!("WARN({}) at {}:{}: ", $fmt), stringify!($cond), file!(), line!() $(, $arg)*);
73        }
74    }};
75}
76
77macro_rules! kerr {
78    ($kind:ident) => {
79        $crate::error::Error::new($crate::error::Kind::$kind)
80    };
81    ($kind:expr, $msg:expr) => {
82        use $crate::error::Error;
83        #[cfg(feature = "error-msg")]
84        {
85            Error::new($crate::error::Kind::$kind).with_msg($msg)
86        }
87        #[cfg(not(feature = "error-msg"))]
88        {
89            Error::new($crate::error::Kind::$kind)
90        }
91    };
92}
93
94#[proc_macros::fmt]
95#[allow(dead_code)]
96#[derive(Clone, PartialEq, Eq)]
97pub enum Kind {
98    InvalidAlign,
99    OutOfMemory,
100    InvalidSize,
101    InvalidAddress(PhysAddr),
102    InvalidArgument,
103    NotFound,
104    Hal(hal::Error),
105}
106
107impl Display for Kind {
108    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
109        match self {
110            Kind::InvalidAlign => write!(f, "Invalid alignment"),
111            Kind::OutOfMemory => write!(f, "Out of memory"),
112            Kind::InvalidSize => write!(f, "Invalid size"),
113            Kind::InvalidAddress(addr) => write!(f, "Invalid address: {addr:#x}"),
114            Kind::InvalidArgument => write!(f, "Invalid argument"),
115            Kind::NotFound => write!(f, "Not found"),
116            Kind::Hal(e) => write!(f, "HAL error: {e:?}"),
117        }
118    }
119}
120
121pub struct Error {
122    pub kind: Kind,
123    #[cfg(feature = "error-msg")]
124    msg: Option<&'static str>,
125}
126
127impl Error {
128    pub fn new(kind: Kind) -> Self {
129        #[cfg(feature = "error-msg")]
130        {
131            Self { kind, msg: None }
132        }
133        #[cfg(not(feature = "error-msg"))]
134        {
135            Self { kind }
136        }
137    }
138
139    #[cfg(feature = "error-msg")]
140    pub fn with_msg(mut self, msg: &'static str) -> Self {
141        self.msg = Some(msg);
142        self
143    }
144}
145
146impl Debug for Error {
147    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
148        #[cfg(feature = "error-msg")]
149        {
150            match self.msg {
151                Some(msg) => write!(f, "{}: {}", self.kind, msg),
152                None => write!(f, "{}", self.kind),
153            }
154        }
155        #[cfg(not(feature = "error-msg"))]
156        {
157            write!(f, "{}", self.kind)
158        }
159    }
160}
161
162impl Display for Error {
163    #[cfg(not(feature = "error-msg"))]
164    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
165        write!(f, "{}", self.kind)
166    }
167
168    #[cfg(feature = "error-msg")]
169    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
170        match self.msg {
171            Some(msg) => write!(f, "{}: {}", self.kind, msg),
172            None => write!(f, "{}", self.kind),
173        }
174    }
175}
176
177impl From<hal::Error> for Error {
178    fn from(e: hal::Error) -> Self {
179        Self::new(Kind::Hal(e))
180    }
181}
182
183impl PartialEq for Error {
184    fn eq(&self, other: &Self) -> bool {
185        self.kind == other.kind
186    }
187}