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>;