1#![no_std]
2
3mod error_code;
4mod extension;
5
6pub use {error_code::*, extension::*};
7use {
8 solana_address::error::AddressError,
9 solana_program_error::{ProgramError, ToStr},
10};
11
12pub struct Error {
13 error: ProgramError,
14 account_name: Option<&'static str>,
15}
16
17impl Error {
18 pub fn new(error: impl Into<ProgramError>) -> Self {
19 Error {
20 error: error.into(),
21 account_name: None,
22 }
23 }
24
25 pub fn with_account(mut self, name: &'static str) -> Self {
26 self.account_name = Some(name);
27 self
28 }
29
30 pub fn account_name(&self) -> Option<&str> {
31 self.account_name
32 }
33
34 pub fn to_str<E>(&self) -> &'static str
35 where
36 E: ToStr + TryFrom<u32> + 'static,
37 {
38 if let ProgramError::Custom(code) = self.error {
39 if (100..200).contains(&code) {
40 return self.error.to_str::<ErrorCode>();
41 }
42 }
43 self.error.to_str::<E>()
44 }
45}
46
47impl From<ProgramError> for Error {
48 fn from(error: ProgramError) -> Self {
49 Error {
50 error,
51 account_name: None,
52 }
53 }
54}
55
56impl From<ErrorCode> for Error {
57 fn from(value: ErrorCode) -> Self {
58 Error {
59 error: value.into(),
60 account_name: None,
61 }
62 }
63}
64
65impl From<Error> for ProgramError {
66 fn from(value: Error) -> Self {
67 value.error
68 }
69}
70
71impl From<AddressError> for Error {
72 fn from(value: AddressError) -> Self {
73 Self {
74 error: value.into(),
75 account_name: None,
76 }
77 }
78}
79
80#[cfg(feature = "logging")]
81pub type LogError = ErrorCode;
82
83#[cfg(feature = "logging")]
84#[cold]
85pub fn log_error<E>(error: &Error)
86where
87 E: ToStr + TryFrom<u32> + 'static,
88{
89 solana_program_log::log(error.to_str::<E>());
90
91 if let Some(account_name) = error.account_name() {
92 let mut logger = solana_program_log::Logger::<50>::default();
93 logger.append("Account origin: ");
94 logger.append(unsafe { str::from_utf8_unchecked(account_name.as_bytes()) });
95 logger.log();
96 }
97}
98
99#[macro_export]
100macro_rules! require {
101 ( $constraint:expr, $error:expr ) => {
102 if pinocchio::hint::unlikely(!$constraint) {
103 return Err($error.into());
104 }
105 };
106}