jcm/message/request/
uid_request.rs

1use crate::{
2    Error, Message, MessageCode, MessageData, MessageType, RequestCode, RequestMode, RequestType,
3    Result,
4};
5
6/// Represents a `Status` request message.
7#[repr(C)]
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub struct UidRequest {
10    uid: u8,
11    mode: RequestMode,
12}
13
14impl UidRequest {
15    /// Creates a new [UidRequest].
16    pub const fn new() -> Self {
17        Self {
18            uid: 0,
19            mode: RequestMode::new(),
20        }
21    }
22
23    /// Creates a new [UidRequest] to [get](RequestMode::Get) the UID.
24    pub const fn new_get() -> Self {
25        Self {
26            uid: 0,
27            mode: RequestMode::Get,
28        }
29    }
30
31    /// Creates a new [UidRequest] to [set](RequestMode::Set) the UID.
32    pub const fn new_set(uid: u8) -> Self {
33        Self {
34            uid,
35            mode: RequestMode::Set,
36        }
37    }
38
39    /// Gets the UID for the [UidRequest].
40    pub const fn uid(&self) -> u8 {
41        self.uid
42    }
43
44    /// Sets the UID for the [UidRequest].
45    pub fn set_uid(&mut self, uid: u8) {
46        self.uid = uid;
47    }
48
49    /// Builder function that sets the UID for the [UidRequest].
50    pub fn with_uid(mut self, uid: u8) -> Self {
51        self.set_uid(uid);
52        self
53    }
54
55    /// Gets the [RequestMode] for the [UidRequest].
56    pub const fn request_mode(&self) -> RequestMode {
57        self.mode
58    }
59
60    /// Sets the [RequestMode] for the [UidRequest].
61    pub fn set_request_mode(&mut self, mode: RequestMode) {
62        self.mode = mode;
63    }
64
65    /// Builder function that sets the [RequestMode] for the [UidRequest].
66    pub fn with_request_mode(mut self, mode: RequestMode) -> Self {
67        self.set_request_mode(mode);
68        self
69    }
70
71    /// Gets the [MessageType] for the [UidRequest].
72    pub const fn message_type(&self) -> MessageType {
73        MessageType::Request(self.request_type())
74    }
75
76    /// Gets the [RequestType] for the [UidRequest].
77    pub const fn request_type(&self) -> RequestType {
78        match self.mode {
79            RequestMode::Get => RequestType::Status,
80            RequestMode::Set => RequestType::SetFeature,
81        }
82    }
83
84    /// Gets the [MessageCode] for the [UidRequest].
85    pub const fn message_code(&self) -> MessageCode {
86        MessageCode::Request(self.request_code())
87    }
88
89    /// Gets the [RequestCode] for the [UidRequest].
90    pub const fn request_code(&self) -> RequestCode {
91        RequestCode::Uid
92    }
93}
94
95impl Default for UidRequest {
96    fn default() -> Self {
97        Self::new()
98    }
99}
100
101impl From<UidRequest> for Message {
102    fn from(val: UidRequest) -> Self {
103        MessageData::from(val).into()
104    }
105}
106
107impl From<&UidRequest> for Message {
108    fn from(val: &UidRequest) -> Self {
109        (*val).into()
110    }
111}
112
113impl From<UidRequest> for MessageData {
114    fn from(val: UidRequest) -> Self {
115        let ret = Self::new()
116            .with_message_type(val.message_type())
117            .with_message_code(val.message_code());
118
119        match val.mode {
120            RequestMode::Get => ret,
121            RequestMode::Set => ret.with_additional(&[val.uid]),
122        }
123    }
124}
125
126impl From<&UidRequest> for MessageData {
127    fn from(val: &UidRequest) -> Self {
128        (*val).into()
129    }
130}
131
132impl TryFrom<&Message> for UidRequest {
133    type Error = Error;
134
135    fn try_from(val: &Message) -> Result<Self> {
136        val.data().try_into()
137    }
138}
139
140impl TryFrom<Message> for UidRequest {
141    type Error = Error;
142
143    fn try_from(val: Message) -> Result<Self> {
144        (&val).try_into()
145    }
146}
147
148impl TryFrom<&MessageData> for UidRequest {
149    type Error = Error;
150
151    fn try_from(val: &MessageData) -> Result<Self> {
152        let (exp_get_type, exp_set_type, exp_code) = (
153            MessageType::Request(RequestType::Status),
154            MessageType::Request(RequestType::SetFeature),
155            MessageCode::Request(RequestCode::Uid),
156        );
157
158        match (val.message_type(), val.message_code()) {
159            (msg_type, msg_code) if msg_type == exp_get_type && msg_code == exp_code => {
160                Ok(Self::new())
161            }
162            (msg_type, msg_code) if msg_type == exp_set_type && msg_code == exp_code => {
163                Ok(Self::new_set(
164                    val.additional()
165                        .first()
166                        .cloned()
167                        .ok_or(Error::InvalidMessageDataLen((0, 1)))?,
168                ))
169            }
170            (msg_type, msg_code) => Err(Error::InvalidMessage((
171                (msg_type.into(), msg_code.into()),
172                (exp_get_type.into(), exp_code.into()),
173            ))),
174        }
175    }
176}
177
178impl TryFrom<MessageData> for UidRequest {
179    type Error = Error;
180
181    fn try_from(val: MessageData) -> Result<Self> {
182        (&val).try_into()
183    }
184}
185
186#[cfg(test)]
187mod tests {
188    use super::*;
189    use crate::{EventCode, EventType};
190
191    #[test]
192    fn test_uid_request() -> Result<()> {
193        let exp_modes = [RequestMode::Get, RequestMode::Set];
194        let exp_types = [
195            MessageType::Request(RequestType::Status),
196            MessageType::Request(RequestType::SetFeature),
197        ];
198        let exp_code = MessageCode::Request(RequestCode::Uid);
199
200        let uid = 1;
201
202        for (mode, exp_type) in exp_modes.into_iter().zip(exp_types) {
203            let msg_data = MessageData::new()
204                .with_message_type(exp_type)
205                .with_message_code(exp_code);
206
207            let (exp_req, msg) = match mode {
208                RequestMode::Get => (UidRequest::new_get(), msg_data.into()),
209                RequestMode::Set => (
210                    UidRequest::new_set(uid),
211                    msg_data.with_additional(&[uid]).into(),
212                ),
213            };
214
215            assert_eq!(exp_req.message_type(), exp_type);
216            assert_eq!(exp_type.request_type(), Ok(exp_req.request_type()));
217
218            assert_eq!(exp_req.message_code(), exp_code);
219            assert_eq!(exp_code.request_code(), Ok(exp_req.request_code()));
220
221            assert_eq!(Message::from(exp_req), msg);
222            assert_eq!(UidRequest::try_from(&msg), Ok(exp_req));
223        }
224
225        Ok(())
226    }
227
228    #[test]
229    fn test_uid_request_invalid() -> Result<()> {
230        let invalid_types = [MessageType::Reserved]
231            .into_iter()
232            .chain((0x80..=0x8f).map(|m| MessageType::Event(EventType::from_u8(m))))
233            .chain([RequestType::Operation, RequestType::Reserved].map(MessageType::Request))
234            .collect::<Vec<MessageType>>();
235
236        let invalid_codes = [
237            RequestCode::ProgramSignature,
238            RequestCode::Version,
239            RequestCode::SerialNumber,
240            RequestCode::ModelName,
241            RequestCode::Reset,
242            RequestCode::Stack,
243            RequestCode::Status,
244            RequestCode::Inhibit,
245            RequestCode::Collect,
246            RequestCode::Key,
247            RequestCode::EventResendInterval,
248            RequestCode::Idle,
249            RequestCode::Reject,
250            RequestCode::Hold,
251            RequestCode::AcceptorCollect,
252            RequestCode::DenominationDisable,
253            RequestCode::DirectionDisable,
254            RequestCode::CurrencyAssign,
255            RequestCode::CashBoxSize,
256            RequestCode::NearFull,
257            RequestCode::BarCode,
258            RequestCode::Insert,
259            RequestCode::ConditionalVend,
260            RequestCode::Pause,
261            RequestCode::NoteDataInfo,
262            RequestCode::RecyclerCollect,
263            RequestCode::Reserved,
264        ]
265        .map(MessageCode::Request)
266        .into_iter()
267        .chain(
268            [
269                EventCode::PowerUp,
270                EventCode::PowerUpAcceptor,
271                EventCode::PowerUpStacker,
272                EventCode::Inhibit,
273                EventCode::ProgramSignature,
274                EventCode::Rejected,
275                EventCode::Collected,
276                EventCode::Clear,
277                EventCode::OperationError,
278                EventCode::Failure,
279                EventCode::NoteStay,
280                EventCode::PowerUpAcceptorAccepting,
281                EventCode::PowerUpStackerAccepting,
282                EventCode::Idle,
283                EventCode::Escrow,
284                EventCode::VendValid,
285                EventCode::AcceptorRejected,
286                EventCode::Returned,
287                EventCode::AcceptorCollected,
288                EventCode::Insert,
289                EventCode::ConditionalVend,
290                EventCode::Pause,
291                EventCode::Resume,
292                EventCode::AcceptorClear,
293                EventCode::AcceptorOperationError,
294                EventCode::AcceptorFailure,
295                EventCode::AcceptorNoteStay,
296                EventCode::FunctionAbeyance,
297                EventCode::Reserved,
298            ]
299            .map(MessageCode::Event),
300        )
301        .collect::<Vec<MessageCode>>();
302
303        for &msg_type in invalid_types.iter() {
304            for &msg_code in invalid_codes.iter() {
305                let inval_data = MessageData::new()
306                    .with_message_type(msg_type)
307                    .with_message_code(msg_code);
308
309                let inval_type = MessageData::new()
310                    .with_message_type(msg_type)
311                    .with_message_code(UidRequest::new().message_code());
312
313                let inval_code = MessageData::new()
314                    .with_message_type(UidRequest::new().message_type())
315                    .with_message_code(msg_code);
316
317                for stack_data in [inval_data, inval_type, inval_code] {
318                    assert!(UidRequest::try_from(&stack_data).is_err());
319                    assert!(UidRequest::try_from(Message::new().with_data(stack_data)).is_err());
320                }
321            }
322        }
323
324        Ok(())
325    }
326}