1use jam_types::{InvokeOutcomeCode, SimpleResult, SimpleResultCode, LOWEST_ERROR};
2
3#[derive(Debug)]
5pub enum ApiError {
6 OutOfBounds,
8 IndexUnknown,
10 StorageFull,
12 BadCore,
14 NoCash,
16 GasLimitTooLow,
19 GasLimitTooHigh,
21 ActionInvalid,
23}
24
25impl From<u64> for ApiError {
26 fn from(code: SimpleResult) -> Self {
27 match code {
28 c if c == SimpleResultCode::OutOfBounds as u64 => ApiError::OutOfBounds,
29 c if c == SimpleResultCode::IndexUnknown as u64 => ApiError::IndexUnknown,
30 c if c == SimpleResultCode::StorageFull as u64 => ApiError::StorageFull,
31 c if c == SimpleResultCode::BadCore as u64 => ApiError::BadCore,
32 c if c == SimpleResultCode::NoCash as u64 => ApiError::NoCash,
33 c if c == SimpleResultCode::GasLimitTooLow as u64 => ApiError::GasLimitTooLow,
34 c if c == SimpleResultCode::GasLimitTooHigh as u64 => ApiError::GasLimitTooHigh,
35 c if c == SimpleResultCode::ActionInvalid as u64 => ApiError::ActionInvalid,
36 _ => panic!("unknown error code: {}", code),
37 }
38 }
39}
40
41pub type ApiResult<T> = Result<T, ApiError>;
43
44pub trait IntoApiResult<T> {
46 fn into_api_result(self) -> ApiResult<T>;
47}
48
49impl IntoApiResult<()> for SimpleResult {
50 fn into_api_result(self) -> ApiResult<()> {
51 if self == SimpleResultCode::Ok as u64 {
52 Ok(())
53 } else {
54 Err(self.into())
55 }
56 }
57}
58impl IntoApiResult<u64> for SimpleResult {
59 fn into_api_result(self) -> ApiResult<u64> {
60 if self < LOWEST_ERROR {
61 Ok(self)
62 } else {
63 Err(self.into())
64 }
65 }
66}
67impl IntoApiResult<u32> for SimpleResult {
68 fn into_api_result(self) -> ApiResult<u32> {
69 if self <= u32::MAX as _ {
70 Ok(self as u32)
71 } else if self < LOWEST_ERROR {
72 panic!("Our own API impl has resulted in success value which is out of range.");
73 } else {
74 Err(self.into())
75 }
76 }
77}
78impl IntoApiResult<Option<()>> for SimpleResult {
79 fn into_api_result(self) -> ApiResult<Option<()>> {
80 if self < LOWEST_ERROR {
81 Ok(Some(()))
82 } else if self == SimpleResultCode::Nothing as u64 {
83 Ok(None)
84 } else {
85 Err(self.into())
86 }
87 }
88}
89impl IntoApiResult<Option<u64>> for SimpleResult {
90 fn into_api_result(self) -> ApiResult<Option<u64>> {
91 if self < LOWEST_ERROR {
92 Ok(Some(self))
93 } else if self == SimpleResultCode::Nothing as u64 {
94 Ok(None)
95 } else {
96 Err(self.into())
97 }
98 }
99}
100
101pub enum InvokeOutcome {
103 Halt,
105 PageFault(u64),
107 HostCallFault(u64),
109 Panic,
111 OutOfGas,
113}
114
115pub type InvokeResult = ApiResult<InvokeOutcome>;
117
118pub trait IntoInvokeResult {
120 fn into_invoke_result(self) -> InvokeResult;
122}
123
124impl IntoInvokeResult for (u64, u64) {
125 fn into_invoke_result(self) -> InvokeResult {
126 const STATUS_HALT: u64 = InvokeOutcomeCode::Halt as u64;
127 const STATUS_PANIC: u64 = InvokeOutcomeCode::Panic as u64;
128 const STATUS_FAULT: u64 = InvokeOutcomeCode::PageFault as u64;
129 const STATUS_HOST: u64 = InvokeOutcomeCode::HostCallFault as u64;
130 const STATUS_OOG: u64 = InvokeOutcomeCode::OutOfGas as u64;
131 match self {
133 (STATUS_HALT, _) => Ok(InvokeOutcome::Halt),
134 (STATUS_FAULT, address) => Ok(InvokeOutcome::PageFault(address)),
135 (STATUS_HOST, index) => Ok(InvokeOutcome::HostCallFault(index)),
136 (STATUS_PANIC, _) => Ok(InvokeOutcome::Panic),
137 (STATUS_OOG, _) => Ok(InvokeOutcome::OutOfGas),
138 (code, _) => Err(code.into()),
139 }
140 }
141}