jcm/
failure_code.rs

1use std::fmt;
2
3use crate::{Error, Result};
4
5const TRANSPORT_MOTOR: u8 = 0x11;
6const STACK_MOTOR: u8 = 0x12;
7const ANTI_STRINGING_MECHANISM: u8 = 0x13;
8const SENSOR: u8 = 0x14;
9const ACCEPTOR_HARDWARE: u8 = 0x1f;
10const RECYCLER_MOTOR: u8 = 0x22;
11const RECYCLER_SENSOR: u8 = 0x24;
12const RECYCLER_HARDWARE: u8 = 0x2f;
13const ROM: u8 = 0xb1;
14const RAM: u8 = 0xb2;
15const COMMUNICATION: u8 = 0xb5;
16const ABNORMAL: u8 = 0xb6;
17const RESERVED: u8 = 0xff;
18
19/// Represents JCM device failure codes.
20#[repr(u8)]
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
22pub enum FailureCode {
23    TransportMotor = TRANSPORT_MOTOR,
24    StackMotor = STACK_MOTOR,
25    AntiStringingMechanism = ANTI_STRINGING_MECHANISM,
26    Sensor = SENSOR,
27    AcceptorHardware = ACCEPTOR_HARDWARE,
28    RecyclerMotor = RECYCLER_MOTOR,
29    RecyclerSensor = RECYCLER_SENSOR,
30    RecyclyHardware = RECYCLER_HARDWARE,
31    Rom = ROM,
32    Ram = RAM,
33    Communication = COMMUNICATION,
34    Abnormal = ABNORMAL,
35    Reserved = RESERVED,
36}
37
38impl FailureCode {
39    /// Creates a new [FailureCode].
40    pub const fn new() -> Self {
41        Self::TransportMotor
42    }
43
44    /// Infallible conversion from a [`u8`] into a [FailureCode].
45    pub const fn from_u8(val: u8) -> Self {
46        match val {
47            TRANSPORT_MOTOR => Self::TransportMotor,
48            STACK_MOTOR => Self::StackMotor,
49            ANTI_STRINGING_MECHANISM => Self::AntiStringingMechanism,
50            SENSOR => Self::Sensor,
51            ACCEPTOR_HARDWARE => Self::AcceptorHardware,
52            RECYCLER_MOTOR => Self::RecyclerMotor,
53            RECYCLER_SENSOR => Self::RecyclerSensor,
54            RECYCLER_HARDWARE => Self::RecyclyHardware,
55            ROM => Self::Rom,
56            RAM => Self::Ram,
57            COMMUNICATION => Self::Communication,
58            ABNORMAL => Self::Abnormal,
59            _ => Self::Reserved,
60        }
61    }
62}
63
64impl Default for FailureCode {
65    fn default() -> Self {
66        Self::new()
67    }
68}
69
70impl From<&FailureCode> for &'static str {
71    fn from(val: &FailureCode) -> Self {
72        match val {
73            FailureCode::TransportMotor => "transport motor related error",
74            FailureCode::StackMotor => "stack motor related error",
75            FailureCode::AntiStringingMechanism => "anti-stringing mechanism error",
76            FailureCode::Sensor => "sensor adjustment related error",
77            FailureCode::AcceptorHardware => "acceptor hardware related error",
78            FailureCode::RecyclerMotor => "recycler motor related error",
79            FailureCode::RecyclerSensor => "recycler sensor adjustement related error",
80            FailureCode::RecyclyHardware => "recycler hardware related error",
81            FailureCode::Rom => "ROM error",
82            FailureCode::Ram => "RAM error",
83            FailureCode::Communication => "communication failure (no response to message)",
84            FailureCode::Abnormal => "abnormal operation sequences (interruption due to communication error or function error due to unconfigured settings)",
85            FailureCode::Reserved => "reserved",
86        }
87    }
88}
89
90impl From<FailureCode> for &'static str {
91    fn from(val: FailureCode) -> Self {
92        (&val).into()
93    }
94}
95
96impl TryFrom<u8> for FailureCode {
97    type Error = Error;
98
99    fn try_from(val: u8) -> Result<Self> {
100        match Self::from_u8(val) {
101            Self::Reserved => Err(Error::InvalidFailureCode(val)),
102            code => Ok(code),
103        }
104    }
105}
106
107impl fmt::Display for FailureCode {
108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109        write!(f, r#""{}""#, <&str>::from(self))
110    }
111}
112
113#[cfg(test)]
114mod tests {
115    use super::*;
116
117    #[test]
118    fn test_failure_code() {
119        let raw_denom = [
120            TRANSPORT_MOTOR,
121            STACK_MOTOR,
122            ANTI_STRINGING_MECHANISM,
123            SENSOR,
124            ACCEPTOR_HARDWARE,
125            RECYCLER_MOTOR,
126            RECYCLER_SENSOR,
127            RECYCLER_HARDWARE,
128            ROM,
129            RAM,
130            COMMUNICATION,
131            ABNORMAL,
132        ];
133        let expected = [
134            FailureCode::TransportMotor,
135            FailureCode::StackMotor,
136            FailureCode::AntiStringingMechanism,
137            FailureCode::Sensor,
138            FailureCode::AcceptorHardware,
139            FailureCode::RecyclerMotor,
140            FailureCode::RecyclerSensor,
141            FailureCode::RecyclyHardware,
142            FailureCode::Rom,
143            FailureCode::Ram,
144            FailureCode::Communication,
145            FailureCode::Abnormal,
146        ];
147
148        for (raw, exp) in raw_denom.into_iter().zip(expected.into_iter()) {
149            assert_eq!(FailureCode::try_from(raw), Ok(exp));
150            assert_eq!(FailureCode::from_u8(raw), exp);
151        }
152
153        for stat in (0..=255u8).filter(|s| !raw_denom.iter().any(|d| d == s)) {
154            assert!(FailureCode::try_from(stat).is_err());
155            assert_eq!(FailureCode::from_u8(stat), FailureCode::Reserved);
156        }
157    }
158}