1use std::fmt;
3
4pub const SIP_PROTOCOL_VERSION: &str = "2.00";
5pub const LINE_TERMINATOR: char = '\r';
6pub const SIP_DATE_FORMAT: &str = "%Y%m%d %H%M%S";
7
8#[derive(Debug, PartialEq, Clone, Copy)]
10pub enum PayType {
11 Cash,
12 Visa,
13 CreditCard,
14 Check,
15}
16
17impl TryFrom<&str> for PayType {
18 type Error = String;
19
20 fn try_from(pt: &str) -> Result<PayType, Self::Error> {
21 match pt {
22 "00" => Ok(Self::Cash),
23 "01" => Ok(Self::Visa),
24 "02" => Ok(Self::CreditCard),
25 "05" => Ok(Self::Check),
26 _ => Err(format!("Unknown payment type code: {pt}")),
27 }
28 }
29}
30
31impl From<PayType> for &'static str {
32 fn from(pt: PayType) -> &'static str {
33 match pt {
34 PayType::Cash => "00",
35 PayType::Visa => "01",
36 PayType::CreditCard => "02",
37 PayType::Check => "05",
38 }
39 }
40}
41
42#[derive(Debug, PartialEq, Clone, Copy)]
44pub enum FeeType {
45 OtherUnknown,
46 Administrative,
47 Damage,
48 Overdue,
49 Processing,
50 Rental,
51 Replacement,
52 ComputerAccessCharge,
53 HoldFee,
54}
55
56impl TryFrom<&str> for FeeType {
57 type Error = String;
58
59 fn try_from(ft: &str) -> Result<FeeType, Self::Error> {
60 match ft {
61 "01" => Ok(Self::OtherUnknown),
62 "02" => Ok(Self::Administrative),
63 "03" => Ok(Self::Damage),
64 "04" => Ok(Self::Overdue),
65 "05" => Ok(Self::Processing),
66 "06" => Ok(Self::Rental),
67 "07" => Ok(Self::Replacement),
68 "08" => Ok(Self::ComputerAccessCharge),
69 "09" => Ok(Self::HoldFee),
70 _ => Err(format!("Unknown fee type: {ft}")),
71 }
72 }
73}
74
75impl From<FeeType> for &'static str {
76 fn from(ft: FeeType) -> &'static str {
77 match ft {
78 FeeType::OtherUnknown => "01",
79 FeeType::Administrative => "02",
80 FeeType::Damage => "03",
81 FeeType::Overdue => "04",
82 FeeType::Processing => "05",
83 FeeType::Rental => "06",
84 FeeType::Replacement => "07",
85 FeeType::ComputerAccessCharge => "08",
86 FeeType::HoldFee => "09",
87 }
88 }
89}
90
91#[derive(PartialEq, Debug)]
93pub struct FixedField {
94 pub label: &'static str,
98
99 pub length: usize,
104}
105
106impl fmt::Display for FixedField {
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108 write!(f, "{} ({})", self.label, self.length)
109 }
110}
111
112#[derive(PartialEq, Debug)]
114pub struct Field {
115 pub label: &'static str,
119
120 pub code: &'static str,
122}
123
124impl fmt::Display for Field {
125 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126 write!(f, "{} {}", self.code, self.label)
127 }
128}
129
130impl Field {
131 pub fn from_code(code: &str) -> Option<&'static Field> {
140 match code {
141 f if f == F_LOGIN_UID.code => Some(&F_LOGIN_UID),
142 f if f == F_LOGIN_PWD.code => Some(&F_LOGIN_PWD),
143 f if f == F_PATRON_ID.code => Some(&F_PATRON_ID),
144 f if f == F_PATRON_IDENT.code => Some(&F_PATRON_IDENT),
145 f if f == F_ITEM_IDENT.code => Some(&F_ITEM_IDENT),
146 f if f == F_TERMINAL_PWD.code => Some(&F_TERMINAL_PWD),
147 f if f == F_PATRON_PWD.code => Some(&F_PATRON_PWD),
148 f if f == F_PERSONAL_NAME.code => Some(&F_PERSONAL_NAME),
149 f if f == F_SCREEN_MSG.code => Some(&F_SCREEN_MSG),
150 f if f == F_PRINT_LINE.code => Some(&F_PRINT_LINE),
151 f if f == F_DUE_DATE.code => Some(&F_DUE_DATE),
152 f if f == F_TITLE_IDENT.code => Some(&F_TITLE_IDENT),
153 f if f == F_BLOCKED_CARD_MSG.code => Some(&F_BLOCKED_CARD_MSG),
154 f if f == F_LIBRARY_NAME.code => Some(&F_LIBRARY_NAME),
155 f if f == F_TERMINAL_LOCATION.code => Some(&F_TERMINAL_LOCATION),
156 f if f == F_INSTITUTION_ID.code => Some(&F_INSTITUTION_ID),
157 f if f == F_CURRENT_LOCATION.code => Some(&F_CURRENT_LOCATION),
158 f if f == F_PERMANENT_LOCATION.code => Some(&F_PERMANENT_LOCATION),
159 f if f == F_HOLD_ITEMS.code => Some(&F_HOLD_ITEMS),
160 f if f == F_OVERDUE_ITEMS.code => Some(&F_OVERDUE_ITEMS),
161 f if f == F_CHARGED_ITEMS.code => Some(&F_CHARGED_ITEMS),
162 f if f == F_FINE_ITEMS.code => Some(&F_FINE_ITEMS),
163 f if f == F_SEQUENCE_NUMBER.code => Some(&F_SEQUENCE_NUMBER),
164 f if f == F_CHECKSUM.code => Some(&F_CHECKSUM),
165 f if f == F_HOME_ADDRESS.code => Some(&F_HOME_ADDRESS),
166 f if f == F_EMAIL_ADDRESS.code => Some(&F_EMAIL_ADDRESS),
167 f if f == F_HOME_PHONE.code => Some(&F_HOME_PHONE),
168 f if f == F_OWNER.code => Some(&F_OWNER),
169 f if f == F_CURRENCY.code => Some(&F_CURRENCY),
170 f if f == F_CANCEL.code => Some(&F_CANCEL),
171 f if f == F_TRANSACTION_ID.code => Some(&F_TRANSACTION_ID),
172 f if f == F_VALID_PATRON.code => Some(&F_VALID_PATRON),
173 f if f == F_RENEWED_ITEMS.code => Some(&F_RENEWED_ITEMS),
174 f if f == F_UNRENEWED_ITEMS.code => Some(&F_UNRENEWED_ITEMS),
175 f if f == F_FEE_ACKNOWLEGED.code => Some(&F_FEE_ACKNOWLEGED),
176 f if f == F_START_ITEM.code => Some(&F_START_ITEM),
177 f if f == F_END_ITEM.code => Some(&F_END_ITEM),
178 f if f == F_QUEUE_POSITION.code => Some(&F_QUEUE_POSITION),
179 f if f == F_PICKUP_LOCATION.code => Some(&F_PICKUP_LOCATION),
180 f if f == F_RECALL_ITEMS.code => Some(&F_RECALL_ITEMS),
181 f if f == F_FEE_TYPE.code => Some(&F_FEE_TYPE),
182 f if f == F_FEE_LIMIT.code => Some(&F_FEE_LIMIT),
183 f if f == F_FEE_AMOUNT.code => Some(&F_FEE_AMOUNT),
184 f if f == F_EXPIRE_DATE.code => Some(&F_EXPIRE_DATE),
185 f if f == F_SUPPORTED_MESSAGES.code => Some(&F_SUPPORTED_MESSAGES),
186 f if f == F_HOLD_TYPE.code => Some(&F_HOLD_TYPE),
187 f if f == F_HOLD_ITEMS_LIMIT.code => Some(&F_HOLD_ITEMS_LIMIT),
188 f if f == F_OVERDUE_ITEMS_LIST.code => Some(&F_OVERDUE_ITEMS_LIST),
189 f if f == F_CHARGED_ITEMS_LIMIT.code => Some(&F_CHARGED_ITEMS_LIMIT),
190 f if f == F_UNAVAIL_HOLD_ITEMS.code => Some(&F_UNAVAIL_HOLD_ITEMS),
191 f if f == F_HOLD_QUEUE_LENGTH.code => Some(&F_HOLD_QUEUE_LENGTH),
192 f if f == F_FEE_IDENTIFIER.code => Some(&F_FEE_IDENTIFIER),
193 f if f == F_ITEM_PROPERTIES.code => Some(&F_ITEM_PROPERTIES),
194 f if f == F_SECURITY_INHIBIT.code => Some(&F_SECURITY_INHIBIT),
195 f if f == F_RECALL_DATE.code => Some(&F_RECALL_DATE),
196 f if f == F_MEDIA_TYPE.code => Some(&F_MEDIA_TYPE),
197 f if f == F_SORT_BIN.code => Some(&F_SORT_BIN),
198 f if f == F_HOLD_PICKUP_DATE.code => Some(&F_HOLD_PICKUP_DATE),
199 f if f == F_LOGIN_USER_ID.code => Some(&F_LOGIN_USER_ID),
200 f if f == F_LOCATION_CODE.code => Some(&F_LOCATION_CODE),
201 f if f == F_VALID_PATRON_PWD.code => Some(&F_VALID_PATRON_PWD),
202 f if f == F_INET_PROFILE.code => Some(&F_INET_PROFILE),
203 f if f == F_CALL_NUMBER.code => Some(&F_CALL_NUMBER),
204 f if f == F_COLLECTION_CODE.code => Some(&F_COLLECTION_CODE),
205 f if f == F_ALERT_TYPE.code => Some(&F_ALERT_TYPE),
206 f if f == F_HOLD_PATRON_ID.code => Some(&F_HOLD_PATRON_ID),
207 f if f == F_HOLD_PATRON_NAME.code => Some(&F_HOLD_PATRON_NAME),
208 f if f == F_DEST_LOCATION.code => Some(&F_DEST_LOCATION),
209 f if f == F_PATRON_EXPIRE_DATE.code => Some(&F_PATRON_EXPIRE_DATE),
210 f if f == F_PATRON_DOB.code => Some(&F_PATRON_DOB),
211 f if f == F_PATRON_CLASS.code => Some(&F_PATRON_CLASS),
212 f if f == F_REGISTER_LOGIN.code => Some(&F_REGISTER_LOGIN),
213 f if f == F_CHECK_NUMBER.code => Some(&F_CHECK_NUMBER),
214 _ => None,
215 }
216 }
217}
218
219#[derive(PartialEq, Debug)]
225pub struct Message {
226 pub code: &'static str,
228
229 pub label: &'static str,
233
234 pub fixed_fields: &'static [&'static FixedField],
237}
238
239impl Message {
240 pub fn from_code(code: &str) -> Option<&'static Message> {
249 match code {
250 m if m == M_SC_STATUS.code => Some(&M_SC_STATUS),
251 m if m == M_ACS_STATUS.code => Some(&M_ACS_STATUS),
252 m if m == M_LOGIN.code => Some(&M_LOGIN),
253 m if m == M_LOGIN_RESP.code => Some(&M_LOGIN_RESP),
254 m if m == M_ITEM_INFO.code => Some(&M_ITEM_INFO),
255 m if m == M_ITEM_INFO_RESP.code => Some(&M_ITEM_INFO_RESP),
256 m if m == M_PATRON_STATUS.code => Some(&M_PATRON_STATUS),
257 m if m == M_PATRON_STATUS_RESP.code => Some(&M_PATRON_STATUS_RESP),
258 m if m == M_PATRON_INFO.code => Some(&M_PATRON_INFO),
259 m if m == M_PATRON_INFO_RESP.code => Some(&M_PATRON_INFO_RESP),
260 m if m == M_CHECKOUT.code => Some(&M_CHECKOUT),
261 m if m == M_CHECKOUT_RESP.code => Some(&M_CHECKOUT_RESP),
262 m if m == M_RENEW.code => Some(&M_RENEW),
263 m if m == M_RENEW_RESP.code => Some(&M_RENEW_RESP),
264 m if m == M_RENEW_ALL.code => Some(&M_RENEW_ALL),
265 m if m == M_RENEW_ALL_RESP.code => Some(&M_RENEW_ALL_RESP),
266 m if m == M_CHECKIN.code => Some(&M_CHECKIN),
267 m if m == M_CHECKIN_RESP.code => Some(&M_CHECKIN_RESP),
268 m if m == M_HOLD.code => Some(&M_HOLD),
269 m if m == M_HOLD_RESP.code => Some(&M_HOLD_RESP),
270 m if m == M_FEE_PAID.code => Some(&M_FEE_PAID),
271 m if m == M_FEE_PAID_RESP.code => Some(&M_FEE_PAID_RESP),
272 m if m == M_END_PATRON_SESSION.code => Some(&M_END_PATRON_SESSION),
273 m if m == M_END_PATRON_SESSION_RESP.code => Some(&M_END_PATRON_SESSION_RESP),
274 m if m == M_END_SESSION.code => Some(&M_END_SESSION),
275 m if m == M_END_SESSION_RESP.code => Some(&M_END_SESSION_RESP),
276 m if m == M_BLOCK_PATRON.code => Some(&M_BLOCK_PATRON),
277 m if m == M_REQUEST_ACS_RESEND.code => Some(&M_REQUEST_ACS_RESEND),
278 _ => None,
279 }
280 }
281}
282
283type FF = FixedField; pub const FF_DATE: FF = FF {
290 length: 18,
291 label: "transaction date",
292};
293pub const FF_OK: FF = FF {
294 length: 1,
295 label: "ok",
296};
297pub const FF_UID_ALGO: FF = FF {
298 length: 1,
299 label: "uid algorithm",
300};
301pub const FF_PWD_ALGO: FF = FF {
302 length: 1,
303 label: "pwd algorithm",
304};
305pub const FF_FEE_TYPE: FF = FF {
306 length: 2,
307 label: "fee type",
308};
309pub const FF_PAYMENT_TYPE: FF = FF {
310 length: 2,
311 label: "payment type",
312};
313pub const FF_CURRENCY: FF = FF {
314 length: 3,
315 label: "currency type",
316};
317pub const FF_PAYMENT_ACCEPTED: FF = FF {
318 length: 1,
319 label: "payment accepted",
320};
321pub const FF_CIRCULATION_STATUS: FF = FF {
322 length: 2,
323 label: "circulation status",
324};
325pub const FF_SECURITY_MARKER: FF = FF {
326 length: 2,
327 label: "security marker",
328};
329pub const FF_LANGUAGE: FF = FF {
330 length: 3,
331 label: "language",
332};
333pub const FF_PATRON_STATUS: FF = FF {
334 length: 14,
335 label: "patron status",
336};
337pub const FF_SUMMARY: FF = FF {
338 length: 10,
339 label: "summary",
340};
341pub const FF_HOLD_ITEMS_COUNT: FF = FF {
342 length: 4,
343 label: "hold items count",
344};
345pub const FF_OD_ITEMS_COUNT: FF = FF {
346 length: 4,
347 label: "overdue items count",
348};
349pub const FF_CH_ITEMS_COUNT: FF = FF {
350 length: 4,
351 label: "charged items count",
352};
353pub const FF_FINE_ITEMS_COUNT: FF = FF {
354 length: 4,
355 label: "fine items count",
356};
357pub const FF_RECALL_ITEMS_COUNT: FF = FF {
358 length: 4,
359 label: "recall items count",
360};
361pub const FF_UNAVAIL_HOLDS_COUNT: FF = FF {
362 length: 4,
363 label: "unavail holds count",
364};
365pub const FF_SC_RENEWAL_POLICY: FF = FF {
366 length: 1,
367 label: "sc renewal policy",
368};
369pub const FF_NO_BLOCK: FF = FF {
370 length: 1,
371 label: "no block",
372};
373pub const FF_NB_DUE_DATE: FF = FF {
374 length: 18,
375 label: "nb due date",
376};
377pub const FF_STATUS_CODE: FF = FF {
378 length: 1,
379 label: "status code",
380};
381pub const FF_MAX_PRINT_WIDTH: FF = FF {
382 length: 3,
383 label: "max print width",
384};
385pub const FF_PROTOCOL_VERSION: FF = FF {
386 length: 4,
387 label: "protocol version",
388};
389pub const FF_RENEW_OK: FF = FF {
390 length: 1,
391 label: "renewal ok",
392};
393pub const FF_MAGNETIC_MEDIA: FF = FF {
394 length: 1,
395 label: "magnetic media",
396};
397pub const FF_DESENSITIZE: FF = FF {
398 length: 1,
399 label: "desensitize",
400};
401pub const FF_RESENSITIZE: FF = FF {
402 length: 1,
403 label: "resensitize",
404};
405pub const FF_RETURN_DATE: FF = FF {
406 length: 18,
407 label: "return date",
408};
409pub const FF_ALERT: FF = FF {
410 length: 1,
411 label: "alert",
412};
413pub const FF_ONLINE_STATUS: FF = FF {
414 length: 1,
415 label: "on-line status",
416};
417pub const FF_CHECKIN_OK: FF = FF {
418 length: 1,
419 label: "checkin ok",
420};
421pub const FF_CHECKOUT_OK: FF = FF {
422 length: 1,
423 label: "checkout ok",
424};
425pub const FF_ACS_RENEWAL_POLICY: FF = FF {
426 length: 1,
427 label: "acs renewal policy",
428};
429pub const FF_STATUS_UPDATE_OK: FF = FF {
430 length: 1,
431 label: "status update ok",
432};
433pub const FF_OFFLINE_OK: FF = FF {
434 length: 1,
435 label: "offline ok",
436};
437pub const FF_TIMEOUT_PERIOD: FF = FF {
438 length: 3,
439 label: "timeout period",
440};
441pub const FF_RETRIES_ALLOWED: FF = FF {
442 length: 3,
443 label: "retries allowed",
444};
445pub const FF_DATETIME_SYNC: FF = FF {
446 length: 18,
447 label: "date/time sync",
448};
449pub const FF_THIRD_PARTY_ALLOWED: FF = FF {
450 length: 1,
451 label: "third party allowed",
452};
453pub const FF_RENEWED_COUNT: FF = FF {
454 length: 4,
455 label: "renewed count",
456};
457pub const FF_UNRENEWED_COUNT: FF = FF {
458 length: 4,
459 label: "unrenewed count",
460};
461pub const FF_HOLD_MODE: FF = FF {
462 length: 1,
463 label: "hold mode",
464};
465pub const FF_HOLD_AVAILABLE: FF = FF {
466 length: 1,
467 label: "hold available",
468};
469pub const FF_CARD_RETAINED: FF = FF {
470 length: 1,
471 label: "card retained",
472};
473pub const FF_END_PATRON_SESSION: FF = FF {
474 length: 1,
475 label: "end session",
476};
477
478type F = Field; pub const F_LOGIN_UID: F = F {
485 code: "CN",
486 label: "login user id",
487};
488pub const F_LOGIN_PWD: F = F {
489 code: "CO",
490 label: "login password",
491};
492pub const F_PATRON_ID: F = F {
493 code: "AA",
494 label: "patron identifier",
495};
496pub const F_PATRON_IDENT: F = F {
497 code: "AA",
498 label: "patron identifier",
499};
500pub const F_ITEM_IDENT: F = F {
501 code: "AB",
502 label: "item identifier",
503};
504pub const F_TERMINAL_PWD: F = F {
505 code: "AC",
506 label: "terminal password",
507};
508pub const F_PATRON_PWD: F = F {
509 code: "AD",
510 label: "patron password",
511};
512pub const F_PERSONAL_NAME: F = F {
513 code: "AE",
514 label: "personal name",
515};
516pub const F_SCREEN_MSG: F = F {
517 code: "AF",
518 label: "screen message",
519};
520pub const F_PRINT_LINE: F = F {
521 code: "AG",
522 label: "print line",
523};
524pub const F_DUE_DATE: F = F {
525 code: "AH",
526 label: "due date",
527};
528pub const F_TITLE_IDENT: F = F {
529 code: "AJ",
530 label: "title identifier",
531};
532pub const F_BLOCKED_CARD_MSG: F = F {
533 code: "AL",
534 label: "blocked card msg",
535};
536pub const F_LIBRARY_NAME: F = F {
537 code: "AM",
538 label: "library name",
539};
540pub const F_TERMINAL_LOCATION: F = F {
541 code: "AN",
542 label: "terminal location",
543};
544pub const F_INSTITUTION_ID: F = F {
545 code: "AO",
546 label: "institution id",
547};
548pub const F_CURRENT_LOCATION: F = F {
549 code: "AP",
550 label: "current location",
551};
552pub const F_PERMANENT_LOCATION: F = F {
553 code: "AQ",
554 label: "permanent location",
555};
556pub const F_HOLD_ITEMS: F = F {
557 code: "AS",
558 label: "hold items",
559};
560pub const F_OVERDUE_ITEMS: F = F {
561 code: "AT",
562 label: "overdue items",
563};
564pub const F_CHARGED_ITEMS: F = F {
565 code: "AU",
566 label: "charged items",
567};
568pub const F_FINE_ITEMS: F = F {
569 code: "AV",
570 label: "fine items",
571};
572pub const F_SEQUENCE_NUMBER: F = F {
573 code: "AY",
574 label: "sequence number",
575};
576pub const F_CHECKSUM: F = F {
577 code: "AZ",
578 label: "checksum",
579};
580pub const F_HOME_ADDRESS: F = F {
581 code: "BD",
582 label: "home address",
583};
584pub const F_EMAIL_ADDRESS: F = F {
585 code: "BE",
586 label: "e-mail address",
587};
588pub const F_HOME_PHONE: F = F {
589 code: "BF",
590 label: "home phone number",
591};
592pub const F_OWNER: F = F {
593 code: "BG",
594 label: "owner",
595};
596pub const F_CURRENCY: F = F {
597 code: "BH",
598 label: "currency type",
599};
600pub const F_CANCEL: F = F {
601 code: "BI",
602 label: "cancel",
603};
604pub const F_TRANSACTION_ID: F = F {
605 code: "BK",
606 label: "transaction id",
607};
608pub const F_VALID_PATRON: F = F {
609 code: "BL",
610 label: "valid patron",
611};
612pub const F_RENEWED_ITEMS: F = F {
613 code: "BM",
614 label: "renewed items",
615};
616pub const F_UNRENEWED_ITEMS: F = F {
617 code: "BN",
618 label: "unrenewed items",
619};
620pub const F_FEE_ACKNOWLEGED: F = F {
621 code: "BO",
622 label: "fee acknowledged",
623};
624pub const F_START_ITEM: F = F {
625 code: "BP",
626 label: "start item",
627};
628pub const F_END_ITEM: F = F {
629 code: "BQ",
630 label: "end item",
631};
632pub const F_QUEUE_POSITION: F = F {
633 code: "BR",
634 label: "queue position",
635};
636pub const F_PICKUP_LOCATION: F = F {
637 code: "BS",
638 label: "pickup location",
639};
640pub const F_RECALL_ITEMS: F = F {
641 code: "BU",
642 label: "recall items",
643};
644pub const F_FEE_TYPE: F = F {
645 code: "BT",
646 label: "fee type",
647};
648pub const F_FEE_LIMIT: F = F {
649 code: "CC",
650 label: "fee limit",
651};
652pub const F_FEE_AMOUNT: F = F {
653 code: "BV",
654 label: "fee amount",
655};
656pub const F_EXPIRE_DATE: F = F {
657 code: "BW",
658 label: "expiration date",
659};
660pub const F_SUPPORTED_MESSAGES: F = F {
661 code: "BX",
662 label: "supported messages",
663};
664pub const F_HOLD_TYPE: F = F {
665 code: "BY",
666 label: "hold type",
667};
668pub const F_HOLD_ITEMS_LIMIT: F = F {
669 code: "BZ",
670 label: "hold items limit",
671};
672pub const F_OVERDUE_ITEMS_LIST: F = F {
673 code: "CA",
674 label: "overdue items limit",
675};
676pub const F_CHARGED_ITEMS_LIMIT: F = F {
677 code: "CB",
678 label: "charged items limit",
679};
680pub const F_UNAVAIL_HOLD_ITEMS: F = F {
681 code: "CD",
682 label: "unavailable hold items",
683};
684pub const F_HOLD_QUEUE_LENGTH: F = F {
685 code: "CF",
686 label: "hold queue length",
687};
688pub const F_FEE_IDENTIFIER: F = F {
689 code: "CG",
690 label: "fee identifier",
691};
692pub const F_ITEM_PROPERTIES: F = F {
693 code: "CH",
694 label: "item properties",
695};
696pub const F_SECURITY_INHIBIT: F = F {
697 code: "CI",
698 label: "security inhibit",
699};
700pub const F_RECALL_DATE: F = F {
701 code: "CJ",
702 label: "recall date",
703};
704pub const F_MEDIA_TYPE: F = F {
705 code: "CK",
706 label: "media type",
707};
708pub const F_SORT_BIN: F = F {
709 code: "CL",
710 label: "sort bin",
711};
712pub const F_HOLD_PICKUP_DATE: F = F {
713 code: "CM",
714 label: "hold pickup date",
715};
716pub const F_LOGIN_USER_ID: F = F {
717 code: "CN",
718 label: "login user id",
719};
720pub const F_LOCATION_CODE: F = F {
721 code: "CP",
722 label: "location code",
723};
724pub const F_VALID_PATRON_PWD: F = F {
725 code: "CQ",
726 label: "valid patron password",
727};
728pub const F_INET_PROFILE: F = F {
729 code: "PI",
730 label: "patron internet profile",
731};
732pub const F_CALL_NUMBER: F = F {
733 code: "CS",
734 label: "call number",
735};
736pub const F_COLLECTION_CODE: F = F {
737 code: "CR",
738 label: "collection code",
739};
740pub const F_ALERT_TYPE: F = F {
741 code: "CV",
742 label: "alert type",
743};
744pub const F_HOLD_PATRON_ID: F = F {
745 code: "CY",
746 label: "hold patron id",
747};
748pub const F_HOLD_PATRON_NAME: F = F {
749 code: "DA",
750 label: "hold patron name",
751};
752pub const F_DEST_LOCATION: F = F {
753 code: "CT",
754 label: "destination location",
755};
756
757pub const F_PATRON_EXPIRE_DATE: F = F {
759 code: "PA",
760 label: "patron expire date",
761};
762pub const F_PATRON_DOB: F = F {
763 code: "PB",
764 label: "patron birth date",
765};
766pub const F_PATRON_CLASS: F = F {
767 code: "PC",
768 label: "patron class",
769};
770pub const F_REGISTER_LOGIN: F = F {
771 code: "OR",
772 label: "register login",
773};
774pub const F_CHECK_NUMBER: F = F {
775 code: "RN",
776 label: "check number",
777};
778
779pub const EMPTY: &[&FixedField; 0] = &[];
787
788pub const M_SC_STATUS: Message = Message {
790 code: "99",
791 label: "SC Status",
792 fixed_fields: &[&FF_STATUS_CODE, &FF_MAX_PRINT_WIDTH, &FF_PROTOCOL_VERSION],
793};
794
795pub const M_ACS_STATUS: Message = Message {
797 code: "98",
798 label: "ACS Status",
799 fixed_fields: &[
800 &FF_ONLINE_STATUS,
801 &FF_CHECKIN_OK,
802 &FF_CHECKOUT_OK,
803 &FF_ACS_RENEWAL_POLICY,
804 &FF_STATUS_UPDATE_OK,
805 &FF_OFFLINE_OK,
806 &FF_TIMEOUT_PERIOD,
807 &FF_RETRIES_ALLOWED,
808 &FF_DATETIME_SYNC,
809 &FF_PROTOCOL_VERSION,
810 ],
811};
812
813pub const M_LOGIN: Message = Message {
815 code: "93",
816 label: "Login Request",
817 fixed_fields: &[&FF_UID_ALGO, &FF_PWD_ALGO],
818};
819
820pub const M_LOGIN_RESP: Message = Message {
822 code: "94",
823 label: "Login Response",
824 fixed_fields: &[&FF_OK],
825};
826
827pub const M_ITEM_INFO: Message = Message {
829 code: "17",
830 label: "Item Information Request",
831 fixed_fields: &[&FF_DATE],
832};
833
834pub const M_ITEM_INFO_RESP: Message = Message {
836 code: "18",
837 label: "Item Information Response",
838 fixed_fields: &[
839 &FF_CIRCULATION_STATUS,
840 &FF_SECURITY_MARKER,
841 &FF_FEE_TYPE,
842 &FF_DATE,
843 ],
844};
845
846pub const M_PATRON_STATUS: Message = Message {
848 code: "23",
849 label: "Patron Status Request",
850 fixed_fields: &[&FF_LANGUAGE, &FF_DATE],
851};
852
853pub const M_PATRON_STATUS_RESP: Message = Message {
855 code: "24",
856 label: "Patron Status Response",
857 fixed_fields: &[&FF_PATRON_STATUS, &FF_LANGUAGE, &FF_DATE],
858};
859
860pub const M_PATRON_INFO: Message = Message {
862 code: "63",
863 label: "Patron Information",
864 fixed_fields: &[&FF_LANGUAGE, &FF_DATE, &FF_SUMMARY],
865};
866
867pub const M_PATRON_INFO_RESP: Message = Message {
869 code: "64",
870 label: "Patron Information Response",
871 fixed_fields: &[
872 &FF_PATRON_STATUS,
873 &FF_LANGUAGE,
874 &FF_DATE,
875 &FF_HOLD_ITEMS_COUNT,
876 &FF_OD_ITEMS_COUNT,
877 &FF_CH_ITEMS_COUNT,
878 &FF_FINE_ITEMS_COUNT,
879 &FF_RECALL_ITEMS_COUNT,
880 &FF_UNAVAIL_HOLDS_COUNT,
881 ],
882};
883
884pub const M_CHECKOUT: Message = Message {
886 code: "11",
887 label: "Checkout Request",
888 fixed_fields: &[
889 &FF_SC_RENEWAL_POLICY,
890 &FF_NO_BLOCK,
891 &FF_DATE,
892 &FF_NB_DUE_DATE,
893 ],
894};
895
896pub const M_CHECKOUT_RESP: Message = Message {
898 code: "12",
899 label: "Checkout Response",
900 fixed_fields: &[
901 &FF_OK,
902 &FF_RENEW_OK,
903 &FF_MAGNETIC_MEDIA,
904 &FF_DESENSITIZE,
905 &FF_DATE,
906 ],
907};
908
909pub const M_RENEW: Message = Message {
911 code: "29",
912 label: "Renew Request",
913 fixed_fields: &[
914 &FF_THIRD_PARTY_ALLOWED,
915 &FF_NO_BLOCK,
916 &FF_DATE,
917 &FF_NB_DUE_DATE,
918 ],
919};
920
921pub const M_RENEW_RESP: Message = Message {
923 code: "30",
924 label: "Renew Response",
925 fixed_fields: &[
926 &FF_OK,
927 &FF_RENEW_OK,
928 &FF_MAGNETIC_MEDIA,
929 &FF_DESENSITIZE,
930 &FF_DATE,
931 ],
932};
933
934pub const M_RENEW_ALL: Message = Message {
936 code: "65",
937 label: "Renew All Request",
938 fixed_fields: &[&FF_DATE],
939};
940
941pub const M_RENEW_ALL_RESP: Message = Message {
943 code: "66",
944 label: "Renew All Response",
945 fixed_fields: &[&FF_OK, &FF_RENEWED_COUNT, &FF_UNRENEWED_COUNT, &FF_DATE],
946};
947
948pub const M_CHECKIN: Message = Message {
950 code: "09",
951 label: "Checkin Request",
952 fixed_fields: &[&FF_NO_BLOCK, &FF_DATE, &FF_RETURN_DATE],
953};
954
955pub const M_CHECKIN_RESP: Message = Message {
957 code: "10",
958 label: "Checkin Response",
959 fixed_fields: &[
960 &FF_OK,
961 &FF_RESENSITIZE,
962 &FF_MAGNETIC_MEDIA,
963 &FF_ALERT,
964 &FF_DATE,
965 ],
966};
967
968pub const M_HOLD: Message = Message {
970 code: "15",
971 label: "Hold Request",
972 fixed_fields: &[&FF_HOLD_MODE, &FF_DATE],
973};
974
975pub const M_HOLD_RESP: Message = Message {
977 code: "16",
978 label: "Hold Response",
979 fixed_fields: &[&FF_OK, &FF_HOLD_AVAILABLE, &FF_DATE],
980};
981
982pub const M_END_PATRON_SESSION: Message = Message {
984 code: "35",
985 label: "End Patron Session",
986 fixed_fields: &[&FF_DATE],
987};
988
989pub const M_END_PATRON_SESSION_RESP: Message = Message {
991 code: "36",
992 label: "End Session Response",
993 fixed_fields: &[&FF_END_PATRON_SESSION, &FF_DATE],
994};
995
996pub const M_FEE_PAID: Message = Message {
998 code: "37",
999 label: "Fee Paid",
1000 fixed_fields: &[&FF_DATE, &FF_FEE_TYPE, &FF_PAYMENT_TYPE, &FF_CURRENCY],
1001};
1002
1003pub const M_FEE_PAID_RESP: Message = Message {
1005 code: "38",
1006 label: "Fee Paid Response",
1007 fixed_fields: &[&FF_PAYMENT_ACCEPTED, &FF_DATE],
1008};
1009
1010pub const M_REQUEST_ACS_RESEND: Message = Message {
1012 code: "97",
1013 label: "Request ACS Resend",
1014 fixed_fields: &[],
1015};
1016
1017pub const M_BLOCK_PATRON: Message = Message {
1019 code: "01",
1020 label: "Block Patron",
1021 fixed_fields: &[&FF_CARD_RETAINED, &FF_DATE],
1022};
1023
1024pub const M_END_SESSION: Message = Message {
1031 code: "XS",
1032 label: "End SIP Session",
1033 fixed_fields: &[],
1034};
1035
1036pub const M_END_SESSION_RESP: Message = Message {
1038 code: "XT",
1039 label: "End SIP Session Response",
1040 fixed_fields: &[],
1041};
1042
1043#[derive(Debug, PartialEq)]
1047pub enum CheckinAlert {
1048 Unknown,
1049 LocalHold,
1050 RemoteHold,
1051 Ill,
1052 Transit,
1053 Other,
1054}
1055
1056impl TryFrom<&str> for CheckinAlert {
1057 type Error = super::error::Error;
1058
1059 fn try_from(v: &str) -> Result<Self, Self::Error> {
1060 match v {
1061 "00" => Ok(Self::Unknown),
1062 "01" => Ok(Self::LocalHold),
1063 "02" => Ok(Self::RemoteHold),
1064 "03" => Ok(Self::Ill),
1065 "04" => Ok(Self::Transit),
1066 "99" => Ok(Self::Other),
1067 _ => {
1068 log::error!("Invalid checkin alert code: {v}");
1069 Err(Self::Error::MessageFormatError)
1070 }
1071 }
1072 }
1073}
1074
1075impl From<CheckinAlert> for &str {
1076 fn from(a: CheckinAlert) -> &'static str {
1077 match a {
1078 CheckinAlert::Unknown => "00",
1079 CheckinAlert::LocalHold => "01",
1080 CheckinAlert::RemoteHold => "02",
1081 CheckinAlert::Ill => "03",
1082 CheckinAlert::Transit => "04",
1083 CheckinAlert::Other => "99",
1084 }
1085 }
1086}