1use serde::{Deserialize, Serialize};
7use std::fmt;
8use std::str::FromStr;
9
10use crate::error::{Error, Result};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
15#[serde(rename_all = "UPPERCASE")]
16pub enum RadioService {
17 AA,
19 AB,
21 AC,
23 AD,
25 AF,
27 AH,
29 AI,
31 AL,
33 AN,
35 AR,
37 AS,
39 AT,
41 AW,
43 BA,
45 BB,
47 BC,
49 BR,
51 BS,
53 CA,
55 CB,
57 CD,
59 CE,
61 CF,
63 CG,
65 CJ,
67 CL,
69 CM,
71 CN,
73 CO,
75 CP,
77 CR,
79 CT,
81 CW,
83 CX,
85 CY,
87 CZ,
89 DV,
91 ED,
93 GB,
95 GC,
97 GE,
99 GF,
101 GI,
103 GJ,
105 GL,
107 GM,
109 GO,
111 GP,
113 GR,
115 GS,
117 GU,
119 GW,
121 GX,
123 HA,
125 HV,
127 IG,
129 IK,
131 IQ,
133 LD,
135 LN,
137 LP,
139 LS,
141 LV,
143 LW,
145 MA,
147 MC,
149 MD,
151 MG,
153 MK,
155 MM,
157 MR,
159 MS,
161 MW,
163 NC,
165 NN,
167 OW,
169 PA,
171 PB,
173 PC,
175 PE,
177 PF,
179 PK,
181 PL,
183 PM,
185 PW,
187 QA,
189 QD,
191 QM,
193 QO,
195 QQ,
197 QT,
199 RP,
201 RR,
203 RS,
205 SA,
207 SB,
209 SE,
211 SG,
213 SL,
215 SP,
217 SY,
219 TB,
221 TC,
223 TI,
225 TN,
227 TP,
229 TS,
231 TT,
233 TZ,
235 UM,
237 UU,
239 VX,
241 WA,
243 WM,
245 WP,
247 WR,
249 WS,
251 WT,
253 WU,
255 WX,
257 WY,
259 WZ,
261 YB,
263 YC,
265 YD,
267 YE,
269 YF,
271 YG,
273 YH,
275 YI,
277 YJ,
279 YK,
281 YL,
283 YM,
285 YO,
287 YP,
289 YS,
291 YU,
293 YW,
295 YX,
297 ZA,
299 ZV,
301}
302
303impl RadioService {
304 pub fn as_str(&self) -> &'static str {
306 match self {
307 Self::AA => "AA",
308 Self::AB => "AB",
309 Self::AC => "AC",
310 Self::AD => "AD",
311 Self::AF => "AF",
312 Self::AH => "AH",
313 Self::AI => "AI",
314 Self::AL => "AL",
315 Self::AN => "AN",
316 Self::AR => "AR",
317 Self::AS => "AS",
318 Self::AT => "AT",
319 Self::AW => "AW",
320 Self::BA => "BA",
321 Self::BB => "BB",
322 Self::BC => "BC",
323 Self::BR => "BR",
324 Self::BS => "BS",
325 Self::CA => "CA",
326 Self::CB => "CB",
327 Self::CD => "CD",
328 Self::CE => "CE",
329 Self::CF => "CF",
330 Self::CG => "CG",
331 Self::CJ => "CJ",
332 Self::CL => "CL",
333 Self::CM => "CM",
334 Self::CN => "CN",
335 Self::CO => "CO",
336 Self::CP => "CP",
337 Self::CR => "CR",
338 Self::CT => "CT",
339 Self::CW => "CW",
340 Self::CX => "CX",
341 Self::CY => "CY",
342 Self::CZ => "CZ",
343 Self::DV => "DV",
344 Self::ED => "ED",
345 Self::GB => "GB",
346 Self::GC => "GC",
347 Self::GE => "GE",
348 Self::GF => "GF",
349 Self::GI => "GI",
350 Self::GJ => "GJ",
351 Self::GL => "GL",
352 Self::GM => "GM",
353 Self::GO => "GO",
354 Self::GP => "GP",
355 Self::GR => "GR",
356 Self::GS => "GS",
357 Self::GU => "GU",
358 Self::GW => "GW",
359 Self::GX => "GX",
360 Self::HA => "HA",
361 Self::HV => "HV",
362 Self::IG => "IG",
363 Self::IK => "IK",
364 Self::IQ => "IQ",
365 Self::LD => "LD",
366 Self::LN => "LN",
367 Self::LP => "LP",
368 Self::LS => "LS",
369 Self::LV => "LV",
370 Self::LW => "LW",
371 Self::MA => "MA",
372 Self::MC => "MC",
373 Self::MD => "MD",
374 Self::MG => "MG",
375 Self::MK => "MK",
376 Self::MM => "MM",
377 Self::MR => "MR",
378 Self::MS => "MS",
379 Self::MW => "MW",
380 Self::NC => "NC",
381 Self::NN => "NN",
382 Self::OW => "OW",
383 Self::PA => "PA",
384 Self::PB => "PB",
385 Self::PC => "PC",
386 Self::PE => "PE",
387 Self::PF => "PF",
388 Self::PK => "PK",
389 Self::PL => "PL",
390 Self::PM => "PM",
391 Self::PW => "PW",
392 Self::QA => "QA",
393 Self::QD => "QD",
394 Self::QM => "QM",
395 Self::QO => "QO",
396 Self::QQ => "QQ",
397 Self::QT => "QT",
398 Self::RP => "RP",
399 Self::RR => "RR",
400 Self::RS => "RS",
401 Self::SA => "SA",
402 Self::SB => "SB",
403 Self::SE => "SE",
404 Self::SG => "SG",
405 Self::SL => "SL",
406 Self::SP => "SP",
407 Self::SY => "SY",
408 Self::TB => "TB",
409 Self::TC => "TC",
410 Self::TI => "TI",
411 Self::TN => "TN",
412 Self::TP => "TP",
413 Self::TS => "TS",
414 Self::TT => "TT",
415 Self::TZ => "TZ",
416 Self::UM => "UM",
417 Self::UU => "UU",
418 Self::VX => "VX",
419 Self::WA => "WA",
420 Self::WM => "WM",
421 Self::WP => "WP",
422 Self::WR => "WR",
423 Self::WS => "WS",
424 Self::WT => "WT",
425 Self::WU => "WU",
426 Self::WX => "WX",
427 Self::WY => "WY",
428 Self::WZ => "WZ",
429 Self::YB => "YB",
430 Self::YC => "YC",
431 Self::YD => "YD",
432 Self::YE => "YE",
433 Self::YF => "YF",
434 Self::YG => "YG",
435 Self::YH => "YH",
436 Self::YI => "YI",
437 Self::YJ => "YJ",
438 Self::YK => "YK",
439 Self::YL => "YL",
440 Self::YM => "YM",
441 Self::YO => "YO",
442 Self::YP => "YP",
443 Self::YS => "YS",
444 Self::YU => "YU",
445 Self::YW => "YW",
446 Self::YX => "YX",
447 Self::ZA => "ZA",
448 Self::ZV => "ZV",
449 }
450 }
451
452 pub fn description(&self) -> &'static str {
454 match self {
455 Self::AA => "Aviation Auxiliary Group",
456 Self::AB => "Aural Microwave Booster",
457 Self::AC => "Aircraft",
458 Self::AD => "AWS-4 (2000-2020 MHz and 2180-2200 MHz)",
459 Self::AF => "Aeronautical and Fixed",
460 Self::AH => "AWS-H Block (1915-1920 MHz and 1995-2000 MHz)",
461 Self::AI => "Aural Intercity Relay",
462 Self::AL => "ALL",
463 Self::AN => "Antenna Structure Registration",
464 Self::AR => "Aviation Radionavigation",
465 Self::AS => "Aural Studio Transmitter Link",
466 Self::AT => "AWS-3 (1695-1710, 1755-1780, 2155-2180 MHz)",
467 Self::AW => "AWS (1710-1755 MHz and 2110-2155 MHz)",
468 Self::BA => "1390-1392 MHz Band, Market Area",
469 Self::BB => "1392-1395 and 1432-1435 MHz Bands, Market Area",
470 Self::BC => "1670-1675 MHz Band, Market Area",
471 Self::BR => "Broadband Radio Service",
472 Self::BS => "900 MHz Broadband Service",
473 Self::CA => "Commercial Air-ground Radiotelephone",
474 Self::CB => "BETRS",
475 Self::CD => "Paging and Radiotelephone",
476 Self::CE => "Digital Electronic Message Service - Common Carrier",
477 Self::CF => "Common Carrier Fixed Point to Point Microwave",
478 Self::CG => "General Aviation Air-ground Radiotelephone",
479 Self::CJ => "Commercial Aviation Air-Ground Radiotelephone (800 MHz)",
480 Self::CL => "Cellular",
481 Self::CM => "Commercial Operator",
482 Self::CN => "PCS Narrowband",
483 Self::CO => "Offshore Radiotelephone",
484 Self::CP => "Part 22 VHF/UHF Paging (excluding 931MHz)",
485 Self::CR => "Rural Radiotelephone",
486 Self::CT => "Local Television Transmission",
487 Self::CW => "PCS Broadband",
488 Self::CX => "Cellular, Auctioned",
489 Self::CY => "1910-1915/1990-1995 MHz Bands, Market Area",
490 Self::CZ => "Part 22 931 MHz Paging",
491 Self::DV => "Multichannel Video Distribution AND Data Service",
492 Self::ED => "Educational Broadband Service",
493 Self::GB => "Business, 806-821/851-866 MHz, Conventional",
494 Self::GC => "929-931 MHz Band, Auctioned",
495 Self::GE => "Public Safety/Special Emergency, 806-817/851-862MHz, Conventional",
496 Self::GF => "Public Safety Ntl Plan, 821-824/866-869 MHz, Conventional",
497 Self::GI => "Other Industrial/Land Transport, 896-901/935-940 MHz, Conventional",
498 Self::GJ => "Business/Industrial/Land Trans, 809-824/854-869 MHz, Conventional",
499 Self::GL => "900 MHz Conventional SMR (Site-Specific)",
500 Self::GM => "800 MHz Conventional SMR (Site-specific)",
501 Self::GO => "Other Industrial/Land Transport, 806-821/851-866 MHz, Conventional",
502 Self::GP => "Public Safety/Special Emergency, 806-821/851-866 MHz, Conventional",
503 Self::GR => "SMR, 896-901/935-940 MHz, Conventional",
504 Self::GS => "Private Carrier Paging, 929-930 MHz",
505 Self::GU => "Business, 896-901/935-940 MHz, Conventional",
506 Self::GW => "General Wireless Communications Service",
507 Self::GX => "SMR, 806-821/851-866 MHz, Conventional",
508 Self::HA => "Amateur",
509 Self::HV => "Vanity (Amateur)",
510 Self::IG => "Industrial/Business Pool, Conventional",
511 Self::IK => "Industrial/Business Pool - Commercial, Conventional",
512 Self::IQ => "Intelligent Transportation Service (Public Safety)",
513 Self::LD => "Local Multipoint Distribution Service",
514 Self::LN => "902-928 MHz Location Narrowband (Non-multilateration)",
515 Self::LP => "Broadcast Auxiliary Low Power",
516 Self::LS => "Location and Monitoring Service, Multilateration (LMS)",
517 Self::LV => "Low Power Wireless Assist Video Devices",
518 Self::LW => "902-928 MHz Location Wideband (Grandfathered AVM)",
519 Self::MA => "Marine Auxiliary Group",
520 Self::MC => "Coastal Group",
521 Self::MD => "Multipoint Distribution Service (MDS and MMDS)",
522 Self::MG => "Microwave Industrial/Business Pool",
523 Self::MK => "Alaska Group",
524 Self::MM => "Millimeter Wave 70/80/90 GHz Service",
525 Self::MR => "Marine Radiolocation Land",
526 Self::MS => "Multiple Address Service, Auctioned",
527 Self::MW => "Microwave Public Safety Pool",
528 Self::NC => "Nationwide Commercial 5 Channel, 220 MHz",
529 Self::NN => "3650-3700 MHz",
530 Self::OW => "FCC Ownership Disclosure Information",
531 Self::PA => "Public Safety 4940-4990 MHz Band",
532 Self::PB => "4940-4990 MHz Public Safety, Base/Mobile",
533 Self::PC => "Public Coast Stations, Auctioned",
534 Self::PE => "Digital Electronic Message Service - Private",
535 Self::PF => "4940-4990 MHz Public Safety, Point-to-Point",
536 Self::PK => "3.45 GHz Service",
537 Self::PL => "3.5 GHz Band Priority Access License",
538 Self::PM => "3.7 GHz Service",
539 Self::PW => "Public Safety Pool, Conventional",
540 Self::QA => "220-222 MHz Band, Auctioned",
541 Self::QD => "Non-Nationwide Data, 220 MHz",
542 Self::QM => "Non-Nationwide Public Safety/Mutual Aid, 220 MHz",
543 Self::QO => "Non-Nationwide Other, 220 MHz",
544 Self::QQ => "Intelligent Transportation Service (Non-Public Safety)",
545 Self::QT => "Non-Nationwide 5 Channel Trunked, 220 MHz",
546 Self::RP => "Broadcast Auxiliary Remote Pickup",
547 Self::RR => "Restricted Operator",
548 Self::RS => "Land Mobile Radiolocation",
549 Self::SA => "Ship Recreational or Voluntarily Equipped",
550 Self::SB => "Ship Compulsory Equipped",
551 Self::SE => "Ship Exemption",
552 Self::SG => "Conventional Public Safety 700 MHz",
553 Self::SL => "Public Safety 700 MHz Band-State License",
554 Self::SP => "700 MHz Public Safety Broadband Nationwide License",
555 Self::SY => "Trunked Public Safety 700 MHz",
556 Self::TB => "TV Microwave Booster",
557 Self::TC => "MSS Ancillary Terrestrial Component (ATC) Leasing",
558 Self::TI => "TV Intercity Relay",
559 Self::TN => "39 GHz, Auctioned",
560 Self::TP => "TV Pickup",
561 Self::TS => "TV Studio Transmitter Link",
562 Self::TT => "TV Translator Relay",
563 Self::TZ => "24 GHz Service",
564 Self::UM => "Unlicensed Wireless Microphone Registration",
565 Self::UU => "Upper Microwave Flexible Use Service",
566 Self::VX => "Instructional Television Fixed Service",
567 Self::WA => "Microwave Aviation",
568 Self::WM => "Microwave Marine",
569 Self::WP => "700 MHz Upper Band (Block D)",
570 Self::WR => "Microwave Radiolocation",
571 Self::WS => "Wireless Communications Service",
572 Self::WT => "600 MHz Band",
573 Self::WU => "700 MHz Upper Band (Block C)",
574 Self::WX => "700 MHz Guard Band",
575 Self::WY => "700 MHz Lower Band (Blocks A, B & E)",
576 Self::WZ => "700 MHz Lower Band (Blocks C, D)",
577 Self::YB => "Business, 806-821/851-866 MHz, Trunked",
578 Self::YC => "SMR, 806-821/851-866 MHz, Auctioned",
579 Self::YD => "SMR, 896-901/935-940 MHz, Auctioned",
580 Self::YE => "Public Safety/Special Emergency, 806-817/851-862MHz, Trunked",
581 Self::YF => "Public Safety Ntl Plan, 821-824/866-869 MHz, Trunked",
582 Self::YG => "Industrial/Business Pool, Trunked",
583 Self::YH => "SMR, 806-821/851-866 MHz, Auctioned (Rebanded YC)",
584 Self::YI => "Other Industrial/Land Transport, 896-901/935-940 MHz, Trunked",
585 Self::YJ => "Business/Industrial/Land Trans, 809-824/854-869 MHz, Trunked",
586 Self::YK => "Industrial/Business Pool - Commercial, Trunked",
587 Self::YL => "900 MHz Trunked SMR (Site-Specific)",
588 Self::YM => "800 MHz Trunked SMR (Site-specific)",
589 Self::YO => "Other Industrial/Land Transport, 806-821/851-866 MHz, Trunked",
590 Self::YP => "Public Safety/Special Emergency, 806-821/851-866 MHz, Trunked",
591 Self::YS => "SMR, 896-901/935-940 MHz, Trunked",
592 Self::YU => "Business, 896-901/935-940 MHz, Trunked",
593 Self::YW => "Public Safety Pool, Trunked",
594 Self::YX => "SMR, 806-821/851-866 MHz, Trunked",
595 Self::ZA => "General Mobile Radio (GMRS)",
596 Self::ZV => "218-219 MHz Service",
597 }
598 }
599
600 pub fn is_amateur(&self) -> bool {
602 matches!(self, Self::HA | Self::HV)
603 }
604
605 pub fn is_maritime(&self) -> bool {
607 matches!(
608 self,
609 Self::SA | Self::SB | Self::SE | Self::MA | Self::MC | Self::MK
610 )
611 }
612
613 pub fn is_aircraft(&self) -> bool {
615 matches!(
616 self,
617 Self::AC | Self::AA | Self::AF | Self::AR | Self::CA | Self::CG | Self::CJ
618 )
619 }
620
621 pub fn to_u8(&self) -> u8 {
624 match self {
625 Self::AA => 0,
626 Self::AB => 1,
627 Self::AC => 2,
628 Self::AD => 3,
629 Self::AF => 4,
630 Self::AH => 5,
631 Self::AI => 6,
632 Self::AL => 7,
633 Self::AN => 8,
634 Self::AR => 9,
635 Self::AS => 10,
636 Self::AT => 11,
637 Self::AW => 12,
638 Self::BA => 13,
639 Self::BB => 14,
640 Self::BC => 15,
641 Self::BR => 16,
642 Self::BS => 17,
643 Self::CA => 18,
644 Self::CB => 19,
645 Self::CD => 20,
646 Self::CE => 21,
647 Self::CF => 22,
648 Self::CG => 23,
649 Self::CJ => 24,
650 Self::CL => 25,
651 Self::CM => 26,
652 Self::CN => 27,
653 Self::CO => 28,
654 Self::CP => 29,
655 Self::CR => 30,
656 Self::CT => 31,
657 Self::CW => 32,
658 Self::CX => 33,
659 Self::CY => 34,
660 Self::CZ => 35,
661 Self::DV => 36,
662 Self::ED => 37,
663 Self::GB => 38,
664 Self::GC => 39,
665 Self::GE => 40,
666 Self::GF => 41,
667 Self::GI => 42,
668 Self::GJ => 43,
669 Self::GL => 44,
670 Self::GM => 45,
671 Self::GO => 46,
672 Self::GP => 47,
673 Self::GR => 48,
674 Self::GS => 49,
675 Self::GU => 50,
676 Self::GW => 51,
677 Self::GX => 52,
678 Self::HA => 53,
679 Self::HV => 54,
680 Self::IG => 55,
681 Self::IK => 56,
682 Self::IQ => 57,
683 Self::LD => 58,
684 Self::LN => 59,
685 Self::LP => 60,
686 Self::LS => 61,
687 Self::LV => 62,
688 Self::LW => 63,
689 Self::MA => 64,
690 Self::MC => 65,
691 Self::MD => 66,
692 Self::MG => 67,
693 Self::MK => 68,
694 Self::MM => 69,
695 Self::MR => 70,
696 Self::MS => 71,
697 Self::MW => 72,
698 Self::NC => 73,
699 Self::NN => 74,
700 Self::OW => 75,
701 Self::PA => 76,
702 Self::PB => 77,
703 Self::PC => 78,
704 Self::PE => 79,
705 Self::PF => 80,
706 Self::PK => 81,
707 Self::PL => 82,
708 Self::PM => 83,
709 Self::PW => 84,
710 Self::QA => 85,
711 Self::QD => 86,
712 Self::QM => 87,
713 Self::QO => 88,
714 Self::QQ => 89,
715 Self::QT => 90,
716 Self::RP => 91,
717 Self::RR => 92,
718 Self::RS => 93,
719 Self::SA => 94,
720 Self::SB => 95,
721 Self::SE => 96,
722 Self::SG => 97,
723 Self::SL => 98,
724 Self::SP => 99,
725 Self::SY => 100,
726 Self::TB => 101,
727 Self::TC => 102,
728 Self::TI => 103,
729 Self::TN => 104,
730 Self::TP => 105,
731 Self::TS => 106,
732 Self::TT => 107,
733 Self::TZ => 108,
734 Self::UM => 109,
735 Self::UU => 110,
736 Self::VX => 111,
737 Self::WA => 112,
738 Self::WM => 113,
739 Self::WP => 114,
740 Self::WR => 115,
741 Self::WS => 116,
742 Self::WT => 117,
743 Self::WU => 118,
744 Self::WX => 119,
745 Self::WY => 120,
746 Self::WZ => 121,
747 Self::YB => 122,
748 Self::YC => 123,
749 Self::YD => 124,
750 Self::YE => 125,
751 Self::YF => 126,
752 Self::YG => 127,
753 Self::YH => 128,
754 Self::YI => 129,
755 Self::YJ => 130,
756 Self::YK => 131,
757 Self::YL => 132,
758 Self::YM => 133,
759 Self::YO => 134,
760 Self::YP => 135,
761 Self::YS => 136,
762 Self::YU => 137,
763 Self::YW => 138,
764 Self::YX => 139,
765 Self::ZA => 140,
766 Self::ZV => 141,
767 }
768 }
769
770 pub fn from_u8(value: u8) -> Option<Self> {
773 match value {
774 0 => Some(Self::AA),
775 1 => Some(Self::AB),
776 2 => Some(Self::AC),
777 3 => Some(Self::AD),
778 4 => Some(Self::AF),
779 5 => Some(Self::AH),
780 6 => Some(Self::AI),
781 7 => Some(Self::AL),
782 8 => Some(Self::AN),
783 9 => Some(Self::AR),
784 10 => Some(Self::AS),
785 11 => Some(Self::AT),
786 12 => Some(Self::AW),
787 13 => Some(Self::BA),
788 14 => Some(Self::BB),
789 15 => Some(Self::BC),
790 16 => Some(Self::BR),
791 17 => Some(Self::BS),
792 18 => Some(Self::CA),
793 19 => Some(Self::CB),
794 20 => Some(Self::CD),
795 21 => Some(Self::CE),
796 22 => Some(Self::CF),
797 23 => Some(Self::CG),
798 24 => Some(Self::CJ),
799 25 => Some(Self::CL),
800 26 => Some(Self::CM),
801 27 => Some(Self::CN),
802 28 => Some(Self::CO),
803 29 => Some(Self::CP),
804 30 => Some(Self::CR),
805 31 => Some(Self::CT),
806 32 => Some(Self::CW),
807 33 => Some(Self::CX),
808 34 => Some(Self::CY),
809 35 => Some(Self::CZ),
810 36 => Some(Self::DV),
811 37 => Some(Self::ED),
812 38 => Some(Self::GB),
813 39 => Some(Self::GC),
814 40 => Some(Self::GE),
815 41 => Some(Self::GF),
816 42 => Some(Self::GI),
817 43 => Some(Self::GJ),
818 44 => Some(Self::GL),
819 45 => Some(Self::GM),
820 46 => Some(Self::GO),
821 47 => Some(Self::GP),
822 48 => Some(Self::GR),
823 49 => Some(Self::GS),
824 50 => Some(Self::GU),
825 51 => Some(Self::GW),
826 52 => Some(Self::GX),
827 53 => Some(Self::HA),
828 54 => Some(Self::HV),
829 55 => Some(Self::IG),
830 56 => Some(Self::IK),
831 57 => Some(Self::IQ),
832 58 => Some(Self::LD),
833 59 => Some(Self::LN),
834 60 => Some(Self::LP),
835 61 => Some(Self::LS),
836 62 => Some(Self::LV),
837 63 => Some(Self::LW),
838 64 => Some(Self::MA),
839 65 => Some(Self::MC),
840 66 => Some(Self::MD),
841 67 => Some(Self::MG),
842 68 => Some(Self::MK),
843 69 => Some(Self::MM),
844 70 => Some(Self::MR),
845 71 => Some(Self::MS),
846 72 => Some(Self::MW),
847 73 => Some(Self::NC),
848 74 => Some(Self::NN),
849 75 => Some(Self::OW),
850 76 => Some(Self::PA),
851 77 => Some(Self::PB),
852 78 => Some(Self::PC),
853 79 => Some(Self::PE),
854 80 => Some(Self::PF),
855 81 => Some(Self::PK),
856 82 => Some(Self::PL),
857 83 => Some(Self::PM),
858 84 => Some(Self::PW),
859 85 => Some(Self::QA),
860 86 => Some(Self::QD),
861 87 => Some(Self::QM),
862 88 => Some(Self::QO),
863 89 => Some(Self::QQ),
864 90 => Some(Self::QT),
865 91 => Some(Self::RP),
866 92 => Some(Self::RR),
867 93 => Some(Self::RS),
868 94 => Some(Self::SA),
869 95 => Some(Self::SB),
870 96 => Some(Self::SE),
871 97 => Some(Self::SG),
872 98 => Some(Self::SL),
873 99 => Some(Self::SP),
874 100 => Some(Self::SY),
875 101 => Some(Self::TB),
876 102 => Some(Self::TC),
877 103 => Some(Self::TI),
878 104 => Some(Self::TN),
879 105 => Some(Self::TP),
880 106 => Some(Self::TS),
881 107 => Some(Self::TT),
882 108 => Some(Self::TZ),
883 109 => Some(Self::UM),
884 110 => Some(Self::UU),
885 111 => Some(Self::VX),
886 112 => Some(Self::WA),
887 113 => Some(Self::WM),
888 114 => Some(Self::WP),
889 115 => Some(Self::WR),
890 116 => Some(Self::WS),
891 117 => Some(Self::WT),
892 118 => Some(Self::WU),
893 119 => Some(Self::WX),
894 120 => Some(Self::WY),
895 121 => Some(Self::WZ),
896 122 => Some(Self::YB),
897 123 => Some(Self::YC),
898 124 => Some(Self::YD),
899 125 => Some(Self::YE),
900 126 => Some(Self::YF),
901 127 => Some(Self::YG),
902 128 => Some(Self::YH),
903 129 => Some(Self::YI),
904 130 => Some(Self::YJ),
905 131 => Some(Self::YK),
906 132 => Some(Self::YL),
907 133 => Some(Self::YM),
908 134 => Some(Self::YO),
909 135 => Some(Self::YP),
910 136 => Some(Self::YS),
911 137 => Some(Self::YU),
912 138 => Some(Self::YW),
913 139 => Some(Self::YX),
914 140 => Some(Self::ZA),
915 141 => Some(Self::ZV),
916 _ => None,
917 }
918 }
919}
920
921impl fmt::Display for RadioService {
922 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
923 write!(f, "{}", self.as_str())
924 }
925}
926
927impl FromStr for RadioService {
928 type Err = Error;
929
930 fn from_str(s: &str) -> Result<Self> {
931 match s.trim().to_uppercase().as_str() {
932 "AA" => Ok(Self::AA),
933 "AB" => Ok(Self::AB),
934 "AC" => Ok(Self::AC),
935 "AD" => Ok(Self::AD),
936 "AF" => Ok(Self::AF),
937 "AH" => Ok(Self::AH),
938 "AI" => Ok(Self::AI),
939 "AL" => Ok(Self::AL),
940 "AN" => Ok(Self::AN),
941 "AR" => Ok(Self::AR),
942 "AS" => Ok(Self::AS),
943 "AT" => Ok(Self::AT),
944 "AW" => Ok(Self::AW),
945 "BA" => Ok(Self::BA),
946 "BB" => Ok(Self::BB),
947 "BC" => Ok(Self::BC),
948 "BR" => Ok(Self::BR),
949 "BS" => Ok(Self::BS),
950 "CA" => Ok(Self::CA),
951 "CB" => Ok(Self::CB),
952 "CD" => Ok(Self::CD),
953 "CE" => Ok(Self::CE),
954 "CF" => Ok(Self::CF),
955 "CG" => Ok(Self::CG),
956 "CJ" => Ok(Self::CJ),
957 "CL" => Ok(Self::CL),
958 "CM" => Ok(Self::CM),
959 "CN" => Ok(Self::CN),
960 "CO" => Ok(Self::CO),
961 "CP" => Ok(Self::CP),
962 "CR" => Ok(Self::CR),
963 "CT" => Ok(Self::CT),
964 "CW" => Ok(Self::CW),
965 "CX" => Ok(Self::CX),
966 "CY" => Ok(Self::CY),
967 "CZ" => Ok(Self::CZ),
968 "DV" => Ok(Self::DV),
969 "ED" => Ok(Self::ED),
970 "GB" => Ok(Self::GB),
971 "GC" => Ok(Self::GC),
972 "GE" => Ok(Self::GE),
973 "GF" => Ok(Self::GF),
974 "GI" => Ok(Self::GI),
975 "GJ" => Ok(Self::GJ),
976 "GL" => Ok(Self::GL),
977 "GM" => Ok(Self::GM),
978 "GO" => Ok(Self::GO),
979 "GP" => Ok(Self::GP),
980 "GR" => Ok(Self::GR),
981 "GS" => Ok(Self::GS),
982 "GU" => Ok(Self::GU),
983 "GW" => Ok(Self::GW),
984 "GX" => Ok(Self::GX),
985 "HA" => Ok(Self::HA),
986 "HV" => Ok(Self::HV),
987 "IG" => Ok(Self::IG),
988 "IK" => Ok(Self::IK),
989 "IQ" => Ok(Self::IQ),
990 "LD" => Ok(Self::LD),
991 "LN" => Ok(Self::LN),
992 "LP" => Ok(Self::LP),
993 "LS" => Ok(Self::LS),
994 "LV" => Ok(Self::LV),
995 "LW" => Ok(Self::LW),
996 "MA" => Ok(Self::MA),
997 "MC" => Ok(Self::MC),
998 "MD" => Ok(Self::MD),
999 "MG" => Ok(Self::MG),
1000 "MK" => Ok(Self::MK),
1001 "MM" => Ok(Self::MM),
1002 "MR" => Ok(Self::MR),
1003 "MS" => Ok(Self::MS),
1004 "MW" => Ok(Self::MW),
1005 "NC" => Ok(Self::NC),
1006 "NN" => Ok(Self::NN),
1007 "OW" => Ok(Self::OW),
1008 "PA" => Ok(Self::PA),
1009 "PB" => Ok(Self::PB),
1010 "PC" => Ok(Self::PC),
1011 "PE" => Ok(Self::PE),
1012 "PF" => Ok(Self::PF),
1013 "PK" => Ok(Self::PK),
1014 "PL" => Ok(Self::PL),
1015 "PM" => Ok(Self::PM),
1016 "PW" => Ok(Self::PW),
1017 "QA" => Ok(Self::QA),
1018 "QD" => Ok(Self::QD),
1019 "QM" => Ok(Self::QM),
1020 "QO" => Ok(Self::QO),
1021 "QQ" => Ok(Self::QQ),
1022 "QT" => Ok(Self::QT),
1023 "RP" => Ok(Self::RP),
1024 "RR" => Ok(Self::RR),
1025 "RS" => Ok(Self::RS),
1026 "SA" => Ok(Self::SA),
1027 "SB" => Ok(Self::SB),
1028 "SE" => Ok(Self::SE),
1029 "SG" => Ok(Self::SG),
1030 "SL" => Ok(Self::SL),
1031 "SP" => Ok(Self::SP),
1032 "SY" => Ok(Self::SY),
1033 "TB" => Ok(Self::TB),
1034 "TC" => Ok(Self::TC),
1035 "TI" => Ok(Self::TI),
1036 "TN" => Ok(Self::TN),
1037 "TP" => Ok(Self::TP),
1038 "TS" => Ok(Self::TS),
1039 "TT" => Ok(Self::TT),
1040 "TZ" => Ok(Self::TZ),
1041 "UM" => Ok(Self::UM),
1042 "UU" => Ok(Self::UU),
1043 "VX" => Ok(Self::VX),
1044 "WA" => Ok(Self::WA),
1045 "WM" => Ok(Self::WM),
1046 "WP" => Ok(Self::WP),
1047 "WR" => Ok(Self::WR),
1048 "WS" => Ok(Self::WS),
1049 "WT" => Ok(Self::WT),
1050 "WU" => Ok(Self::WU),
1051 "WX" => Ok(Self::WX),
1052 "WY" => Ok(Self::WY),
1053 "WZ" => Ok(Self::WZ),
1054 "YB" => Ok(Self::YB),
1055 "YC" => Ok(Self::YC),
1056 "YD" => Ok(Self::YD),
1057 "YE" => Ok(Self::YE),
1058 "YF" => Ok(Self::YF),
1059 "YG" => Ok(Self::YG),
1060 "YH" => Ok(Self::YH),
1061 "YI" => Ok(Self::YI),
1062 "YJ" => Ok(Self::YJ),
1063 "YK" => Ok(Self::YK),
1064 "YL" => Ok(Self::YL),
1065 "YM" => Ok(Self::YM),
1066 "YO" => Ok(Self::YO),
1067 "YP" => Ok(Self::YP),
1068 "YS" => Ok(Self::YS),
1069 "YU" => Ok(Self::YU),
1070 "YW" => Ok(Self::YW),
1071 "YX" => Ok(Self::YX),
1072 "ZA" => Ok(Self::ZA),
1073 "ZV" => Ok(Self::ZV),
1074 _ => Err(Error::InvalidEnumValue {
1075 enum_type: "RadioService",
1076 value: s.to_string(),
1077 }),
1078 }
1079 }
1080}
1081
1082#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
1084pub enum ApplicationPurpose {
1085 AssignmentOfAuthorization,
1087 Amendment,
1089 DEAnnualReport,
1091 AdministrativeUpdate,
1093 CancellationOfLicense,
1095 CBlockElection,
1097 DataCorrection,
1099 DuplicateLicense,
1101 ExtensionOfTime,
1103 HACReport,
1105 CancelLease,
1107 ExtendLease,
1109 ModifyLease,
1111 NewLease,
1113 TransferLessee,
1115 AdminUpdateLease,
1117 Modification,
1119 New,
1121 RequiredNotification,
1123 DEReportableEvent,
1125 RegisterLinkLocation,
1127 RenewalModification,
1129 RenewalOnly,
1131 TransferOfControl,
1133 Withdrawal,
1135}
1136
1137impl ApplicationPurpose {
1138 pub fn as_str(&self) -> &'static str {
1140 match self {
1141 Self::AssignmentOfAuthorization => "AA",
1142 Self::Amendment => "AM",
1143 Self::DEAnnualReport => "AR",
1144 Self::AdministrativeUpdate => "AU",
1145 Self::CancellationOfLicense => "CA",
1146 Self::CBlockElection => "CB",
1147 Self::DataCorrection => "DC",
1148 Self::DuplicateLicense => "DU",
1149 Self::ExtensionOfTime => "EX",
1150 Self::HACReport => "HA",
1151 Self::CancelLease => "LC",
1152 Self::ExtendLease => "LE",
1153 Self::ModifyLease => "LM",
1154 Self::NewLease => "LN",
1155 Self::TransferLessee => "LT",
1156 Self::AdminUpdateLease => "LU",
1157 Self::Modification => "MD",
1158 Self::New => "NE",
1159 Self::RequiredNotification => "NT",
1160 Self::DEReportableEvent => "RE",
1161 Self::RegisterLinkLocation => "RL",
1162 Self::RenewalModification => "RM",
1163 Self::RenewalOnly => "RO",
1164 Self::TransferOfControl => "TC",
1165 Self::Withdrawal => "WD",
1166 }
1167 }
1168}
1169
1170impl FromStr for ApplicationPurpose {
1171 type Err = Error;
1172
1173 fn from_str(s: &str) -> Result<Self> {
1174 match s.trim().to_uppercase().as_str() {
1175 "AA" => Ok(Self::AssignmentOfAuthorization),
1176 "AM" => Ok(Self::Amendment),
1177 "AR" => Ok(Self::DEAnnualReport),
1178 "AU" => Ok(Self::AdministrativeUpdate),
1179 "CA" => Ok(Self::CancellationOfLicense),
1180 "CB" => Ok(Self::CBlockElection),
1181 "DC" => Ok(Self::DataCorrection),
1182 "DU" => Ok(Self::DuplicateLicense),
1183 "EX" => Ok(Self::ExtensionOfTime),
1184 "HA" => Ok(Self::HACReport),
1185 "LC" => Ok(Self::CancelLease),
1186 "LE" => Ok(Self::ExtendLease),
1187 "LM" => Ok(Self::ModifyLease),
1188 "LN" => Ok(Self::NewLease),
1189 "LT" => Ok(Self::TransferLessee),
1190 "LU" => Ok(Self::AdminUpdateLease),
1191 "MD" => Ok(Self::Modification),
1192 "NE" => Ok(Self::New),
1193 "NT" => Ok(Self::RequiredNotification),
1194 "RE" => Ok(Self::DEReportableEvent),
1195 "RL" => Ok(Self::RegisterLinkLocation),
1196 "RM" => Ok(Self::RenewalModification),
1197 "RO" => Ok(Self::RenewalOnly),
1198 "TC" => Ok(Self::TransferOfControl),
1199 "WD" => Ok(Self::Withdrawal),
1200 _ => Err(Error::InvalidEnumValue {
1201 enum_type: "ApplicationPurpose",
1202 value: s.to_string(),
1203 }),
1204 }
1205 }
1206}
1207
1208impl fmt::Display for ApplicationPurpose {
1209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1210 write!(f, "{}", self.as_str())
1211 }
1212}
1213
1214#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
1216pub enum ApplicationStatus {
1217 Submitted,
1219 Pending,
1221 AGranted,
1223 ConsentedTo,
1225 Dismissed,
1227 Eliminate,
1229 Granted,
1231 HistoryOnly,
1233 Inactive,
1235 HACSubmitted,
1237 Killed,
1239 Consummated,
1241 GrantedInPart,
1243 PendingPackFiling,
1245 Accepted,
1247 Returned,
1249 Saved,
1251 Terminated,
1253 Unprocessable,
1255 Withdrawn,
1257 NotApplicable,
1259 HasProblems,
1261}
1262
1263impl ApplicationStatus {
1264 pub fn as_str(&self) -> &'static str {
1266 match self {
1267 Self::Submitted => "1",
1268 Self::Pending => "2",
1269 Self::AGranted => "A",
1270 Self::ConsentedTo => "C",
1271 Self::Dismissed => "D",
1272 Self::Eliminate => "E",
1273 Self::Granted => "G",
1274 Self::HistoryOnly => "H",
1275 Self::Inactive => "I",
1276 Self::HACSubmitted => "J",
1277 Self::Killed => "K",
1278 Self::Consummated => "M",
1279 Self::GrantedInPart => "N",
1280 Self::PendingPackFiling => "P",
1281 Self::Accepted => "Q",
1282 Self::Returned => "R",
1283 Self::Saved => "S",
1284 Self::Terminated => "T",
1285 Self::Unprocessable => "U",
1286 Self::Withdrawn => "W",
1287 Self::NotApplicable => "X",
1288 Self::HasProblems => "Y",
1289 }
1290 }
1291}
1292
1293impl FromStr for ApplicationStatus {
1294 type Err = Error;
1295
1296 fn from_str(s: &str) -> Result<Self> {
1297 match s.trim().to_uppercase().as_str() {
1298 "1" => Ok(Self::Submitted),
1299 "2" => Ok(Self::Pending),
1300 "A" => Ok(Self::AGranted),
1301 "C" => Ok(Self::ConsentedTo),
1302 "D" => Ok(Self::Dismissed),
1303 "E" => Ok(Self::Eliminate),
1304 "G" => Ok(Self::Granted),
1305 "H" => Ok(Self::HistoryOnly),
1306 "I" => Ok(Self::Inactive),
1307 "J" => Ok(Self::HACSubmitted),
1308 "K" => Ok(Self::Killed),
1309 "M" => Ok(Self::Consummated),
1310 "N" => Ok(Self::GrantedInPart),
1311 "P" => Ok(Self::PendingPackFiling),
1312 "Q" => Ok(Self::Accepted),
1313 "R" => Ok(Self::Returned),
1314 "S" => Ok(Self::Saved),
1315 "T" => Ok(Self::Terminated),
1316 "U" => Ok(Self::Unprocessable),
1317 "W" => Ok(Self::Withdrawn),
1318 "X" => Ok(Self::NotApplicable),
1319 "Y" => Ok(Self::HasProblems),
1320 _ => Err(Error::InvalidEnumValue {
1321 enum_type: "ApplicationStatus",
1322 value: s.to_string(),
1323 }),
1324 }
1325 }
1326}
1327
1328impl fmt::Display for ApplicationStatus {
1329 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1330 write!(f, "{}", self.as_str())
1331 }
1332}
1333
1334#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
1336pub enum LicenseStatus {
1337 Active,
1339 Cancelled,
1341 Expired,
1343 PendingLegalStatus,
1345 ParentStationCancelled,
1347 Terminated,
1349 TermPending,
1351}
1352
1353impl LicenseStatus {
1354 pub fn as_str(&self) -> &'static str {
1356 match self {
1357 Self::Active => "A",
1358 Self::Cancelled => "C",
1359 Self::Expired => "E",
1360 Self::PendingLegalStatus => "L",
1361 Self::ParentStationCancelled => "P",
1362 Self::Terminated => "T",
1363 Self::TermPending => "X",
1364 }
1365 }
1366
1367 pub fn is_active(&self) -> bool {
1369 matches!(self, Self::Active)
1370 }
1371
1372 pub fn to_u8(&self) -> u8 {
1374 match self {
1375 Self::Active => 0,
1376 Self::Cancelled => 1,
1377 Self::Expired => 2,
1378 Self::PendingLegalStatus => 3,
1379 Self::ParentStationCancelled => 4,
1380 Self::Terminated => 5,
1381 Self::TermPending => 6,
1382 }
1383 }
1384
1385 pub fn from_u8(value: u8) -> Option<Self> {
1387 match value {
1388 0 => Some(Self::Active),
1389 1 => Some(Self::Cancelled),
1390 2 => Some(Self::Expired),
1391 3 => Some(Self::PendingLegalStatus),
1392 4 => Some(Self::ParentStationCancelled),
1393 5 => Some(Self::Terminated),
1394 6 => Some(Self::TermPending),
1395 _ => None,
1396 }
1397 }
1398}
1399
1400impl FromStr for LicenseStatus {
1401 type Err = Error;
1402
1403 fn from_str(s: &str) -> Result<Self> {
1404 match s.trim().to_uppercase().as_str() {
1405 "A" => Ok(Self::Active),
1406 "C" => Ok(Self::Cancelled),
1407 "E" => Ok(Self::Expired),
1408 "L" => Ok(Self::PendingLegalStatus),
1409 "P" => Ok(Self::ParentStationCancelled),
1410 "T" => Ok(Self::Terminated),
1411 "X" => Ok(Self::TermPending),
1412 _ => Err(Error::InvalidEnumValue {
1413 enum_type: "LicenseStatus",
1414 value: s.to_string(),
1415 }),
1416 }
1417 }
1418}
1419
1420impl fmt::Display for LicenseStatus {
1421 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1422 write!(f, "{}", self.as_str())
1423 }
1424}
1425
1426#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
1428pub enum OperatorClass {
1429 Advanced,
1431 Extra,
1433 General,
1435 Novice,
1437 TechnicianPlus,
1439 Technician,
1441}
1442
1443impl OperatorClass {
1444 pub fn as_str(&self) -> &'static str {
1446 match self {
1447 Self::Advanced => "A",
1448 Self::Extra => "E",
1449 Self::General => "G",
1450 Self::Novice => "N",
1451 Self::TechnicianPlus => "P",
1452 Self::Technician => "T",
1453 }
1454 }
1455
1456 pub fn description(&self) -> &'static str {
1458 match self {
1459 Self::Advanced => "Advanced",
1460 Self::Extra => "Amateur Extra",
1461 Self::General => "General",
1462 Self::Novice => "Novice",
1463 Self::TechnicianPlus => "Technician Plus",
1464 Self::Technician => "Technician",
1465 }
1466 }
1467
1468 pub fn to_u8(&self) -> u8 {
1470 match self {
1471 Self::Advanced => 0,
1472 Self::Extra => 1,
1473 Self::General => 2,
1474 Self::Novice => 3,
1475 Self::TechnicianPlus => 4,
1476 Self::Technician => 5,
1477 }
1478 }
1479
1480 pub fn from_u8(value: u8) -> Option<Self> {
1482 match value {
1483 0 => Some(Self::Advanced),
1484 1 => Some(Self::Extra),
1485 2 => Some(Self::General),
1486 3 => Some(Self::Novice),
1487 4 => Some(Self::TechnicianPlus),
1488 5 => Some(Self::Technician),
1489 _ => None,
1490 }
1491 }
1492}
1493
1494impl FromStr for OperatorClass {
1495 type Err = Error;
1496
1497 fn from_str(s: &str) -> Result<Self> {
1498 match s.trim().to_uppercase().as_str() {
1499 "A" => Ok(Self::Advanced),
1500 "E" => Ok(Self::Extra),
1501 "G" => Ok(Self::General),
1502 "N" => Ok(Self::Novice),
1503 "P" => Ok(Self::TechnicianPlus),
1504 "T" => Ok(Self::Technician),
1505 _ => Err(Error::InvalidEnumValue {
1506 enum_type: "OperatorClass",
1507 value: s.to_string(),
1508 }),
1509 }
1510 }
1511}
1512
1513impl fmt::Display for OperatorClass {
1514 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1515 write!(f, "{}", self.as_str())
1516 }
1517}
1518
1519#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
1521pub enum EntityType {
1522 TransfereeContact,
1524 LicenseeContact,
1526 AssignorContact,
1528 LesseeContact,
1530 Transferee,
1532 Licensee,
1534 Owner,
1536 Assignor,
1538 Lessee,
1540}
1541
1542impl EntityType {
1543 pub fn as_str(&self) -> &'static str {
1545 match self {
1546 Self::TransfereeContact => "CE",
1547 Self::LicenseeContact => "CL",
1548 Self::AssignorContact => "CR",
1549 Self::LesseeContact => "CS",
1550 Self::Transferee => "E",
1551 Self::Licensee => "L",
1552 Self::Owner => "O",
1553 Self::Assignor => "R",
1554 Self::Lessee => "S",
1555 }
1556 }
1557
1558 pub fn to_u8(&self) -> u8 {
1560 match self {
1561 Self::TransfereeContact => 0,
1562 Self::LicenseeContact => 1,
1563 Self::AssignorContact => 2,
1564 Self::LesseeContact => 3,
1565 Self::Transferee => 4,
1566 Self::Licensee => 5,
1567 Self::Owner => 6,
1568 Self::Assignor => 7,
1569 Self::Lessee => 8,
1570 }
1571 }
1572
1573 pub fn from_u8(value: u8) -> Option<Self> {
1575 match value {
1576 0 => Some(Self::TransfereeContact),
1577 1 => Some(Self::LicenseeContact),
1578 2 => Some(Self::AssignorContact),
1579 3 => Some(Self::LesseeContact),
1580 4 => Some(Self::Transferee),
1581 5 => Some(Self::Licensee),
1582 6 => Some(Self::Owner),
1583 7 => Some(Self::Assignor),
1584 8 => Some(Self::Lessee),
1585 _ => None,
1586 }
1587 }
1588}
1589
1590impl FromStr for EntityType {
1591 type Err = Error;
1592
1593 fn from_str(s: &str) -> Result<Self> {
1594 match s.trim().to_uppercase().as_str() {
1595 "CE" => Ok(Self::TransfereeContact),
1596 "CL" => Ok(Self::LicenseeContact),
1597 "CR" => Ok(Self::AssignorContact),
1598 "CS" => Ok(Self::LesseeContact),
1599 "E" => Ok(Self::Transferee),
1600 "L" => Ok(Self::Licensee),
1601 "O" => Ok(Self::Owner),
1602 "R" => Ok(Self::Assignor),
1603 "S" => Ok(Self::Lessee),
1604 _ => Err(Error::InvalidEnumValue {
1605 enum_type: "EntityType",
1606 value: s.to_string(),
1607 }),
1608 }
1609 }
1610}
1611
1612impl fmt::Display for EntityType {
1613 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1614 write!(f, "{}", self.as_str())
1615 }
1616}
1617
1618#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
1620pub enum RecordType {
1621 A2,
1622 A3,
1623 AC,
1624 AD,
1625 AG,
1626 AH,
1627 AM,
1628 AN,
1629 AP,
1630 AS,
1631 AT,
1632 BC,
1633 BD,
1634 BE,
1635 BF,
1636 BL,
1637 BO,
1638 BT,
1639 CD,
1640 CF,
1641 CG,
1642 CO,
1643 CP,
1644 CS,
1645 EC,
1646 EM,
1647 EN,
1648 F2,
1649 F3,
1650 F4,
1651 F5,
1652 F6,
1653 FA,
1654 FC,
1655 FF,
1656 FR,
1657 FS,
1658 FT,
1659 HD,
1660 HS,
1661 IA,
1662 IF,
1663 IR,
1664 L2,
1665 L3,
1666 L4,
1667 L5,
1668 L6,
1669 LA,
1670 LC,
1671 LD,
1672 LF,
1673 LH,
1674 LL,
1675 LM,
1676 LO,
1677 LS,
1678 MC,
1679 ME,
1680 MF,
1681 MH,
1682 MI,
1683 MK,
1684 MP,
1685 MW,
1686 O2,
1687 OP,
1688 P2,
1689 PA,
1690 PC,
1691 RA,
1692 RC,
1693 RE,
1694 RI,
1695 RZ,
1696 SC,
1697 SE,
1698 SF,
1699 SG,
1700 SH,
1701 SI,
1702 SR,
1703 ST,
1704 SV,
1705 TA,
1706 TL,
1707 TP,
1708 UA,
1709 VC,
1710}
1711
1712impl RecordType {
1713 pub fn as_str(&self) -> &'static str {
1715 match self {
1716 Self::A2 => "A2",
1717 Self::A3 => "A3",
1718 Self::AC => "AC",
1719 Self::AD => "AD",
1720 Self::AG => "AG",
1721 Self::AH => "AH",
1722 Self::AM => "AM",
1723 Self::AN => "AN",
1724 Self::AP => "AP",
1725 Self::AS => "AS",
1726 Self::AT => "AT",
1727 Self::BC => "BC",
1728 Self::BD => "BD",
1729 Self::BE => "BE",
1730 Self::BF => "BF",
1731 Self::BL => "BL",
1732 Self::BO => "BO",
1733 Self::BT => "BT",
1734 Self::CD => "CD",
1735 Self::CF => "CF",
1736 Self::CG => "CG",
1737 Self::CO => "CO",
1738 Self::CP => "CP",
1739 Self::CS => "CS",
1740 Self::EC => "EC",
1741 Self::EM => "EM",
1742 Self::EN => "EN",
1743 Self::F2 => "F2",
1744 Self::F3 => "F3",
1745 Self::F4 => "F4",
1746 Self::F5 => "F5",
1747 Self::F6 => "F6",
1748 Self::FA => "FA",
1749 Self::FC => "FC",
1750 Self::FF => "FF",
1751 Self::FR => "FR",
1752 Self::FS => "FS",
1753 Self::FT => "FT",
1754 Self::HD => "HD",
1755 Self::HS => "HS",
1756 Self::IA => "IA",
1757 Self::IF => "IF",
1758 Self::IR => "IR",
1759 Self::L2 => "L2",
1760 Self::L3 => "L3",
1761 Self::L4 => "L4",
1762 Self::L5 => "L5",
1763 Self::L6 => "L6",
1764 Self::LA => "LA",
1765 Self::LC => "LC",
1766 Self::LD => "LD",
1767 Self::LF => "LF",
1768 Self::LH => "LH",
1769 Self::LL => "LL",
1770 Self::LM => "LM",
1771 Self::LO => "LO",
1772 Self::LS => "LS",
1773 Self::MC => "MC",
1774 Self::ME => "ME",
1775 Self::MF => "MF",
1776 Self::MH => "MH",
1777 Self::MI => "MI",
1778 Self::MK => "MK",
1779 Self::MP => "MP",
1780 Self::MW => "MW",
1781 Self::O2 => "O2",
1782 Self::OP => "OP",
1783 Self::P2 => "P2",
1784 Self::PA => "PA",
1785 Self::PC => "PC",
1786 Self::RA => "RA",
1787 Self::RC => "RC",
1788 Self::RE => "RE",
1789 Self::RI => "RI",
1790 Self::RZ => "RZ",
1791 Self::SC => "SC",
1792 Self::SE => "SE",
1793 Self::SF => "SF",
1794 Self::SG => "SG",
1795 Self::SH => "SH",
1796 Self::SI => "SI",
1797 Self::SR => "SR",
1798 Self::ST => "ST",
1799 Self::SV => "SV",
1800 Self::TA => "TA",
1801 Self::TL => "TL",
1802 Self::TP => "TP",
1803 Self::UA => "UA",
1804 Self::VC => "VC",
1805 }
1806 }
1807
1808 pub fn dat_filename(&self) -> String {
1810 format!("{}.dat", self.as_str())
1811 }
1812}
1813
1814impl FromStr for RecordType {
1815 type Err = Error;
1816
1817 fn from_str(s: &str) -> Result<Self> {
1818 match s.trim().to_uppercase().as_str() {
1819 "A2" => Ok(Self::A2),
1820 "A3" => Ok(Self::A3),
1821 "AC" => Ok(Self::AC),
1822 "AD" => Ok(Self::AD),
1823 "AG" => Ok(Self::AG),
1824 "AH" => Ok(Self::AH),
1825 "AM" => Ok(Self::AM),
1826 "AN" => Ok(Self::AN),
1827 "AP" => Ok(Self::AP),
1828 "AS" => Ok(Self::AS),
1829 "AT" => Ok(Self::AT),
1830 "BC" => Ok(Self::BC),
1831 "BD" => Ok(Self::BD),
1832 "BE" => Ok(Self::BE),
1833 "BF" => Ok(Self::BF),
1834 "BL" => Ok(Self::BL),
1835 "BO" => Ok(Self::BO),
1836 "BT" => Ok(Self::BT),
1837 "CD" => Ok(Self::CD),
1838 "CF" => Ok(Self::CF),
1839 "CG" => Ok(Self::CG),
1840 "CO" => Ok(Self::CO),
1841 "CP" => Ok(Self::CP),
1842 "CS" => Ok(Self::CS),
1843 "EC" => Ok(Self::EC),
1844 "EM" => Ok(Self::EM),
1845 "EN" => Ok(Self::EN),
1846 "F2" => Ok(Self::F2),
1847 "F3" => Ok(Self::F3),
1848 "F4" => Ok(Self::F4),
1849 "F5" => Ok(Self::F5),
1850 "F6" => Ok(Self::F6),
1851 "FA" => Ok(Self::FA),
1852 "FC" => Ok(Self::FC),
1853 "FF" => Ok(Self::FF),
1854 "FR" => Ok(Self::FR),
1855 "FS" => Ok(Self::FS),
1856 "FT" => Ok(Self::FT),
1857 "HD" => Ok(Self::HD),
1858 "HS" => Ok(Self::HS),
1859 "IA" => Ok(Self::IA),
1860 "IF" => Ok(Self::IF),
1861 "IR" => Ok(Self::IR),
1862 "L2" => Ok(Self::L2),
1863 "L3" => Ok(Self::L3),
1864 "L4" => Ok(Self::L4),
1865 "L5" => Ok(Self::L5),
1866 "L6" => Ok(Self::L6),
1867 "LA" => Ok(Self::LA),
1868 "LC" => Ok(Self::LC),
1869 "LD" => Ok(Self::LD),
1870 "LF" => Ok(Self::LF),
1871 "LH" => Ok(Self::LH),
1872 "LL" => Ok(Self::LL),
1873 "LM" => Ok(Self::LM),
1874 "LO" => Ok(Self::LO),
1875 "LS" => Ok(Self::LS),
1876 "MC" => Ok(Self::MC),
1877 "ME" => Ok(Self::ME),
1878 "MF" => Ok(Self::MF),
1879 "MH" => Ok(Self::MH),
1880 "MI" => Ok(Self::MI),
1881 "MK" => Ok(Self::MK),
1882 "MP" => Ok(Self::MP),
1883 "MW" => Ok(Self::MW),
1884 "O2" => Ok(Self::O2),
1885 "OP" => Ok(Self::OP),
1886 "P2" => Ok(Self::P2),
1887 "PA" => Ok(Self::PA),
1888 "PC" => Ok(Self::PC),
1889 "RA" => Ok(Self::RA),
1890 "RC" => Ok(Self::RC),
1891 "RE" => Ok(Self::RE),
1892 "RI" => Ok(Self::RI),
1893 "RZ" => Ok(Self::RZ),
1894 "SC" => Ok(Self::SC),
1895 "SE" => Ok(Self::SE),
1896 "SF" => Ok(Self::SF),
1897 "SG" => Ok(Self::SG),
1898 "SH" => Ok(Self::SH),
1899 "SI" => Ok(Self::SI),
1900 "SR" => Ok(Self::SR),
1901 "ST" => Ok(Self::ST),
1902 "SV" => Ok(Self::SV),
1903 "TA" => Ok(Self::TA),
1904 "TL" => Ok(Self::TL),
1905 "TP" => Ok(Self::TP),
1906 "UA" => Ok(Self::UA),
1907 "VC" => Ok(Self::VC),
1908 _ => Err(Error::InvalidRecordType(s.to_string())),
1909 }
1910 }
1911}
1912
1913impl fmt::Display for RecordType {
1914 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1915 write!(f, "{}", self.as_str())
1916 }
1917}
1918
1919#[cfg(test)]
1920mod tests {
1921 use super::*;
1922
1923 #[test]
1924 fn test_radio_service_roundtrip() {
1925 let codes = [
1927 "AA", "AB", "AC", "AD", "AF", "AH", "AI", "AL", "AN", "AR", "AS", "AT", "AW", "BA",
1928 "BB", "BC", "BR", "BS", "CA", "CB", "CD", "CE", "CF", "CG", "CJ", "CL", "CM", "CN",
1929 "CO", "CP", "CR", "CT", "CW", "CX", "CY", "CZ", "DV", "ED", "GB", "GC", "GE", "GF",
1930 "GI", "GJ", "GL", "GM", "GO", "GP", "GR", "GS", "GU", "GW", "GX", "HA", "HV", "IG",
1931 "IK", "IQ", "LD", "LN", "LP", "LS", "LV", "LW", "MA", "MC", "MD", "MG", "MK", "MM",
1932 "MR", "MS", "MW", "NC", "NN", "OW", "PA", "PB", "PC", "PE", "PF", "PK", "PL", "PM",
1933 "PW", "QA", "QD", "QM", "QO", "QQ", "QT", "RP", "RR", "RS", "SA", "SB", "SE", "SG",
1934 "SL", "SP", "SY", "TB", "TC", "TI", "TN", "TP", "TS", "TT", "TZ", "UM", "UU", "VX",
1935 "WA", "WM", "WP", "WR", "WS", "WT", "WU", "WX", "WY", "WZ", "YB", "YC", "YD", "YE",
1936 "YF", "YG", "YH", "YI", "YJ", "YK", "YL", "YM", "YO", "YP", "YS", "YU", "YW", "YX",
1937 "ZA", "ZV",
1938 ];
1939 for code in codes {
1940 let service: RadioService = code
1941 .parse()
1942 .unwrap_or_else(|_| panic!("Failed to parse RadioService {}", code));
1943 assert_eq!(service.as_str(), code);
1944 assert_eq!(service.to_string(), code);
1945 }
1946 }
1947
1948 #[test]
1949 fn test_radio_service_amateur() {
1950 assert!(RadioService::HA.is_amateur());
1951 assert!(RadioService::HV.is_amateur());
1952 assert!(!RadioService::AC.is_amateur());
1953 }
1954
1955 #[test]
1956 fn test_radio_service_maritime() {
1957 assert!(RadioService::SA.is_maritime());
1958 assert!(RadioService::SB.is_maritime());
1959 assert!(RadioService::SE.is_maritime());
1960 assert!(RadioService::MA.is_maritime());
1961 assert!(RadioService::MC.is_maritime());
1962 assert!(!RadioService::HA.is_maritime());
1963 assert!(!RadioService::AC.is_maritime());
1964 }
1965
1966 #[test]
1967 fn test_radio_service_aircraft() {
1968 assert!(RadioService::AC.is_aircraft());
1969 assert!(RadioService::AF.is_aircraft());
1970 assert!(!RadioService::HA.is_aircraft());
1971 assert!(!RadioService::SA.is_aircraft());
1972 }
1973
1974 #[test]
1975 fn test_radio_service_description() {
1976 let all_services = [
1978 RadioService::AA,
1979 RadioService::AB,
1980 RadioService::AC,
1981 RadioService::AD,
1982 RadioService::AF,
1983 RadioService::AH,
1984 RadioService::AI,
1985 RadioService::AL,
1986 RadioService::AN,
1987 RadioService::AR,
1988 RadioService::AS,
1989 RadioService::AT,
1990 RadioService::AW,
1991 RadioService::BA,
1992 RadioService::BB,
1993 RadioService::BC,
1994 RadioService::BR,
1995 RadioService::BS,
1996 RadioService::CA,
1997 RadioService::CB,
1998 RadioService::CD,
1999 RadioService::CE,
2000 RadioService::CF,
2001 RadioService::CG,
2002 RadioService::CJ,
2003 RadioService::CL,
2004 RadioService::CM,
2005 RadioService::CN,
2006 RadioService::CO,
2007 RadioService::CP,
2008 RadioService::CR,
2009 RadioService::CT,
2010 RadioService::CW,
2011 RadioService::CX,
2012 RadioService::CY,
2013 RadioService::CZ,
2014 RadioService::DV,
2015 RadioService::ED,
2016 RadioService::GB,
2017 RadioService::GC,
2018 RadioService::GE,
2019 RadioService::GF,
2020 RadioService::GI,
2021 RadioService::GJ,
2022 RadioService::GL,
2023 RadioService::GM,
2024 RadioService::GO,
2025 RadioService::GP,
2026 RadioService::GR,
2027 RadioService::GS,
2028 RadioService::GU,
2029 RadioService::GW,
2030 RadioService::GX,
2031 RadioService::HA,
2032 RadioService::HV,
2033 RadioService::IG,
2034 RadioService::IK,
2035 RadioService::IQ,
2036 RadioService::LD,
2037 RadioService::LN,
2038 RadioService::LP,
2039 RadioService::LS,
2040 RadioService::LV,
2041 RadioService::LW,
2042 RadioService::MA,
2043 RadioService::MC,
2044 RadioService::MD,
2045 RadioService::MG,
2046 RadioService::MK,
2047 RadioService::MM,
2048 RadioService::MR,
2049 RadioService::MS,
2050 RadioService::MW,
2051 RadioService::NC,
2052 RadioService::NN,
2053 RadioService::OW,
2054 RadioService::PA,
2055 RadioService::PB,
2056 RadioService::PC,
2057 RadioService::PE,
2058 RadioService::PF,
2059 RadioService::PK,
2060 RadioService::PL,
2061 RadioService::PM,
2062 RadioService::PW,
2063 RadioService::QA,
2064 RadioService::QD,
2065 RadioService::QM,
2066 RadioService::QO,
2067 RadioService::QQ,
2068 RadioService::QT,
2069 RadioService::RP,
2070 RadioService::RR,
2071 RadioService::RS,
2072 RadioService::SA,
2073 RadioService::SB,
2074 RadioService::SE,
2075 RadioService::SG,
2076 RadioService::SL,
2077 RadioService::SP,
2078 RadioService::SY,
2079 RadioService::TB,
2080 RadioService::TC,
2081 RadioService::TI,
2082 RadioService::TN,
2083 RadioService::TP,
2084 RadioService::TS,
2085 RadioService::TT,
2086 RadioService::TZ,
2087 RadioService::UM,
2088 RadioService::UU,
2089 RadioService::VX,
2090 RadioService::WA,
2091 RadioService::WM,
2092 RadioService::WP,
2093 RadioService::WR,
2094 RadioService::WS,
2095 RadioService::WT,
2096 RadioService::WU,
2097 RadioService::WX,
2098 RadioService::WY,
2099 RadioService::WZ,
2100 RadioService::YB,
2101 RadioService::YC,
2102 RadioService::YD,
2103 RadioService::YE,
2104 RadioService::YF,
2105 RadioService::YG,
2106 RadioService::YH,
2107 RadioService::YI,
2108 RadioService::YJ,
2109 RadioService::YK,
2110 RadioService::YL,
2111 RadioService::YM,
2112 RadioService::YO,
2113 RadioService::YP,
2114 RadioService::YS,
2115 RadioService::YU,
2116 RadioService::YW,
2117 RadioService::YX,
2118 RadioService::ZA,
2119 RadioService::ZV,
2120 ];
2121 for service in all_services {
2122 let desc = service.description();
2123 assert!(
2124 !desc.is_empty(),
2125 "RadioService::{:?} has empty description",
2126 service
2127 );
2128 }
2129
2130 assert_eq!(RadioService::HA.description(), "Amateur");
2132 assert_eq!(RadioService::HV.description(), "Vanity (Amateur)");
2133 assert_eq!(
2134 RadioService::ZA.description(),
2135 "General Mobile Radio (GMRS)"
2136 );
2137 assert_eq!(RadioService::AC.description(), "Aircraft");
2138 }
2139
2140 #[test]
2141 fn test_radio_service_invalid() {
2142 let result: Result<RadioService> = "XX".parse();
2143 assert!(result.is_err());
2144 }
2145
2146 #[test]
2147 fn test_radio_service_case_insensitive() {
2148 let upper: RadioService = "HA".parse().unwrap();
2149 let lower: RadioService = "ha".parse().unwrap();
2150 let mixed: RadioService = "Ha".parse().unwrap();
2151 assert_eq!(upper, lower);
2152 assert_eq!(lower, mixed);
2153 }
2154
2155 #[test]
2156 fn test_operator_class_roundtrip() {
2157 for code in ["A", "E", "G", "N", "P", "T"] {
2158 let class: OperatorClass = code.parse().unwrap();
2159 assert_eq!(class.as_str(), code);
2160 assert_eq!(class.to_string(), code);
2161 }
2162 }
2163
2164 #[test]
2165 fn test_operator_class_description() {
2166 assert_eq!(OperatorClass::Extra.description(), "Amateur Extra");
2167 assert_eq!(OperatorClass::Advanced.description(), "Advanced");
2168 assert_eq!(OperatorClass::General.description(), "General");
2169 assert_eq!(OperatorClass::Technician.description(), "Technician");
2170 assert_eq!(
2171 OperatorClass::TechnicianPlus.description(),
2172 "Technician Plus"
2173 );
2174 assert_eq!(OperatorClass::Novice.description(), "Novice");
2175 }
2176
2177 #[test]
2178 fn test_operator_class_invalid() {
2179 let result: Result<OperatorClass> = "X".parse();
2180 assert!(result.is_err());
2181 }
2182
2183 #[test]
2184 fn test_operator_class_case_insensitive() {
2185 let upper: OperatorClass = "E".parse().unwrap();
2186 let lower: OperatorClass = "e".parse().unwrap();
2187 assert_eq!(upper, lower);
2188 }
2189
2190 #[test]
2191 fn test_license_status_roundtrip() {
2192 for code in ["A", "C", "E", "L", "P", "T", "X"] {
2193 let status: LicenseStatus = code.parse().unwrap();
2194 assert_eq!(status.as_str(), code);
2195 assert_eq!(status.to_string(), code);
2196 }
2197 }
2198
2199 #[test]
2200 fn test_license_status_is_active() {
2201 assert!(LicenseStatus::Active.is_active());
2202 assert!(!LicenseStatus::Expired.is_active());
2203 assert!(!LicenseStatus::Cancelled.is_active());
2204 assert!(!LicenseStatus::Terminated.is_active());
2205 assert!(!LicenseStatus::PendingLegalStatus.is_active());
2206 assert!(!LicenseStatus::ParentStationCancelled.is_active());
2207 assert!(!LicenseStatus::TermPending.is_active());
2208 }
2209
2210 #[test]
2211 fn test_license_status_invalid() {
2212 let result: Result<LicenseStatus> = "Z".parse();
2213 assert!(result.is_err());
2214 }
2215
2216 #[test]
2217 fn test_license_status_case_insensitive() {
2218 let upper: LicenseStatus = "A".parse().unwrap();
2219 let lower: LicenseStatus = "a".parse().unwrap();
2220 assert_eq!(upper, lower);
2221 }
2222
2223 #[test]
2224 fn test_application_purpose_roundtrip() {
2225 let codes = [
2226 "AA", "AM", "AR", "AU", "CA", "CB", "DC", "DU", "EX", "HA", "LC", "LE", "LM", "LN",
2227 "LT", "LU", "MD", "NE", "NT", "RE", "RL", "RM", "RO", "TC", "WD",
2228 ];
2229 for code in codes {
2230 let purpose: ApplicationPurpose = code
2231 .parse()
2232 .unwrap_or_else(|_| panic!("Failed to parse ApplicationPurpose {}", code));
2233 assert_eq!(purpose.as_str(), code);
2234 assert_eq!(purpose.to_string(), code);
2235 }
2236 }
2237
2238 #[test]
2239 fn test_application_purpose_specific_values() {
2240 assert_eq!(ApplicationPurpose::AssignmentOfAuthorization.as_str(), "AA");
2241 assert_eq!(ApplicationPurpose::New.as_str(), "NE");
2242 assert_eq!(ApplicationPurpose::RenewalOnly.as_str(), "RO");
2243 assert_eq!(ApplicationPurpose::Modification.as_str(), "MD");
2244 assert_eq!(ApplicationPurpose::Withdrawal.as_str(), "WD");
2245 }
2246
2247 #[test]
2248 fn test_application_purpose_invalid() {
2249 let result: Result<ApplicationPurpose> = "XX".parse();
2250 assert!(result.is_err());
2251 }
2252
2253 #[test]
2254 fn test_application_purpose_case_insensitive() {
2255 let upper: ApplicationPurpose = "NE".parse().unwrap();
2256 let lower: ApplicationPurpose = "ne".parse().unwrap();
2257 let mixed: ApplicationPurpose = "Ne".parse().unwrap();
2258 assert_eq!(upper, lower);
2259 assert_eq!(lower, mixed);
2260 }
2261
2262 #[test]
2263 fn test_application_status_roundtrip() {
2264 let codes = [
2265 "1", "2", "A", "C", "D", "E", "G", "H", "I", "J", "K", "M", "N", "P", "Q", "R", "S",
2266 "T", "U", "W", "X", "Y",
2267 ];
2268 for code in codes {
2269 let status: ApplicationStatus = code
2270 .parse()
2271 .unwrap_or_else(|_| panic!("Failed to parse ApplicationStatus {}", code));
2272 assert_eq!(status.as_str(), code);
2273 assert_eq!(status.to_string(), code);
2274 }
2275 }
2276
2277 #[test]
2278 fn test_application_status_specific_values() {
2279 assert_eq!(ApplicationStatus::Submitted.as_str(), "1");
2280 assert_eq!(ApplicationStatus::Pending.as_str(), "2");
2281 assert_eq!(ApplicationStatus::Granted.as_str(), "G");
2282 assert_eq!(ApplicationStatus::Withdrawn.as_str(), "W");
2283 assert_eq!(ApplicationStatus::Terminated.as_str(), "T");
2284 assert_eq!(ApplicationStatus::HasProblems.as_str(), "Y");
2285 }
2286
2287 #[test]
2288 fn test_application_status_invalid() {
2289 let result: Result<ApplicationStatus> = "Z".parse();
2290 assert!(result.is_err());
2291 }
2292
2293 #[test]
2294 fn test_application_status_case_insensitive() {
2295 let upper: ApplicationStatus = "G".parse().unwrap();
2296 let lower: ApplicationStatus = "g".parse().unwrap();
2297 assert_eq!(upper, lower);
2298 }
2299
2300 #[test]
2301 fn test_entity_type_roundtrip() {
2302 let codes = ["CE", "CL", "CR", "CS", "E", "L", "O", "R", "S"];
2303 for code in codes {
2304 let entity: EntityType = code
2305 .parse()
2306 .unwrap_or_else(|_| panic!("Failed to parse EntityType {}", code));
2307 assert_eq!(entity.as_str(), code);
2308 assert_eq!(entity.to_string(), code);
2309 }
2310 }
2311
2312 #[test]
2313 fn test_entity_type_specific_values() {
2314 assert_eq!(EntityType::Licensee.as_str(), "L");
2315 assert_eq!(EntityType::LicenseeContact.as_str(), "CL");
2316 assert_eq!(EntityType::Transferee.as_str(), "E");
2317 assert_eq!(EntityType::TransfereeContact.as_str(), "CE");
2318 assert_eq!(EntityType::Owner.as_str(), "O");
2319 assert_eq!(EntityType::Assignor.as_str(), "R");
2320 assert_eq!(EntityType::Lessee.as_str(), "S");
2321 }
2322
2323 #[test]
2324 fn test_entity_type_invalid() {
2325 let result: Result<EntityType> = "XX".parse();
2326 assert!(result.is_err());
2327 }
2328
2329 #[test]
2330 fn test_entity_type_case_insensitive() {
2331 let upper: EntityType = "L".parse().unwrap();
2332 let lower: EntityType = "l".parse().unwrap();
2333 assert_eq!(upper, lower);
2334 }
2335
2336 #[test]
2337 fn test_record_type_dat_filename() {
2338 assert_eq!(RecordType::HD.dat_filename(), "HD.dat");
2339 assert_eq!(RecordType::AM.dat_filename(), "AM.dat");
2340 assert_eq!(RecordType::EN.dat_filename(), "EN.dat");
2341 }
2342
2343 #[test]
2344 fn test_all_record_types_parse() {
2345 let codes = [
2346 "A2", "A3", "AC", "AD", "AG", "AH", "AM", "AN", "AP", "AS", "AT", "BC", "BD", "BE",
2347 "BF", "BL", "BO", "BT", "CD", "CF", "CG", "CO", "CP", "CS", "EC", "EM", "EN", "F2",
2348 "F3", "F4", "F5", "F6", "FA", "FC", "FF", "FR", "FS", "FT", "HD", "HS", "IA", "IF",
2349 "IR", "L2", "L3", "L4", "L5", "L6", "LA", "LC", "LD", "LF", "LH", "LL", "LM", "LO",
2350 "LS", "MC", "ME", "MF", "MH", "MI", "MK", "MP", "MW", "O2", "OP", "P2", "PA", "PC",
2351 "RA", "RC", "RE", "RI", "RZ", "SC", "SE", "SF", "SG", "SH", "SI", "SR", "ST", "SV",
2352 "TA", "TL", "TP", "UA", "VC",
2353 ];
2354
2355 for code in codes {
2356 let rt: RecordType = code
2357 .parse()
2358 .unwrap_or_else(|_| panic!("Failed to parse {}", code));
2359 assert_eq!(rt.as_str(), code);
2360 assert_eq!(rt.to_string(), code);
2361 }
2362 }
2363
2364 #[test]
2365 fn test_record_type_invalid() {
2366 let result: Result<RecordType> = "XX".parse();
2367 assert!(result.is_err());
2368 }
2369
2370 #[test]
2371 fn test_record_type_case_insensitive() {
2372 let upper: RecordType = "HD".parse().unwrap();
2373 let lower: RecordType = "hd".parse().unwrap();
2374 let mixed: RecordType = "Hd".parse().unwrap();
2375 assert_eq!(upper, lower);
2376 assert_eq!(lower, mixed);
2377 }
2378}