polkavm/
error.rs

1use alloc::string::{String, ToString};
2use polkavm_common::program::ProgramParseError;
3
4macro_rules! bail {
5    ($($arg:expr),* $(,)?) => {
6        return Err(Error::from_display(format_args!($($arg),*)))
7    }
8}
9
10macro_rules! bail_static {
11    ($arg:expr) => {
12        return Err(Error::from_static_str($arg))
13    };
14}
15
16pub(crate) use bail;
17pub(crate) use bail_static;
18
19#[derive(Debug)]
20enum ErrorKind {
21    Owned(String),
22    Static(&'static str),
23    ProgramParseError(ProgramParseError),
24}
25
26#[derive(Debug)]
27#[repr(transparent)]
28pub struct Error(ErrorKind);
29
30impl From<&'static str> for Error {
31    #[cold]
32    fn from(message: &'static str) -> Self {
33        Error(ErrorKind::Static(message))
34    }
35}
36
37impl From<String> for Error {
38    #[cold]
39    fn from(string: String) -> Self {
40        Error(ErrorKind::Owned(string))
41    }
42}
43
44impl From<ProgramParseError> for Error {
45    #[cold]
46    fn from(error: ProgramParseError) -> Self {
47        Self(ErrorKind::ProgramParseError(error))
48    }
49}
50
51if_compiler_is_supported! {
52    #[cfg(target_os = "linux")]
53    impl From<polkavm_linux_raw::Error> for Error {
54        #[cold]
55        fn from(error: polkavm_linux_raw::Error) -> Self {
56            Self(ErrorKind::Owned(error.to_string()))
57        }
58    }
59
60    #[cfg(feature = "generic-sandbox")]
61    use crate::sandbox::generic;
62
63    #[cfg(feature = "generic-sandbox")]
64    impl From<generic::Error> for Error {
65        #[cold]
66        fn from(error: generic::Error) -> Self {
67            Self(ErrorKind::Owned(error.to_string()))
68        }
69    }
70}
71
72impl Error {
73    #[cold]
74    pub(crate) fn from_display(message: impl core::fmt::Display) -> Self {
75        Error(ErrorKind::Owned(message.to_string()))
76    }
77
78    #[cold]
79    pub(crate) fn from_static_str(message: &'static str) -> Self {
80        Error(ErrorKind::Static(message))
81    }
82}
83
84if_compiler_is_supported! {
85    impl Error {
86        #[cold]
87        pub(crate) fn context(self, message: impl core::fmt::Display) -> Self {
88            use alloc::format;
89
90            let string = match self.0 {
91                ErrorKind::Owned(buffer) => format!("{}: {}", message, buffer),
92                error => format!("{}: {}", message, Error(error)),
93            };
94
95            Error(ErrorKind::Owned(string))
96        }
97    }
98}
99
100impl core::fmt::Display for Error {
101    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
102        let message = match &self.0 {
103            ErrorKind::Owned(message) => message.as_str(),
104            ErrorKind::Static(message) => message,
105            ErrorKind::ProgramParseError(error) => return error.fmt(fmt),
106        };
107
108        fmt.write_str(message)
109    }
110}
111
112impl core::error::Error for Error {}
113
114impl From<Error> for String {
115    fn from(error: Error) -> String {
116        error.to_string()
117    }
118}