polkavm/
error.rs

1use polkavm_common::program::ProgramParseError;
2
3macro_rules! bail {
4    ($($arg:expr),* $(,)?) => {
5        return Err(Error::from_display(format_args!($($arg),*)))
6    }
7}
8
9macro_rules! bail_static {
10    ($arg:expr) => {
11        return Err(Error::from_static_str($arg))
12    };
13}
14
15pub(crate) use bail;
16pub(crate) use bail_static;
17
18#[derive(Debug)]
19enum ErrorKind {
20    Owned(String),
21    Static(&'static str),
22    ProgramParseError(ProgramParseError),
23}
24
25#[derive(Debug)]
26#[repr(transparent)]
27pub struct Error(ErrorKind);
28
29impl From<String> for Error {
30    #[cold]
31    fn from(string: String) -> Self {
32        Error(ErrorKind::Owned(string))
33    }
34}
35
36impl From<ProgramParseError> for Error {
37    #[cold]
38    fn from(error: ProgramParseError) -> Self {
39        Self(ErrorKind::ProgramParseError(error))
40    }
41}
42
43impl Error {
44    #[cold]
45    pub(crate) fn from_display(message: impl core::fmt::Display) -> Self {
46        Error(ErrorKind::Owned(message.to_string()))
47    }
48
49    #[cold]
50    pub(crate) fn from_static_str(message: &'static str) -> Self {
51        Error(ErrorKind::Static(message))
52    }
53
54    #[cold]
55    pub(crate) fn from_execution_error<E>(error: ExecutionError<E>) -> Self
56    where
57        E: core::fmt::Display,
58    {
59        match error {
60            ExecutionError::Error(error) => Error::from_display(error),
61            ExecutionError::Trap(_) => Error::from_display("unexpected trap"),
62            ExecutionError::OutOfGas => Error::from_display("unexpected out-of-gas"),
63        }
64    }
65
66    #[cold]
67    pub(crate) fn context(self, message: impl core::fmt::Display) -> Self {
68        let string = match self.0 {
69            ErrorKind::Owned(mut buffer) => {
70                use core::fmt::Write;
71                let _ = write!(&mut buffer, ": {}", message);
72                buffer
73            }
74            error => format!("{}: {}", Error(error), message),
75        };
76
77        Error(ErrorKind::Owned(string))
78    }
79}
80
81impl core::fmt::Display for Error {
82    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
83        let message = match &self.0 {
84            ErrorKind::Owned(message) => message.as_str(),
85            ErrorKind::Static(message) => message,
86            ErrorKind::ProgramParseError(error) => return error.fmt(fmt),
87        };
88
89        fmt.write_str(message)
90    }
91}
92
93impl std::error::Error for Error {}
94
95pub type ExecutionError<T = Error> = polkavm_common::error::ExecutionError<T>;