1#[cfg(not(feature = "std"))]
2use alloc::string::String;
3
4use crate::std;
5use std::{fmt, result};
6
7use serde::{Deserialize, Serialize};
8
9pub type Result<T> = result::Result<T, Error>;
10pub type JsonRpcResult<T> = result::Result<T, JsonRpcError>;
11
12#[repr(u16)]
14#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
15pub enum HalResult {
16    Success = 0,
17    Failure = 1,
18    LogicFailure = 2,
19    RuntimeFailure = 3,
20    InvalidArgumentFailure = 4,
21    OutOfRangeFailure = 5,
22    NakResponse = 6,
23    IllegalCall = 7,
24    AsyncInterrupted = 8,
25    InsufficientException = 9,
26    TimeOut = 10,
27    ErrorInvalidArguments = 4105,
28    InvalidHandle = 4112,
29    IncompleteArguments = 4113,
30}
31
32impl From<u16> for HalResult {
33    fn from(res: u16) -> Self {
34        match res {
35            0 => Self::Success,
36            1 => Self::Failure,
37            2 => Self::LogicFailure,
38            3 => Self::RuntimeFailure,
39            4 => Self::InvalidArgumentFailure,
40            5 => Self::OutOfRangeFailure,
41            6 => Self::NakResponse,
42            7 => Self::IllegalCall,
43            8 => Self::AsyncInterrupted,
44            9 => Self::InsufficientException,
45            10 => Self::TimeOut,
46            4105 => Self::ErrorInvalidArguments,
47            4112 => Self::InvalidHandle,
48            4113 => Self::IncompleteArguments,
49            _ => Self::Failure,
50        }
51    }
52}
53
54impl From<HalResult> for &'static str {
55    fn from(res: HalResult) -> Self {
56        match res {
57            HalResult::Success => "success",
58            HalResult::Failure => "failure",
59            HalResult::LogicFailure => "logic failure",
60            HalResult::RuntimeFailure => "runtime failure",
61            HalResult::InvalidArgumentFailure => "invalid argument failure",
62            HalResult::OutOfRangeFailure => "out of range failure",
63            HalResult::NakResponse => "NAK response",
64            HalResult::IllegalCall => "illegal call",
65            HalResult::AsyncInterrupted => "async interrupted",
66            HalResult::InsufficientException => "insufficient exception",
67            HalResult::TimeOut => "time out",
68            HalResult::ErrorInvalidArguments => "error invalid arguments",
69            HalResult::InvalidHandle => "invalid handle",
70            HalResult::IncompleteArguments => "incomplete arguments",
71        }
72    }
73}
74
75impl From<&HalResult> for &'static str {
76    fn from(res: &HalResult) -> &'static str {
77        (*res).into()
78    }
79}
80
81impl fmt::Display for HalResult {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        let s = <&'static str>::from(self);
84        let code = (*self) as u16;
85
86        write!(f, "{s}: {code}")
87    }
88}
89
90#[repr(i16)]
92#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
93pub enum HalError {
94    LicenseKeyAuthFailure = -18,
95    BillPresentInEscrow = -15,
96    BillNotPresentInEscrow = -14,
97    BillReject = -13,
98    PrintImageErr = -12,
99    OpenSerialPortFailure = -11,
100    BufferOverflow = -10,
101    DeviceTimeout = -9,
102    LibraryInternalErr = -8,
103    DeviceAlreadyOpen = -7,
104    DeviceNotReady = -6,
105    Cancelled = -5,
106    InvalidData = -3,
107    DeviceBusy = -2,
108    DeviceFailure = -1,
109    RequestFieldInvalid = 1,
110    InternalErr = 2,
111    InternalValidationErr = 3,
112    ComponentNotImplemented = 4,
113    PreconditionFailed = 5,
114    ApplicationTimeout = 6,
115    InvalidDenomination = 7,
116    ApplicationBusy = 8,
117    DeviceCommErr = 9,
118    FirmwareErr = 10,
119    PhysicalTamper = 11,
120    SystemErr = 12,
121    MethodNotImplemented = 13,
122    DecodingErr = 14,
123}
124
125impl From<HalError> for &'static str {
126    fn from(err: HalError) -> Self {
127        match err {
128            HalError::LicenseKeyAuthFailure => "license key auth failure",
129            HalError::BillPresentInEscrow => "bill present in escrow",
130            HalError::BillNotPresentInEscrow => "bill not present in escrow",
131            HalError::BillReject => "bill reject",
132            HalError::PrintImageErr => "print image err",
133            HalError::OpenSerialPortFailure => "open serial port failure",
134            HalError::BufferOverflow => "buffer overflow",
135            HalError::DeviceTimeout => "device timeout",
136            HalError::LibraryInternalErr => "library internal err",
137            HalError::DeviceAlreadyOpen => "device already open",
138            HalError::DeviceNotReady => "device not ready",
139            HalError::Cancelled => "cancelled",
140            HalError::InvalidData => "invalid data",
141            HalError::DeviceBusy => "device busy",
142            HalError::DeviceFailure => "device failure",
143            HalError::RequestFieldInvalid => "request field invalid",
144            HalError::InternalErr => "internal err",
145            HalError::InternalValidationErr => "internal validation err",
146            HalError::ComponentNotImplemented => "component not implemented",
147            HalError::PreconditionFailed => "precondition failed",
148            HalError::ApplicationTimeout => "application timeout",
149            HalError::InvalidDenomination => "invalid denomination",
150            HalError::ApplicationBusy => "application busy",
151            HalError::DeviceCommErr => "device comm err",
152            HalError::FirmwareErr => "firmware err",
153            HalError::PhysicalTamper => "physical tamper",
154            HalError::SystemErr => "system err",
155            HalError::MethodNotImplemented => "method not implemented",
156            HalError::DecodingErr => "decoding err",
157        }
158    }
159}
160
161impl From<&HalError> for &'static str {
162    fn from(err: &HalError) -> Self {
163        (*err).into()
164    }
165}
166
167impl fmt::Display for HalError {
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169        let s: &'static str = self.into();
170        let code = (*self) as i32;
171
172        write!(f, "{s}: {code}")
173    }
174}
175
176#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
177pub enum JsonRpcErrorCode {
178    HalResult(HalResult),
179    HalError(HalError),
180    IoError(String),
181    JsonError(String),
182    SerialError(String),
183    GenericError(i64),
184    Stop,
185}
186
187impl From<HalResult> for JsonRpcErrorCode {
188    fn from(err: HalResult) -> Self {
189        Self::HalResult(err)
190    }
191}
192
193impl From<HalError> for JsonRpcErrorCode {
194    fn from(err: HalError) -> Self {
195        Self::HalError(err)
196    }
197}
198
199#[cfg(feature = "std")]
200impl From<std::io::Error> for JsonRpcErrorCode {
201    fn from(err: std::io::Error) -> Self {
202        Self::IoError(format!("{err}"))
203    }
204}
205
206impl From<serde_json::Error> for JsonRpcErrorCode {
207    fn from(err: serde_json::Error) -> Self {
208        Self::JsonError(format!("{err}"))
209    }
210}
211
212impl From<i64> for JsonRpcErrorCode {
213    fn from(err: i64) -> Self {
214        Self::GenericError(err)
215    }
216}
217
218impl fmt::Display for JsonRpcErrorCode {
219    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220        match self {
221            Self::HalResult(err) => write!(f, "Hal result: {err}"),
222            Self::HalError(err) => write!(f, "Hal error: {err}"),
223            Self::IoError(err) => write!(f, "I/O error: {err}"),
224            Self::JsonError(err) => write!(f, "JSON error: {err}"),
225            Self::SerialError(err) => write!(f, "Serial error: {err}"),
226            Self::GenericError(err) => write!(f, "Generic error: {err}"),
227            Self::Stop => write!(f, "Stop"),
228        }
229    }
230}
231
232#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
234pub struct JsonRpcError {
235    pub(crate) code: JsonRpcErrorCode,
237    pub(crate) message: String,
239}
240
241impl JsonRpcError {
242    pub fn new<C, S>(code: C, message: S) -> Self
244    where
245        C: Into<JsonRpcErrorCode>,
246        S: Into<String>,
247    {
248        Self {
249            code: code.into(),
250            message: message.into(),
251        }
252    }
253
254    pub fn failure<S>(message: S) -> Self
256    where
257        S: Into<String>,
258    {
259        Self::new(-1i64, message)
260    }
261
262    pub fn stop() -> Self {
263        Self::new(JsonRpcErrorCode::Stop, "")
264    }
265
266    pub fn code(&self) -> &JsonRpcErrorCode {
268        &self.code
269    }
270
271    pub fn set_code<C>(&mut self, code: C)
273    where
274        C: Into<JsonRpcErrorCode>,
275    {
276        self.code = code.into();
277    }
278
279    pub fn message(&self) -> &str {
281        &self.message
282    }
283
284    pub fn set_message<S>(&mut self, message: S)
286    where
287        S: Into<String>,
288    {
289        self.message = message.into();
290    }
291}
292
293impl fmt::Display for JsonRpcError {
294    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295        write!(f, "code[{}]: {}", self.code, self.message)
296    }
297}
298
299impl From<HalResult> for JsonRpcError {
300    fn from(res: HalResult) -> Self {
301        match res {
302            HalResult::Success => Self {
303                code: res.into(),
304                message: String::new(),
305            },
306            HalResult::InvalidHandle => Self {
307                code: HalError::PreconditionFailed.into(),
308                message: "Device handle is invalid".into(),
309            },
310            HalResult::ErrorInvalidArguments => Self {
311                code: HalError::InternalValidationErr.into(),
312                message: "One of the passed arguments is NULL".into(),
313            },
314            HalResult::IncompleteArguments => Self {
315                code: HalError::InternalValidationErr.into(),
316                message: "One of the passed arguments is incomplete (wrong length)".into(),
317            },
318            hal_result => Self {
319                code: hal_result.into(),
320                message: String::new(),
321            },
322        }
323    }
324}
325
326#[cfg(feature = "std")]
327impl From<JsonRpcError> for std::io::Error {
328    fn from(err: JsonRpcError) -> Self {
329        Self::new(std::io::ErrorKind::Other, format!("{err}"))
330    }
331}
332
333#[cfg(feature = "std")]
334impl From<std::io::Error> for JsonRpcError {
335    fn from(err: std::io::Error) -> Self {
336        Self {
337            code: err.into(),
338            message: String::new(),
339        }
340    }
341}
342
343impl From<serde_json::Error> for JsonRpcError {
344    fn from(err: serde_json::Error) -> Self {
345        Self {
346            code: err.into(),
347            message: String::new(),
348        }
349    }
350}
351
352impl From<std::str::Utf8Error> for JsonRpcError {
353    fn from(err: std::str::Utf8Error) -> Self {
354        Self::failure(format!("{err}"))
355    }
356}
357
358#[repr(C)]
360#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
361pub struct Error {
362    code: ErrorCode,
363    message: String,
364}
365
366impl Error {
367    pub fn failure<S>(message: S) -> Self
369    where
370        S: Into<String>,
371    {
372        Self {
373            code: ErrorCode::Failure,
374            message: message.into(),
375        }
376    }
377
378    pub fn serial<S>(message: S) -> Self
380    where
381        S: Into<String>,
382    {
383        Self {
384            code: ErrorCode::SerialPort,
385            message: message.into(),
386        }
387    }
388
389    pub fn json_rpc<S>(message: S) -> Self
391    where
392        S: Into<String>,
393    {
394        Self {
395            code: ErrorCode::JsonRpc,
396            message: message.into(),
397        }
398    }
399
400    pub fn code(&self) -> ErrorCode {
402        self.code
403    }
404
405    pub fn message(&self) -> &str {
407        self.message.as_str()
408    }
409}
410
411impl fmt::Display for Error {
412    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
413        write!(f, "code: {}, message: {}", self.code, self.message)
414    }
415}
416
417#[cfg(feature = "std")]
418impl From<std::io::Error> for Error {
419    fn from(err: std::io::Error) -> Self {
420        Self {
421            code: ErrorCode::Failure,
422            message: format!("I/O error: {}", err),
423        }
424    }
425}
426
427impl From<std::str::Utf8Error> for Error {
428    fn from(err: std::str::Utf8Error) -> Self {
429        Self {
430            code: ErrorCode::Failure,
431            message: format!("Utf8 error: {}", err),
432        }
433    }
434}
435
436impl From<serialport::Error> for Error {
437    fn from(err: serialport::Error) -> Self {
438        Self {
439            code: ErrorCode::SerialPort,
440            message: format!("Serial port error: {err}"),
441        }
442    }
443}
444
445#[cfg(feature = "std")]
446impl<T> From<std::sync::mpsc::SendError<T>> for Error {
447    fn from(err: std::sync::mpsc::SendError<T>) -> Self {
448        Self::failure(format!("failed to send an item to the queue: {err}"))
449    }
450}
451
452impl From<&Error> for JsonRpcError {
453    fn from(err: &Error) -> Self {
454        Self::new(err.code(), err.message())
455    }
456}
457
458impl From<Error> for JsonRpcError {
459    fn from(err: Error) -> Self {
460        Self::from(&err)
461    }
462}
463
464impl From<JsonRpcError> for Error {
465    fn from(err: JsonRpcError) -> Self {
466        Self::from(&err)
467    }
468}
469
470impl From<&JsonRpcError> for Error {
471    fn from(err: &JsonRpcError) -> Self {
472        Self::json_rpc(format!("code[{}]: {}", err.code(), err.message()))
473    }
474}
475
476#[repr(C)]
478#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
479pub enum ErrorCode {
481    Failure = -1,
483    SerialPort = -2,
485    JsonRpc = -3,
487}
488
489impl From<ErrorCode> for &'static str {
490    fn from(e: ErrorCode) -> Self {
491        match e {
492            ErrorCode::Failure => "failure",
493            ErrorCode::SerialPort => "serial port",
494            ErrorCode::JsonRpc => "JSON-RPC",
495        }
496    }
497}
498
499impl From<&ErrorCode> for &'static str {
500    fn from(e: &ErrorCode) -> Self {
501        (*e).into()
502    }
503}
504
505impl From<ErrorCode> for JsonRpcErrorCode {
506    fn from(e: ErrorCode) -> Self {
507        JsonRpcErrorCode::SerialError(format!("{e}"))
508    }
509}
510
511impl From<&ErrorCode> for JsonRpcErrorCode {
512    fn from(e: &ErrorCode) -> Self {
513        (*e).into()
514    }
515}
516
517impl From<JsonRpcErrorCode> for ErrorCode {
518    fn from(_e: JsonRpcErrorCode) -> Self {
519        Self::JsonRpc
520    }
521}
522
523impl From<&JsonRpcErrorCode> for ErrorCode {
524    fn from(_e: &JsonRpcErrorCode) -> Self {
525        Self::JsonRpc
526    }
527}
528
529impl fmt::Display for ErrorCode {
530    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
531        write!(f, "{}", <&str>::from(self))
532    }
533}