jcm/message/message_data/
message_code.rs

1use std::{fmt, mem};
2
3use crate::{Error, FuncId, MessageType, Result};
4
5mod event_code;
6mod request_code;
7
8pub use event_code::*;
9pub use request_code::*;
10
11const RESERVED: u16 = 0xffff;
12
13#[repr(u16)]
14#[derive(Copy, Clone, Debug, Eq, PartialEq)]
15pub enum MessageCode {
16    Request(RequestCode),
17    Event(EventCode),
18    Reserved = RESERVED,
19}
20
21impl MessageCode {
22    /// Creates a new [MessageCode].
23    pub const fn new() -> Self {
24        Self::Request(RequestCode::new())
25    }
26
27    /// Creates a new [MessageCode] from the provided parameters.
28    pub const fn create(msg_type: MessageType, val: u16) -> Self {
29        match msg_type {
30            MessageType::Request(_ty) => Self::Request(RequestCode::from_u16(val)),
31            MessageType::Event(_ty) => Self::Event(EventCode::from_u16(val)),
32            _ => Self::Reserved,
33        }
34    }
35
36    /// Gets whether the [MessageCode] contains a [RequestCode] variant.
37    pub const fn is_request_code(&self) -> bool {
38        matches!(self, Self::Request(_))
39    }
40
41    /// Converts the [MessageCode] into a [RequestCode].
42    pub const fn request_code(&self) -> Result<RequestCode> {
43        match self {
44            Self::Request(code) => Ok(*code),
45            _ => Err(Error::InvalidRequestCode(RESERVED)),
46        }
47    }
48
49    /// Gets whether the [MessageCode] contains a [EventCode] variant.
50    pub const fn is_event_code(&self) -> bool {
51        matches!(self, Self::Event(_))
52    }
53
54    /// Gets whether the [MessageCode] contains a `PowerUp` [EventCode] variant.
55    pub const fn is_power_up_event(&self) -> bool {
56        matches!(
57            self,
58            Self::Event(EventCode::PowerUp)
59                | Self::Event(EventCode::PowerUpAcceptor)
60                | Self::Event(EventCode::PowerUpStacker)
61                | Self::Event(EventCode::PowerUpAcceptorAccepting)
62                | Self::Event(EventCode::PowerUpStackerAccepting)
63        )
64    }
65
66    /// Converts the [MessageCode] into a [EventCode].
67    pub const fn event_code(&self) -> Result<EventCode> {
68        match self {
69            Self::Event(code) => Ok(*code),
70            _ => Err(Error::InvalidEventCode(RESERVED)),
71        }
72    }
73
74    /// Gets the [FuncId] of the [MessageCode].
75    pub const fn func_id(&self) -> FuncId {
76        match self {
77            Self::Request(code) => code.func_id(),
78            Self::Event(code) => code.func_id(),
79            _ => FuncId::Reserved,
80        }
81    }
82
83    /// Converts the [MessageCode] to raw byte array.
84    pub fn to_bytes(&self) -> [u8; 2] {
85        u16::from(self).to_le_bytes()
86    }
87
88    /// Gets the length of the [MessageCode].
89    pub const fn len() -> usize {
90        mem::size_of::<u16>()
91    }
92
93    /// Gets whether the [MessageCode] contains a reserved variant.
94    pub const fn is_empty(&self) -> bool {
95        matches!(
96            self,
97            Self::Reserved
98                | Self::Request(RequestCode::Reserved)
99                | Self::Event(EventCode::Reserved)
100        )
101    }
102
103    /// Gets whether the [MessageCode] is a valid variant.
104    pub const fn is_valid(&self) -> bool {
105        !self.is_empty()
106    }
107}
108
109impl From<MessageCode> for u16 {
110    fn from(val: MessageCode) -> Self {
111        match val {
112            MessageCode::Request(c) => c.into(),
113            MessageCode::Event(c) => c.into(),
114            _ => RESERVED,
115        }
116    }
117}
118
119impl From<&MessageCode> for u16 {
120    fn from(val: &MessageCode) -> Self {
121        (*val).into()
122    }
123}
124
125impl From<MessageCode> for u8 {
126    fn from(val: MessageCode) -> Self {
127        u16::from(val) as u8
128    }
129}
130
131impl From<&MessageCode> for u8 {
132    fn from(val: &MessageCode) -> Self {
133        (*val).into()
134    }
135}
136
137impl TryFrom<RawMessageCode> for MessageCode {
138    type Error = Error;
139
140    fn try_from(val: RawMessageCode) -> Result<Self> {
141        match Self::create(val.msg_type, val.code) {
142            Self::Reserved
143            | Self::Request(RequestCode::Reserved)
144            | Self::Event(EventCode::Reserved) => {
145                Err(Error::InvalidMessageCode((val.msg_type.into(), val.code)))
146            }
147            v => Ok(v),
148        }
149    }
150}
151
152impl Default for MessageCode {
153    fn default() -> Self {
154        Self::new()
155    }
156}
157
158impl fmt::Display for MessageCode {
159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160        match self {
161            Self::Request(c) => write!(
162                f,
163                r#"{{"message_type": "request", "code": {c}, "details": {}}}"#,
164                RequestCodeDetails(*c)
165            ),
166            Self::Event(c) => write!(
167                f,
168                r#"{{"message_type": "event", "code": {c}, "details": {}}}"#,
169                EventCodeDetails(*c)
170            ),
171            Self::Reserved => write!(
172                f,
173                r#"{{"message_type": "reserved", "code": {RESERVED:#x}, "details": "reserved"}}"#
174            ),
175        }
176    }
177}
178
179/// Convenience struct for internal conversion implementation.
180#[repr(C)]
181#[derive(Copy, Clone, Debug, Eq, PartialEq)]
182pub(crate) struct RawMessageCode {
183    pub msg_type: MessageType,
184    pub code: u16,
185}
186
187impl RawMessageCode {
188    /// Creates a new [RawMessageCode].
189    pub const fn new() -> Self {
190        Self {
191            msg_type: MessageType::new(),
192            code: 0,
193        }
194    }
195
196    /// Creates a new [RawMessageCode] from the provided parameters.
197    pub const fn create(msg_type: MessageType, code: u16) -> Self {
198        Self { msg_type, code }
199    }
200}
201
202impl Default for RawMessageCode {
203    fn default() -> Self {
204        Self::new()
205    }
206}
207
208#[cfg(test)]
209mod tests {
210    use super::*;
211    use crate::{EventType, RequestType};
212
213    #[test]
214    fn test_message_code() {
215        let req_type = MessageType::Request(RequestType::new());
216        let event_type = MessageType::Event(EventType::new());
217
218        let raw_vals = [
219            RawMessageCode::create(req_type, u16::from(RequestCode::Uid)),
220            RawMessageCode::create(req_type, u16::from(RequestCode::ProgramSignature)),
221            RawMessageCode::create(req_type, u16::from(RequestCode::Version)),
222            RawMessageCode::create(req_type, u16::from(RequestCode::SerialNumber)),
223            RawMessageCode::create(req_type, u16::from(RequestCode::ModelName)),
224            RawMessageCode::create(req_type, u16::from(RequestCode::Status)),
225            RawMessageCode::create(req_type, u16::from(RequestCode::Reset)),
226            RawMessageCode::create(req_type, u16::from(RequestCode::Inhibit)),
227            RawMessageCode::create(req_type, u16::from(RequestCode::Collect)),
228            RawMessageCode::create(req_type, u16::from(RequestCode::Key)),
229            RawMessageCode::create(req_type, u16::from(RequestCode::EventResendInterval)),
230            RawMessageCode::create(req_type, u16::from(RequestCode::Idle)),
231            RawMessageCode::create(req_type, u16::from(RequestCode::Stack)),
232            RawMessageCode::create(req_type, u16::from(RequestCode::Reject)),
233            RawMessageCode::create(req_type, u16::from(RequestCode::Hold)),
234            RawMessageCode::create(req_type, u16::from(RequestCode::AcceptorCollect)),
235            RawMessageCode::create(req_type, u16::from(RequestCode::DenominationDisable)),
236            RawMessageCode::create(req_type, u16::from(RequestCode::DirectionDisable)),
237            RawMessageCode::create(req_type, u16::from(RequestCode::CurrencyAssign)),
238            RawMessageCode::create(req_type, u16::from(RequestCode::CashBoxSize)),
239            RawMessageCode::create(req_type, u16::from(RequestCode::NearFull)),
240            RawMessageCode::create(req_type, u16::from(RequestCode::BarCode)),
241            RawMessageCode::create(req_type, u16::from(RequestCode::Insert)),
242            RawMessageCode::create(req_type, u16::from(RequestCode::ConditionalVend)),
243            RawMessageCode::create(req_type, u16::from(RequestCode::Pause)),
244            RawMessageCode::create(req_type, u16::from(RequestCode::NoteDataInfo)),
245            RawMessageCode::create(req_type, u16::from(RequestCode::RecyclerCollect)),
246            RawMessageCode::create(event_type, u16::from(EventCode::PowerUp)),
247            RawMessageCode::create(event_type, u16::from(EventCode::PowerUpAcceptor)),
248            RawMessageCode::create(event_type, u16::from(EventCode::PowerUpStacker)),
249            RawMessageCode::create(event_type, u16::from(EventCode::Inhibit)),
250            RawMessageCode::create(event_type, u16::from(EventCode::ProgramSignature)),
251            RawMessageCode::create(event_type, u16::from(EventCode::Rejected)),
252            RawMessageCode::create(event_type, u16::from(EventCode::Collected)),
253            RawMessageCode::create(event_type, u16::from(EventCode::Clear)),
254            RawMessageCode::create(event_type, u16::from(EventCode::OperationError)),
255            RawMessageCode::create(event_type, u16::from(EventCode::Failure)),
256            RawMessageCode::create(event_type, u16::from(EventCode::NoteStay)),
257            RawMessageCode::create(event_type, u16::from(EventCode::PowerUpAcceptorAccepting)),
258            RawMessageCode::create(event_type, u16::from(EventCode::PowerUpStackerAccepting)),
259            RawMessageCode::create(event_type, u16::from(EventCode::Idle)),
260            RawMessageCode::create(event_type, u16::from(EventCode::Escrow)),
261            RawMessageCode::create(event_type, u16::from(EventCode::VendValid)),
262            RawMessageCode::create(event_type, u16::from(EventCode::AcceptorRejected)),
263            RawMessageCode::create(event_type, u16::from(EventCode::Returned)),
264            RawMessageCode::create(event_type, u16::from(EventCode::AcceptorCollected)),
265            RawMessageCode::create(event_type, u16::from(EventCode::Insert)),
266            RawMessageCode::create(event_type, u16::from(EventCode::ConditionalVend)),
267            RawMessageCode::create(event_type, u16::from(EventCode::Pause)),
268            RawMessageCode::create(event_type, u16::from(EventCode::Resume)),
269            RawMessageCode::create(event_type, u16::from(EventCode::AcceptorClear)),
270            RawMessageCode::create(event_type, u16::from(EventCode::AcceptorOperationError)),
271            RawMessageCode::create(event_type, u16::from(EventCode::AcceptorFailure)),
272            RawMessageCode::create(event_type, u16::from(EventCode::AcceptorNoteStay)),
273            RawMessageCode::create(event_type, u16::from(EventCode::FunctionAbeyance)),
274        ];
275        let expected = [
276            MessageCode::Request(RequestCode::Uid),
277            MessageCode::Request(RequestCode::ProgramSignature),
278            MessageCode::Request(RequestCode::Version),
279            MessageCode::Request(RequestCode::SerialNumber),
280            MessageCode::Request(RequestCode::ModelName),
281            MessageCode::Request(RequestCode::Status),
282            MessageCode::Request(RequestCode::Reset),
283            MessageCode::Request(RequestCode::Inhibit),
284            MessageCode::Request(RequestCode::Collect),
285            MessageCode::Request(RequestCode::Key),
286            MessageCode::Request(RequestCode::EventResendInterval),
287            MessageCode::Request(RequestCode::Idle),
288            MessageCode::Request(RequestCode::Stack),
289            MessageCode::Request(RequestCode::Reject),
290            MessageCode::Request(RequestCode::Hold),
291            MessageCode::Request(RequestCode::AcceptorCollect),
292            MessageCode::Request(RequestCode::DenominationDisable),
293            MessageCode::Request(RequestCode::DirectionDisable),
294            MessageCode::Request(RequestCode::CurrencyAssign),
295            MessageCode::Request(RequestCode::CashBoxSize),
296            MessageCode::Request(RequestCode::NearFull),
297            MessageCode::Request(RequestCode::BarCode),
298            MessageCode::Request(RequestCode::Insert),
299            MessageCode::Request(RequestCode::ConditionalVend),
300            MessageCode::Request(RequestCode::Pause),
301            MessageCode::Request(RequestCode::NoteDataInfo),
302            MessageCode::Request(RequestCode::RecyclerCollect),
303            MessageCode::Event(EventCode::PowerUp),
304            MessageCode::Event(EventCode::PowerUpAcceptor),
305            MessageCode::Event(EventCode::PowerUpStacker),
306            MessageCode::Event(EventCode::Inhibit),
307            MessageCode::Event(EventCode::ProgramSignature),
308            MessageCode::Event(EventCode::Rejected),
309            MessageCode::Event(EventCode::Collected),
310            MessageCode::Event(EventCode::Clear),
311            MessageCode::Event(EventCode::OperationError),
312            MessageCode::Event(EventCode::Failure),
313            MessageCode::Event(EventCode::NoteStay),
314            MessageCode::Event(EventCode::PowerUpAcceptorAccepting),
315            MessageCode::Event(EventCode::PowerUpStackerAccepting),
316            MessageCode::Event(EventCode::Idle),
317            MessageCode::Event(EventCode::Escrow),
318            MessageCode::Event(EventCode::VendValid),
319            MessageCode::Event(EventCode::AcceptorRejected),
320            MessageCode::Event(EventCode::Returned),
321            MessageCode::Event(EventCode::AcceptorCollected),
322            MessageCode::Event(EventCode::Insert),
323            MessageCode::Event(EventCode::ConditionalVend),
324            MessageCode::Event(EventCode::Pause),
325            MessageCode::Event(EventCode::Resume),
326            MessageCode::Event(EventCode::AcceptorClear),
327            MessageCode::Event(EventCode::AcceptorOperationError),
328            MessageCode::Event(EventCode::AcceptorFailure),
329            MessageCode::Event(EventCode::AcceptorNoteStay),
330            MessageCode::Event(EventCode::FunctionAbeyance),
331        ];
332
333        for (raw, exp) in raw_vals.into_iter().zip(expected.into_iter()) {
334            assert_eq!(MessageCode::try_from(raw), Ok(exp));
335            assert_eq!(u16::from(exp), raw.code);
336
337            assert!(exp.is_valid());
338            assert!(!exp.is_empty());
339
340            if exp.is_request_code() {
341                assert_eq!(exp.request_code(), Ok(RequestCode::from_u16(raw.code)));
342            }
343
344            if exp.is_event_code() {
345                assert_eq!(exp.event_code(), Ok(EventCode::from_u16(raw.code)));
346            }
347        }
348
349        for val in (0..=0x1fffu16).filter(|s| !raw_vals.iter().any(|d| d.code == *s)) {
350            let req_code = RawMessageCode::create(req_type, val);
351            let event_code = RawMessageCode::create(event_type, val);
352
353            assert!(MessageCode::try_from(req_code).is_err());
354            assert!(MessageCode::try_from(event_code).is_err());
355
356            let res_req = MessageCode::create(req_code.msg_type, req_code.code);
357            let res_event = MessageCode::create(event_code.msg_type, event_code.code);
358
359            assert_eq!(res_req, MessageCode::Request(RequestCode::Reserved));
360            assert_eq!(res_event, MessageCode::Event(EventCode::Reserved));
361
362            assert!(res_req.is_empty());
363            assert!(!res_req.is_valid());
364
365            assert!(res_event.is_empty());
366            assert!(!res_event.is_valid());
367        }
368    }
369}