1use crate::{
2 Error, Message, MessageCode, MessageData, MessageType, RequestCode, RequestMode, RequestType,
3 Result,
4};
5
6#[repr(C)]
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub struct UidRequest {
10 uid: u8,
11 mode: RequestMode,
12}
13
14impl UidRequest {
15 pub const fn new() -> Self {
17 Self {
18 uid: 0,
19 mode: RequestMode::new(),
20 }
21 }
22
23 pub const fn new_get() -> Self {
25 Self {
26 uid: 0,
27 mode: RequestMode::Get,
28 }
29 }
30
31 pub const fn new_set(uid: u8) -> Self {
33 Self {
34 uid,
35 mode: RequestMode::Set,
36 }
37 }
38
39 pub const fn uid(&self) -> u8 {
41 self.uid
42 }
43
44 pub fn set_uid(&mut self, uid: u8) {
46 self.uid = uid;
47 }
48
49 pub fn with_uid(mut self, uid: u8) -> Self {
51 self.set_uid(uid);
52 self
53 }
54
55 pub const fn request_mode(&self) -> RequestMode {
57 self.mode
58 }
59
60 pub fn set_request_mode(&mut self, mode: RequestMode) {
62 self.mode = mode;
63 }
64
65 pub fn with_request_mode(mut self, mode: RequestMode) -> Self {
67 self.set_request_mode(mode);
68 self
69 }
70
71 pub const fn message_type(&self) -> MessageType {
73 MessageType::Request(self.request_type())
74 }
75
76 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 pub const fn message_code(&self) -> MessageCode {
86 MessageCode::Request(self.request_code())
87 }
88
89 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}