ab_contracts_common/
error.rs1use derive_more::Display;
2
3#[derive(Debug, Display, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
4pub struct UnknownContractErrorCode(u8);
5
6impl UnknownContractErrorCode {
7 #[inline(always)]
9 pub const fn code(self) -> u8 {
10 self.0
11 }
12}
13
14#[derive(Debug, Display, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
15pub struct CustomContractErrorCode(u64);
16
17impl CustomContractErrorCode {
18 #[inline(always)]
20 pub const fn code(self) -> u64 {
21 self.0
22 }
23}
24
25#[derive(Debug, Display, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
26pub enum ContractError {
27 BadInput,
28 BadOutput,
29 Forbidden,
30 NotFound,
31 Conflict,
32 InternalError,
33 NotImplemented,
34 Unknown(UnknownContractErrorCode),
35 Custom(CustomContractErrorCode),
36}
37
38impl From<CustomContractErrorCode> for ContractError {
39 #[inline(always)]
40 fn from(error: CustomContractErrorCode) -> Self {
41 Self::Custom(error)
42 }
43}
44
45impl ContractError {
46 #[inline(always)]
50 pub const fn new_custom_code(code: u64) -> Option<Self> {
51 if code > u8::MAX as u64 {
52 Some(Self::Custom(CustomContractErrorCode(code)))
53 } else {
54 None
55 }
56 }
57
58 #[inline(always)]
62 pub const fn exit_code(self) -> ExitCode {
63 ExitCode(match self {
64 Self::BadInput => 1,
65 Self::BadOutput => 2,
66 Self::Forbidden => 3,
67 Self::NotFound => 4,
68 Self::Conflict => 5,
69 Self::InternalError => 6,
70 Self::NotImplemented => 7,
71 Self::Unknown(unknown) => unknown.code() as u64,
72 Self::Custom(custom) => custom.code(),
73 })
74 }
75}
76
77#[derive(Debug, Display, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
78#[repr(C)]
79#[must_use = "Code can be Ok or one of the errors, consider converting to Result<(), ContractCode>"]
80pub struct ExitCode(u64);
81
82impl From<ContractError> for ExitCode {
83 #[inline(always)]
84 fn from(error: ContractError) -> Self {
85 error.exit_code()
86 }
87}
88
89impl From<Result<(), ContractError>> for ExitCode {
90 #[inline(always)]
91 fn from(error: Result<(), ContractError>) -> Self {
92 match error {
93 Ok(()) => Self(0),
94 Err(error) => error.exit_code(),
95 }
96 }
97}
98
99impl From<ExitCode> for Result<(), ContractError> {
100 #[inline(always)]
101 fn from(value: ExitCode) -> Self {
102 Err(match value.0 {
103 0 => {
104 return Ok(());
105 }
106 1 => ContractError::BadInput,
107 2 => ContractError::BadOutput,
108 3 => ContractError::Forbidden,
109 4 => ContractError::NotFound,
110 5 => ContractError::Conflict,
111 6 => ContractError::InternalError,
112 7 => ContractError::NotImplemented,
113 8..=255 => ContractError::Unknown(UnknownContractErrorCode(
114 u8::try_from(value.0).expect("All matched values are within `u8` range; qed"),
115 )),
116 code => ContractError::Custom(CustomContractErrorCode(code)),
117 })
118 }
119}
120
121impl ExitCode {
122 #[inline(always)]
124 pub fn ok() -> Self {
125 Self(0)
126 }
127
128 #[inline(always)]
130 pub const fn into_u64(self) -> u64 {
131 self.0
132 }
133}