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#[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 pub const fn new() -> Self {
41 Self::TransportMotor
42 }
43
44 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}