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}