1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4pub const UNKNOWN_CODE: &str = "XX";
6
7pub const UNKNOWN: &str = "Unknown";
9
10#[derive(Clone, Copy, Debug)]
22#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
23pub struct Country {
24 pub code: &'static str,
25 pub name: &'static str,
26}
27
28impl Default for Country {
30 fn default() -> Self {
31 Self {
32 code: UNKNOWN_CODE,
33 name: UNKNOWN,
34 }
35 }
36}
37
38const _: () = {
39 let mut i = 0;
40 while i < COUNTRIES_DATA.len() - 1 {
41 let a = COUNTRIES_DATA[i].code.as_bytes();
42 let b = COUNTRIES_DATA[i + 1].code.as_bytes();
43 assert!(a.len() == 2 && b.len() == 2);
44 let a_val = (a[0] as u16) << 8 | a[1] as u16;
45 let b_val = (b[0] as u16) << 8 | b[1] as u16;
46 assert!(a_val < b_val);
47 i += 1;
48 }
49};
50
51pub const fn countries() -> &'static [Country] {
61 COUNTRIES_DATA
62}
63
64pub const fn name(code: &str) -> &'static str {
77 let code = code.as_bytes();
82 if code.len() != 2 {
83 return UNKNOWN;
84 }
85 let needle = (code[0] as u16) << 8 | code[1] as u16;
86 let mut lo = 0usize;
87 let mut hi = COUNTRIES_DATA.len();
88 while lo < hi {
89 let mid = lo + (hi - lo) / 2;
90 let entry = COUNTRIES_DATA[mid].code.as_bytes();
91 let mid_val = (entry[0] as u16) << 8 | entry[1] as u16;
92 if needle < mid_val {
93 hi = mid;
94 } else if needle > mid_val {
95 lo = mid + 1;
96 } else {
97 return COUNTRIES_DATA[mid].name;
98 }
99 }
100 UNKNOWN
101}
102
103const COUNTRIES_DATA: &[Country] = &[
104 Country {
105 code: "AD",
106 name: "AndorrA",
107 },
108 Country {
109 code: "AE",
110 name: "United Arab Emirates",
111 },
112 Country {
113 code: "AF",
114 name: "Afghanistan",
115 },
116 Country {
117 code: "AG",
118 name: "Antigua and Barbuda",
119 },
120 Country {
121 code: "AI",
122 name: "Anguilla",
123 },
124 Country {
125 code: "AL",
126 name: "Albania",
127 },
128 Country {
129 code: "AM",
130 name: "Armenia",
131 },
132 Country {
133 code: "AN",
134 name: "Netherlands Antilles",
135 },
136 Country {
137 code: "AO",
138 name: "Angola",
139 },
140 Country {
141 code: "AQ",
142 name: "Antarctica",
143 },
144 Country {
145 code: "AR",
146 name: "Argentina",
147 },
148 Country {
149 code: "AS",
150 name: "American Samoa",
151 },
152 Country {
153 code: "AT",
154 name: "Austria",
155 },
156 Country {
157 code: "AU",
158 name: "Australia",
159 },
160 Country {
161 code: "AW",
162 name: "Aruba",
163 },
164 Country {
165 code: "AX",
166 name: "Åland Islands",
167 },
168 Country {
169 code: "AZ",
170 name: "Azerbaijan",
171 },
172 Country {
173 code: "BA",
174 name: "Bosnia and Herzegovina",
175 },
176 Country {
177 code: "BB",
178 name: "Barbados",
179 },
180 Country {
181 code: "BD",
182 name: "Bangladesh",
183 },
184 Country {
185 code: "BE",
186 name: "Belgium",
187 },
188 Country {
189 code: "BF",
190 name: "Burkina Faso",
191 },
192 Country {
193 code: "BG",
194 name: "Bulgaria",
195 },
196 Country {
197 code: "BH",
198 name: "Bahrain",
199 },
200 Country {
201 code: "BI",
202 name: "Burundi",
203 },
204 Country {
205 code: "BJ",
206 name: "Benin",
207 },
208 Country {
209 code: "BL",
210 name: "Saint Barthélemy",
211 },
212 Country {
213 code: "BM",
214 name: "Bermuda",
215 },
216 Country {
217 code: "BN",
218 name: "Brunei Darussalam",
219 },
220 Country {
221 code: "BO",
222 name: "Bolivia",
223 },
224 Country {
225 code: "BQ",
226 name: "Bonaire, Sint Eustatius and Saba",
227 },
228 Country {
229 code: "BR",
230 name: "Brazil",
231 },
232 Country {
233 code: "BS",
234 name: "Bahamas",
235 },
236 Country {
237 code: "BT",
238 name: "Bhutan",
239 },
240 Country {
241 code: "BV",
242 name: "Bouvet Island",
243 },
244 Country {
245 code: "BW",
246 name: "Botswana",
247 },
248 Country {
249 code: "BY",
250 name: "Belarus",
251 },
252 Country {
253 code: "BZ",
254 name: "Belize",
255 },
256 Country {
257 code: "CA",
258 name: "Canada",
259 },
260 Country {
261 code: "CC",
262 name: "Cocos (Keeling) Islands",
263 },
264 Country {
265 code: "CD",
266 name: "Congo, The Democratic Republic of the",
267 },
268 Country {
269 code: "CF",
270 name: "Central African Republic",
271 },
272 Country {
273 code: "CG",
274 name: "Congo",
275 },
276 Country {
277 code: "CH",
278 name: "Switzerland",
279 },
280 Country {
281 code: "CI",
282 name: "Cote D'Ivoire",
283 },
284 Country {
285 code: "CK",
286 name: "Cook Islands",
287 },
288 Country {
289 code: "CL",
290 name: "Chile",
291 },
292 Country {
293 code: "CM",
294 name: "Cameroon",
295 },
296 Country {
297 code: "CN",
298 name: "China",
299 },
300 Country {
301 code: "CO",
302 name: "Colombia",
303 },
304 Country {
305 code: "CR",
306 name: "Costa Rica",
307 },
308 Country {
309 code: "CU",
310 name: "Cuba",
311 },
312 Country {
313 code: "CV",
314 name: "Cape Verde",
315 },
316 Country {
317 code: "CW",
318 name: "Curacao",
319 },
320 Country {
321 code: "CX",
322 name: "Christmas Island",
323 },
324 Country {
325 code: "CY",
326 name: "Cyprus",
327 },
328 Country {
329 code: "CZ",
330 name: "Czech Republic",
331 },
332 Country {
333 code: "DE",
334 name: "Germany",
335 },
336 Country {
337 code: "DJ",
338 name: "Djibouti",
339 },
340 Country {
341 code: "DK",
342 name: "Denmark",
343 },
344 Country {
345 code: "DM",
346 name: "Dominica",
347 },
348 Country {
349 code: "DO",
350 name: "Dominican Republic",
351 },
352 Country {
353 code: "DZ",
354 name: "Algeria",
355 },
356 Country {
357 code: "EC",
358 name: "Ecuador",
359 },
360 Country {
361 code: "EE",
362 name: "Estonia",
363 },
364 Country {
365 code: "EG",
366 name: "Egypt",
367 },
368 Country {
369 code: "EH",
370 name: "Western Sahara",
371 },
372 Country {
373 code: "ER",
374 name: "Eritrea",
375 },
376 Country {
377 code: "ES",
378 name: "Spain",
379 },
380 Country {
381 code: "ET",
382 name: "Ethiopia",
383 },
384 Country {
385 code: "FI",
386 name: "Finland",
387 },
388 Country {
389 code: "FJ",
390 name: "Fiji",
391 },
392 Country {
393 code: "FK",
394 name: "Falkland Islands (Malvinas)",
395 },
396 Country {
397 code: "FM",
398 name: "Micronesia, Federated States of",
399 },
400 Country {
401 code: "FO",
402 name: "Faroe Islands",
403 },
404 Country {
405 code: "FR",
406 name: "France",
407 },
408 Country {
409 code: "GA",
410 name: "Gabon",
411 },
412 Country {
413 code: "GB",
414 name: "United Kingdom",
415 },
416 Country {
417 code: "GD",
418 name: "Grenada",
419 },
420 Country {
421 code: "GE",
422 name: "Georgia",
423 },
424 Country {
425 code: "GF",
426 name: "French Guiana",
427 },
428 Country {
429 code: "GG",
430 name: "Guernsey",
431 },
432 Country {
433 code: "GH",
434 name: "Ghana",
435 },
436 Country {
437 code: "GI",
438 name: "Gibraltar",
439 },
440 Country {
441 code: "GL",
442 name: "Greenland",
443 },
444 Country {
445 code: "GM",
446 name: "Gambia",
447 },
448 Country {
449 code: "GN",
450 name: "Guinea",
451 },
452 Country {
453 code: "GP",
454 name: "Guadeloupe",
455 },
456 Country {
457 code: "GQ",
458 name: "Equatorial Guinea",
459 },
460 Country {
461 code: "GR",
462 name: "Greece",
463 },
464 Country {
465 code: "GS",
466 name: "South Georgia and the South Sandwich Islands",
467 },
468 Country {
469 code: "GT",
470 name: "Guatemala",
471 },
472 Country {
473 code: "GU",
474 name: "Guam",
475 },
476 Country {
477 code: "GW",
478 name: "Guinea-Bissau",
479 },
480 Country {
481 code: "GY",
482 name: "Guyana",
483 },
484 Country {
485 code: "HK",
486 name: "Hong Kong",
487 },
488 Country {
489 code: "HM",
490 name: "Heard Island and Mcdonald Islands",
491 },
492 Country {
493 code: "HN",
494 name: "Honduras",
495 },
496 Country {
497 code: "HR",
498 name: "Croatia",
499 },
500 Country {
501 code: "HT",
502 name: "Haiti",
503 },
504 Country {
505 code: "HU",
506 name: "Hungary",
507 },
508 Country {
509 code: "ID",
510 name: "Indonesia",
511 },
512 Country {
513 code: "IE",
514 name: "Ireland",
515 },
516 Country {
517 code: "IL",
518 name: "Israel",
519 },
520 Country {
521 code: "IM",
522 name: "Isle of Man",
523 },
524 Country {
525 code: "IN",
526 name: "India",
527 },
528 Country {
529 code: "IO",
530 name: "British Indian Ocean Territory",
531 },
532 Country {
533 code: "IQ",
534 name: "Iraq",
535 },
536 Country {
537 code: "IR",
538 name: "Iran, Islamic Republic Of",
539 },
540 Country {
541 code: "IS",
542 name: "Iceland",
543 },
544 Country {
545 code: "IT",
546 name: "Italy",
547 },
548 Country {
549 code: "JE",
550 name: "Jersey",
551 },
552 Country {
553 code: "JM",
554 name: "Jamaica",
555 },
556 Country {
557 code: "JO",
558 name: "Jordan",
559 },
560 Country {
561 code: "JP",
562 name: "Japan",
563 },
564 Country {
565 code: "KE",
566 name: "Kenya",
567 },
568 Country {
569 code: "KG",
570 name: "Kyrgyzstan",
571 },
572 Country {
573 code: "KH",
574 name: "Cambodia",
575 },
576 Country {
577 code: "KI",
578 name: "Kiribati",
579 },
580 Country {
581 code: "KM",
582 name: "Comoros",
583 },
584 Country {
585 code: "KN",
586 name: "Saint Kitts and Nevis",
587 },
588 Country {
589 code: "KP",
590 name: "Korea, Democratic People's Republic of",
591 },
592 Country {
593 code: "KR",
594 name: "Korea, Republic of",
595 },
596 Country {
597 code: "KW",
598 name: "Kuwait",
599 },
600 Country {
601 code: "KY",
602 name: "Cayman Islands",
603 },
604 Country {
605 code: "KZ",
606 name: "Kazakhstan",
607 },
608 Country {
609 code: "LA",
610 name: "Lao People's Democratic Republic",
611 },
612 Country {
613 code: "LB",
614 name: "Lebanon",
615 },
616 Country {
617 code: "LC",
618 name: "Saint Lucia",
619 },
620 Country {
621 code: "LI",
622 name: "Liechtenstein",
623 },
624 Country {
625 code: "LK",
626 name: "Sri Lanka",
627 },
628 Country {
629 code: "LR",
630 name: "Liberia",
631 },
632 Country {
633 code: "LS",
634 name: "Lesotho",
635 },
636 Country {
637 code: "LT",
638 name: "Lithuania",
639 },
640 Country {
641 code: "LU",
642 name: "Luxembourg",
643 },
644 Country {
645 code: "LV",
646 name: "Latvia",
647 },
648 Country {
649 code: "LY",
650 name: "Libyan Arab Jamahiriya",
651 },
652 Country {
653 code: "MA",
654 name: "Morocco",
655 },
656 Country {
657 code: "MC",
658 name: "Monaco",
659 },
660 Country {
661 code: "MD",
662 name: "Moldova, Republic of",
663 },
664 Country {
665 code: "ME",
666 name: "Montenegro",
667 },
668 Country {
669 code: "MF",
670 name: "Saint Martin",
671 },
672 Country {
673 code: "MG",
674 name: "Madagascar",
675 },
676 Country {
677 code: "MH",
678 name: "Marshall Islands",
679 },
680 Country {
681 code: "MK",
682 name: "North Macedonia",
683 },
684 Country {
685 code: "ML",
686 name: "Mali",
687 },
688 Country {
689 code: "MM",
690 name: "Myanmar",
691 },
692 Country {
693 code: "MN",
694 name: "Mongolia",
695 },
696 Country {
697 code: "MO",
698 name: "Macao",
699 },
700 Country {
701 code: "MP",
702 name: "Northern Mariana Islands",
703 },
704 Country {
705 code: "MQ",
706 name: "Martinique",
707 },
708 Country {
709 code: "MR",
710 name: "Mauritania",
711 },
712 Country {
713 code: "MS",
714 name: "Montserrat",
715 },
716 Country {
717 code: "MT",
718 name: "Malta",
719 },
720 Country {
721 code: "MU",
722 name: "Mauritius",
723 },
724 Country {
725 code: "MV",
726 name: "Maldives",
727 },
728 Country {
729 code: "MW",
730 name: "Malawi",
731 },
732 Country {
733 code: "MX",
734 name: "Mexico",
735 },
736 Country {
737 code: "MY",
738 name: "Malaysia",
739 },
740 Country {
741 code: "MZ",
742 name: "Mozambique",
743 },
744 Country {
745 code: "NA",
746 name: "Namibia",
747 },
748 Country {
749 code: "NC",
750 name: "New Caledonia",
751 },
752 Country {
753 code: "NE",
754 name: "Niger",
755 },
756 Country {
757 code: "NF",
758 name: "Norfolk Island",
759 },
760 Country {
761 code: "NG",
762 name: "Nigeria",
763 },
764 Country {
765 code: "NI",
766 name: "Nicaragua",
767 },
768 Country {
769 code: "NL",
770 name: "Netherlands",
771 },
772 Country {
773 code: "NO",
774 name: "Norway",
775 },
776 Country {
777 code: "NP",
778 name: "Nepal",
779 },
780 Country {
781 code: "NR",
782 name: "Nauru",
783 },
784 Country {
785 code: "NU",
786 name: "Niue",
787 },
788 Country {
789 code: "NZ",
790 name: "New Zealand",
791 },
792 Country {
793 code: "OM",
794 name: "Oman",
795 },
796 Country {
797 code: "PA",
798 name: "Panama",
799 },
800 Country {
801 code: "PE",
802 name: "Peru",
803 },
804 Country {
805 code: "PF",
806 name: "French Polynesia",
807 },
808 Country {
809 code: "PG",
810 name: "Papua New Guinea",
811 },
812 Country {
813 code: "PH",
814 name: "Philippines",
815 },
816 Country {
817 code: "PK",
818 name: "Pakistan",
819 },
820 Country {
821 code: "PL",
822 name: "Poland",
823 },
824 Country {
825 code: "PM",
826 name: "Saint Pierre and Miquelon",
827 },
828 Country {
829 code: "PN",
830 name: "Pitcairn",
831 },
832 Country {
833 code: "PR",
834 name: "Puerto Rico",
835 },
836 Country {
837 code: "PS",
838 name: "Palestinian Territory, Occupied",
839 },
840 Country {
841 code: "PT",
842 name: "Portugal",
843 },
844 Country {
845 code: "PW",
846 name: "Palau",
847 },
848 Country {
849 code: "PY",
850 name: "Paraguay",
851 },
852 Country {
853 code: "QA",
854 name: "Qatar",
855 },
856 Country {
857 code: "RE",
858 name: "Reunion",
859 },
860 Country {
861 code: "RO",
862 name: "Romania",
863 },
864 Country {
865 code: "RS",
866 name: "Serbia",
867 },
868 Country {
869 code: "RU",
870 name: "Russian Federation",
871 },
872 Country {
873 code: "RW",
874 name: "Rwanda",
875 },
876 Country {
877 code: "SA",
878 name: "Saudi Arabia",
879 },
880 Country {
881 code: "SB",
882 name: "Solomon Islands",
883 },
884 Country {
885 code: "SC",
886 name: "Seychelles",
887 },
888 Country {
889 code: "SD",
890 name: "Sudan",
891 },
892 Country {
893 code: "SE",
894 name: "Sweden",
895 },
896 Country {
897 code: "SG",
898 name: "Singapore",
899 },
900 Country {
901 code: "SH",
902 name: "Saint Helena",
903 },
904 Country {
905 code: "SI",
906 name: "Slovenia",
907 },
908 Country {
909 code: "SJ",
910 name: "Svalbard and Jan Mayen",
911 },
912 Country {
913 code: "SK",
914 name: "Slovakia",
915 },
916 Country {
917 code: "SL",
918 name: "Sierra Leone",
919 },
920 Country {
921 code: "SM",
922 name: "San Marino",
923 },
924 Country {
925 code: "SN",
926 name: "Senegal",
927 },
928 Country {
929 code: "SO",
930 name: "Somalia",
931 },
932 Country {
933 code: "SR",
934 name: "Suriname",
935 },
936 Country {
937 code: "SS",
938 name: "South Sudan",
939 },
940 Country {
941 code: "ST",
942 name: "Sao Tome and Principe",
943 },
944 Country {
945 code: "SV",
946 name: "El Salvador",
947 },
948 Country {
949 code: "SX",
950 name: "Sint Maarten (Dutch part)",
951 },
952 Country {
953 code: "SY",
954 name: "Syrian Arab Republic",
955 },
956 Country {
957 code: "SZ",
958 name: "Eswatini",
959 },
960 Country {
961 code: "TC",
962 name: "Turks and Caicos Islands",
963 },
964 Country {
965 code: "TD",
966 name: "Chad",
967 },
968 Country {
969 code: "TF",
970 name: "French Southern Territories",
971 },
972 Country {
973 code: "TG",
974 name: "Togo",
975 },
976 Country {
977 code: "TH",
978 name: "Thailand",
979 },
980 Country {
981 code: "TJ",
982 name: "Tajikistan",
983 },
984 Country {
985 code: "TK",
986 name: "Tokelau",
987 },
988 Country {
989 code: "TL",
990 name: "Timor-Leste",
991 },
992 Country {
993 code: "TM",
994 name: "Turkmenistan",
995 },
996 Country {
997 code: "TN",
998 name: "Tunisia",
999 },
1000 Country {
1001 code: "TO",
1002 name: "Tonga",
1003 },
1004 Country {
1005 code: "TR",
1006 name: "Turkey",
1007 },
1008 Country {
1009 code: "TT",
1010 name: "Trinidad and Tobago",
1011 },
1012 Country {
1013 code: "TV",
1014 name: "Tuvalu",
1015 },
1016 Country {
1017 code: "TW",
1018 name: "Taiwan",
1019 },
1020 Country {
1021 code: "TZ",
1022 name: "Tanzania, United Republic of",
1023 },
1024 Country {
1025 code: "UA",
1026 name: "Ukraine",
1027 },
1028 Country {
1029 code: "UG",
1030 name: "Uganda",
1031 },
1032 Country {
1033 code: "UM",
1034 name: "United States Minor Outlying Islands",
1035 },
1036 Country {
1037 code: "US",
1038 name: "United States",
1039 },
1040 Country {
1041 code: "UY",
1042 name: "Uruguay",
1043 },
1044 Country {
1045 code: "UZ",
1046 name: "Uzbekistan",
1047 },
1048 Country {
1049 code: "VA",
1050 name: "Holy See (Vatican City State)",
1051 },
1052 Country {
1053 code: "VC",
1054 name: "Saint Vincent and the Grenadines",
1055 },
1056 Country {
1057 code: "VE",
1058 name: "Venezuela",
1059 },
1060 Country {
1061 code: "VG",
1062 name: "Virgin Islands, British",
1063 },
1064 Country {
1065 code: "VI",
1066 name: "Virgin Islands, U.S.",
1067 },
1068 Country {
1069 code: "VN",
1070 name: "Viet Nam",
1071 },
1072 Country {
1073 code: "VU",
1074 name: "Vanuatu",
1075 },
1076 Country {
1077 code: "WF",
1078 name: "Wallis and Futuna",
1079 },
1080 Country {
1081 code: "WS",
1082 name: "Samoa",
1083 },
1084 Country {
1085 code: "XK",
1086 name: "Kosovo",
1087 },
1088 Country {
1089 code: "YE",
1090 name: "Yemen",
1091 },
1092 Country {
1093 code: "YT",
1094 name: "Mayotte",
1095 },
1096 Country {
1097 code: "ZA",
1098 name: "South Africa",
1099 },
1100 Country {
1101 code: "ZM",
1102 name: "Zambia",
1103 },
1104 Country {
1105 code: "ZW",
1106 name: "Zimbabwe",
1107 },
1108];
1109
1110#[cfg(test)]
1111mod tests {
1112 use super::*;
1113
1114 #[test]
1115 fn known_country() {
1116 assert_eq!(name("FR"), "France");
1117 assert_eq!(name("GB"), "United Kingdom");
1118 assert_eq!(name("US"), "United States");
1119 assert_eq!(name("DE"), "Germany");
1120 }
1121
1122 #[test]
1123 fn unknown_country() {
1124 assert_eq!(name("ZZ"), "Unknown");
1125 assert_eq!(name("??"), "Unknown");
1126 }
1127
1128 #[test]
1129 fn wrong_length() {
1130 assert_eq!(name(""), "Unknown");
1131 assert_eq!(name("F"), "Unknown");
1132 assert_eq!(name("FRA"), "Unknown");
1133 }
1134
1135 #[test]
1136 fn default_country() {
1137 let c = Country::default();
1138 assert_eq!(c.code, "XX");
1139 assert_eq!(c.name, "Unknown");
1140 }
1141
1142 #[test]
1143 fn countries_slice_is_sorted() {
1144 for win in countries().windows(2) {
1145 assert!(win[0].code < win[1].code, "out of order: {} >= {}", win[0].code, win[1].code);
1146 }
1147 }
1148
1149 #[test]
1150 fn correct_entry_count() {
1151 assert_eq!(countries().len(), 251);
1152 }
1153
1154 #[test]
1155 fn round_trip_all() {
1156 for c in countries() {
1157 assert_eq!(name(c.code), c.name, "failed for {}", c.code);
1158 }
1159 }
1160}