typhoon_errors/
lib.rs

1#![no_std]
2
3mod error_code;
4mod extension;
5
6use pinocchio::program_error::{ProgramError, ToStr};
7pub use {error_code::*, extension::*};
8
9pub struct Error {
10    error: ProgramError,
11    account_name: Option<&'static str>,
12}
13
14impl Error {
15    pub fn new(error: impl Into<ProgramError>) -> Self {
16        Error {
17            error: error.into(),
18            account_name: None,
19        }
20    }
21
22    pub fn with_account(mut self, name: &'static str) -> Self {
23        self.account_name = Some(name);
24        self
25    }
26
27    pub fn account_name(&self) -> Option<&str> {
28        self.account_name
29    }
30}
31
32impl ToStr for Error {
33    fn to_str<E>(&self) -> &'static str
34    where
35        E: 'static + ToStr + TryFrom<u32>,
36    {
37        if let ProgramError::Custom(code) = self.error {
38            if (100..200).contains(&code) {
39                return self.error.to_str::<ErrorCode>();
40            }
41        }
42        self.error.to_str::<E>()
43    }
44}
45
46impl From<ProgramError> for Error {
47    fn from(error: ProgramError) -> Self {
48        Error {
49            error,
50            account_name: None,
51        }
52    }
53}
54
55impl From<ErrorCode> for Error {
56    fn from(value: ErrorCode) -> Self {
57        Error {
58            error: value.into(),
59            account_name: None,
60        }
61    }
62}
63
64impl From<Error> for ProgramError {
65    fn from(value: Error) -> Self {
66        value.error
67    }
68}
69
70#[macro_export]
71macro_rules! impl_error_logger {
72    ($error:ident) => {
73        #[cfg(feature = "logging")]
74        #[cold]
75        fn log_error(error: &Error) {
76            pinocchio::log::sol_log(error.to_str::<$error>());
77            if let Some(account_name) = error.account_name() {
78                let mut buffer = [bytes::UNINIT_BYTE; 50];
79                let total_len = account_name.len() + 16;
80                bytes::write_bytes(&mut buffer[..16], b"Account origin: ");
81                bytes::write_bytes(&mut buffer[16..total_len], account_name.as_bytes());
82                pinocchio::log::sol_log(unsafe {
83                    core::str::from_utf8_unchecked(core::slice::from_raw_parts(
84                        buffer.as_ptr() as _,
85                        total_len,
86                    ))
87                });
88            }
89        }
90    };
91}