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