1pub(crate) mod vdm_t1t2t3;
20pub(crate) mod vdm_t4;
21pub(crate) mod vdm_t5;
22pub(crate) mod vdm_t6;
23pub(crate) mod vdm_t9;
24pub(crate) mod vdm_t10;
25pub(crate) mod vdm_t11;
26pub(crate) mod vdm_t12;
27pub(crate) mod vdm_t13;
28pub(crate) mod vdm_t14;
29pub(crate) mod vdm_t15;
30pub(crate) mod vdm_t16;
31pub(crate) mod vdm_t17;
32pub(crate) mod vdm_t18;
33pub(crate) mod vdm_t19;
34pub(crate) mod vdm_t20;
35pub(crate) mod vdm_t21;
36pub(crate) mod vdm_t22;
37pub(crate) mod vdm_t23;
38pub(crate) mod vdm_t24;
39pub(crate) mod vdm_t25;
40pub(crate) mod vdm_t26;
41pub(crate) mod vdm_t27;
42
43use super::*;
44pub use vdm_t4::BaseStationReport;
45pub use vdm_t6::BinaryAddressedMessage;
46pub use vdm_t9::StandardSarAircraftPositionReport;
47pub use vdm_t10::UtcDateInquiry;
48pub use vdm_t12::AddressedSafetyRelatedMessage;
49pub use vdm_t13::SafetyRelatedAcknowledgement;
50pub use vdm_t14::SafetyRelatedBroadcastMessage;
51pub use vdm_t15::{Interrogation, InterrogationCase};
52pub use vdm_t16::AssignmentModeCommand;
53pub use vdm_t17::DgnssBroadcastBinaryMessage;
54pub use vdm_t20::{DataLinkManagementMessage};
55pub use vdm_t21::{AidToNavigationReport, NavAidType};
56pub use vdm_t22::{ChannelManagement};
57pub use vdm_t23::{GroupAssignmentCommand};
58pub use vdm_t25::{SingleSlotBinaryMessage};
59pub use vdm_t26::{MultipleSlotBinaryMessage};
60
61#[derive(Clone, Copy, Debug, PartialEq)]
65pub enum Station {
66 BaseStation, DependentAisBaseStation, MobileStation, AidToNavigationStation, AisReceivingStation, LimitedBaseStation, AisTransmittingStation, RepeaterStation, Other, }
76
77impl Default for Station {
78 fn default() -> Station {
79 Station::Other
80 }
81}
82
83impl core::fmt::Display for Station {
84 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
85 match self {
86 Station::BaseStation => write!(f, "base station"),
87 Station::DependentAisBaseStation => write!(f, "dependent AIS base station"),
88 Station::MobileStation => write!(f, "mobile station"),
89 Station::AidToNavigationStation => write!(f, "aid to navigation station"),
90 Station::AisReceivingStation => write!(f, "ais receiving station"),
91 Station::LimitedBaseStation => write!(f, "limited base station"),
92 Station::AisTransmittingStation => write!(f, "AIS transmitting station"),
93 Station::RepeaterStation => write!(f, "repeater station"),
94 Station::Other => write!(f, "other"),
95 }
96 }
97}
98
99impl core::str::FromStr for Station {
100 type Err = ParseError;
101
102 fn from_str(talker_id: &str) -> Result<Self, Self::Err> {
103 if talker_id.len() < 2 {
104 return Err(ParseError::InvalidSentence(
105 "Invalid station identifier".to_string(),
106 ));
107 }
108 match &talker_id[0..2] {
109 "AB" => Ok(Self::BaseStation),
110 "AD" => Ok(Self::DependentAisBaseStation),
111 "AI" => Ok(Self::MobileStation),
112 "AN" => Ok(Self::AidToNavigationStation),
113 "AR" => Ok(Self::AisReceivingStation),
114 "AS" => Ok(Self::LimitedBaseStation),
115 "AT" => Ok(Self::AisTransmittingStation),
116 "AX" => Ok(Self::RepeaterStation),
117 _ => Ok(Self::Other),
118 }
119 }
120}
121
122#[derive(Default, Clone, Debug, PartialEq)]
126pub struct VesselDynamicData {
127 pub own_vessel: bool,
129
130 pub station: Station,
132
133 pub ais_type: AisClass,
135
136 pub mmsi: u32,
138
139 pub nav_status: NavigationStatus,
142
143 pub rot: Option<f64>,
145
146 pub rot_direction: Option<RotDirection>,
148
149 pub sog_knots: Option<f64>,
151
152 pub high_position_accuracy: bool,
154
155 pub latitude: Option<f64>,
157
158 pub longitude: Option<f64>,
160
161 pub cog: Option<f64>,
163
164 pub heading_true: Option<f64>,
166
167 pub timestamp_seconds: u8,
169
170 pub positioning_system_meta: Option<PositioningSystemMeta>,
172
173 pub current_gnss_position: Option<bool>,
177
178 pub special_manoeuvre: Option<bool>,
181
182 pub raim_flag: bool,
186
187 pub class_b_unit_flag: Option<bool>,
189
190 pub class_b_display: Option<bool>,
194
195 pub class_b_dsc: Option<bool>,
199
200 pub class_b_band_flag: Option<bool>,
205
206 pub class_b_msg22_flag: Option<bool>,
210
211 pub class_b_mode_flag: Option<bool>,
215
216 pub class_b_css_flag: Option<bool>,
220
221 pub radio_status: Option<u32>,
225}
226
227#[derive(Clone, Copy, Debug, PartialEq)]
229pub enum AisClass {
230 Unknown,
232
233 ClassA, ClassB, }
239
240impl Default for AisClass {
241 fn default() -> AisClass {
242 AisClass::Unknown
243 }
244}
245
246impl core::fmt::Display for AisClass {
247 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
248 match self {
249 AisClass::Unknown => write!(f, "unknown"),
250 AisClass::ClassA => write!(f, "Class A"),
251 AisClass::ClassB => write!(f, "Class B"),
252 }
253 }
254}
255
256impl LatLon for VesselDynamicData {
257 fn latitude(&self) -> Option<f64> {
258 self.latitude
259 }
260
261 fn longitude(&self) -> Option<f64> {
262 self.longitude
263 }
264}
265
266#[derive(Clone, Copy, Debug, PartialEq)]
268pub enum NavigationStatus {
269 UnderWayUsingEngine = 0, AtAnchor = 1, NotUnderCommand = 2, RestrictedManoeuverability = 3, ConstrainedByDraught = 4, Moored = 5, Aground = 6, EngagedInFishing = 7, UnderWaySailing = 8, Reserved9 = 9, Reserved10 = 10, Reserved11 = 11, Reserved12 = 12, Reserved13 = 13, AisSartIsActive = 14, NotDefined = 15, }
286impl NavigationStatus {
287 pub fn new(nav_status: u8) -> NavigationStatus {
288 match nav_status {
289 0 => NavigationStatus::UnderWayUsingEngine,
290 1 => NavigationStatus::AtAnchor,
291 2 => NavigationStatus::NotUnderCommand,
292 3 => NavigationStatus::RestrictedManoeuverability,
293 4 => NavigationStatus::ConstrainedByDraught,
294 5 => NavigationStatus::Moored,
295 6 => NavigationStatus::Aground,
296 7 => NavigationStatus::EngagedInFishing,
297 8 => NavigationStatus::UnderWaySailing,
298 9 => NavigationStatus::Reserved9,
299 10 => NavigationStatus::Reserved10,
300 11 => NavigationStatus::Reserved11,
301 12 => NavigationStatus::Reserved12,
302 13 => NavigationStatus::Reserved13,
303 14 => NavigationStatus::AisSartIsActive,
304 15 => NavigationStatus::NotDefined,
305 _ => NavigationStatus::NotDefined,
306 }
307 }
308
309 pub fn to_value(&self) -> u8 {
310 *self as u8
311 }
312}
313
314impl core::fmt::Display for NavigationStatus {
315 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
316 match self {
317 NavigationStatus::UnderWayUsingEngine => write!(f, "under way using engine"),
318 NavigationStatus::AtAnchor => write!(f, "at anchor"),
319 NavigationStatus::NotUnderCommand => write!(f, "not under command"),
320 NavigationStatus::RestrictedManoeuverability => {
321 write!(f, "restricted manoeuverability")
322 }
323 NavigationStatus::ConstrainedByDraught => write!(f, "constrained by draught"),
324 NavigationStatus::Moored => write!(f, "moored"),
325 NavigationStatus::Aground => write!(f, "aground"),
326 NavigationStatus::EngagedInFishing => write!(f, "engaged in fishing"),
327 NavigationStatus::UnderWaySailing => write!(f, "under way sailing"),
328 NavigationStatus::Reserved9 => write!(f, "(reserved9)"),
329 NavigationStatus::Reserved10 => write!(f, "(reserved10)"),
330 NavigationStatus::Reserved11 => write!(f, "(reserved11)"),
331 NavigationStatus::Reserved12 => write!(f, "(reserved12)"),
332 NavigationStatus::Reserved13 => write!(f, "(reserved13)"),
333 NavigationStatus::AisSartIsActive => write!(f, "ais sart is active"),
334 NavigationStatus::NotDefined => write!(f, "(notDefined)"),
335 }
336 }
337}
338
339impl Default for NavigationStatus {
340 fn default() -> NavigationStatus {
341 NavigationStatus::NotDefined
342 }
343}
344
345#[derive(Clone, Copy, Debug, PartialEq)]
349pub enum PositioningSystemMeta {
350 Operative, ManualInputMode,
352 DeadReckoningMode,
353 Inoperative,
354}
355
356impl core::fmt::Display for PositioningSystemMeta {
357 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
358 match self {
359 PositioningSystemMeta::Operative => write!(f, "operative"),
360 PositioningSystemMeta::ManualInputMode => write!(f, "manual input mode"),
361 PositioningSystemMeta::DeadReckoningMode => write!(f, "dead reckoning mode"),
362 PositioningSystemMeta::Inoperative => write!(f, "inoperative"),
363 }
364 }
365}
366
367#[derive(Clone, Copy, Debug, PartialEq)]
371pub enum RotDirection {
372 Port,
374
375 Center,
377
378 Starboard,
380}
381
382impl Default for RotDirection {
383 fn default() -> RotDirection {
384 RotDirection::Center
385 }
386}
387
388impl core::fmt::Display for RotDirection {
389 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
390 match self {
391 RotDirection::Port => write!(f, "port"),
392 RotDirection::Center => write!(f, "center"),
393 RotDirection::Starboard => write!(f, "starboard"),
394 }
395 }
396}
397
398#[derive(Default, Clone, Debug, PartialEq)]
402pub struct VesselStaticData {
403 pub own_vessel: bool,
405
406 pub ais_type: AisClass,
408
409 pub mmsi: u32,
411
412 pub ais_version_indicator: u8,
414
415 pub imo_number: Option<u32>,
417
418 pub call_sign: Option<String>,
420
421 pub name: Option<String>,
423
424 pub ship_type: ShipType,
426
427 pub cargo_type: CargoType,
429
430 pub equipment_vendor_id: Option<String>,
432
433 pub equipment_model: Option<u8>,
435
436 pub equipment_serial_number: Option<u32>,
438
439 pub dimension_to_bow: Option<u16>,
441 pub dimension_to_stern: Option<u16>,
443 pub dimension_to_port: Option<u16>,
445 pub dimension_to_starboard: Option<u16>,
447
448 pub position_fix_type: Option<PositionFixType>,
450
451 pub eta: Option<DateTime<Utc>>,
453
454 pub draught10: Option<u8>,
456
457 pub destination: Option<String>,
459
460 pub mothership_mmsi: Option<u32>,
462}
463
464#[derive(Clone, Copy, Debug, PartialEq)]
468pub enum ShipType {
469 NotAvailable = 0, Reserved1 = 10, WingInGround = 20, Fishing = 30, Towing = 31, TowingLong = 32, DredgingOrUnderwaterOps = 33, DivingOps = 34, MilitaryOps = 35, Sailing = 36, PleasureCraft = 37, Reserved38 = 38, Reserved39 = 39, HighSpeedCraft = 40, Pilot = 50, SearchAndRescue = 51, Tug = 52, PortTender = 53, AntiPollutionEquipment = 54, LawEnforcement = 55, SpareLocal56 = 56, SpareLocal57 = 57, MedicalTransport = 58, Noncombatant = 59, Passenger = 60, Cargo = 70, Tanker = 80, Other = 90, }
498
499impl ShipType {
500 pub fn new(raw: u8) -> ShipType {
502 match raw {
503 0..=9 => ShipType::NotAvailable,
504 10..=19 => ShipType::Reserved1,
505 20..=29 => ShipType::WingInGround,
506
507 30 => ShipType::Fishing,
508 31 => ShipType::Towing,
509 32 => ShipType::TowingLong,
510 33 => ShipType::DredgingOrUnderwaterOps,
511 34 => ShipType::DivingOps,
512 35 => ShipType::MilitaryOps,
513 36 => ShipType::Sailing,
514 37 => ShipType::PleasureCraft,
515 38 => ShipType::Reserved38,
516 39 => ShipType::Reserved39,
517
518 40..=49 => ShipType::HighSpeedCraft,
519
520 50 => ShipType::Pilot,
521 51 => ShipType::SearchAndRescue,
522 52 => ShipType::Tug,
523 53 => ShipType::PortTender,
524 54 => ShipType::AntiPollutionEquipment,
525 55 => ShipType::LawEnforcement,
526 56 => ShipType::SpareLocal56,
527 57 => ShipType::SpareLocal57,
528 58 => ShipType::MedicalTransport,
529 59 => ShipType::Noncombatant,
530
531 60..=69 => ShipType::Passenger,
532 70..=79 => ShipType::Cargo,
533 80..=89 => ShipType::Tanker,
534 90..=99 => ShipType::Other,
535 _ => {
536 warn!("Unexpected ship and cargo type: {}", raw);
537 ShipType::NotAvailable
538 }
539 }
540 }
541
542 pub fn to_value(&self) -> u8 {
543 *self as u8
544 }
545}
546
547impl Default for ShipType {
548 fn default() -> ShipType {
549 ShipType::NotAvailable
550 }
551}
552
553impl core::fmt::Display for ShipType {
554 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
555 match self {
556 ShipType::NotAvailable => write!(f, "(not available)"),
557 ShipType::Reserved1 => write!(f, "(reserved)"),
558 ShipType::WingInGround => write!(f, "wing in ground"),
559 ShipType::Fishing => write!(f, "fishing"),
560 ShipType::Towing => write!(f, "towing"),
561 ShipType::TowingLong => write!(f, "towing, long"),
562 ShipType::DredgingOrUnderwaterOps => write!(f, "dredging or underwater ops"),
563 ShipType::DivingOps => write!(f, "diving ops"),
564 ShipType::MilitaryOps => write!(f, "military ops"),
565 ShipType::Sailing => write!(f, "sailing"),
566 ShipType::PleasureCraft => write!(f, "pleasure craft"),
567 ShipType::Reserved38 => write!(f, "(reserved)"),
568 ShipType::Reserved39 => write!(f, "(reserved)"),
569 ShipType::HighSpeedCraft => write!(f, "high-speed craft"),
570 ShipType::Pilot => write!(f, "pilot"),
571 ShipType::SearchAndRescue => write!(f, "search and rescue"),
572 ShipType::Tug => write!(f, "tug"),
573 ShipType::PortTender => write!(f, "port tender"),
574 ShipType::AntiPollutionEquipment => write!(f, "anti-pollution equipment"),
575 ShipType::LawEnforcement => write!(f, "law enforcement"),
576 ShipType::SpareLocal56 => write!(f, "(local)"),
577 ShipType::SpareLocal57 => write!(f, "(local)"),
578 ShipType::MedicalTransport => write!(f, "medical transport"),
579 ShipType::Noncombatant => write!(f, "noncombatant"),
580 ShipType::Passenger => write!(f, "passenger"),
581 ShipType::Cargo => write!(f, "cargo"),
582 ShipType::Tanker => write!(f, "tanker"),
583 ShipType::Other => write!(f, "other"),
584 }
585 }
586}
587
588#[derive(Clone, Copy, Debug, PartialEq)]
592pub enum CargoType {
593 Undefined = 10, HazardousCategoryA = 11, HazardousCategoryB = 12, HazardousCategoryC = 13, HazardousCategoryD = 14, Reserved5 = 15, Reserved6 = 16, Reserved7 = 17, Reserved8 = 18, Reserved9 = 19, }
604
605impl CargoType {
606 pub fn new(raw: u8) -> CargoType {
608 match raw {
609 10 | 20 | 40 | 60 | 70 | 80 | 90 => CargoType::Undefined,
610 11 | 21 | 41 | 61 | 71 | 81 | 91 => CargoType::HazardousCategoryA,
611 12 | 22 | 42 | 62 | 72 | 82 | 92 => CargoType::HazardousCategoryB,
612 13 | 23 | 43 | 63 | 73 | 83 | 93 => CargoType::HazardousCategoryC,
613 14 | 24 | 44 | 64 | 74 | 84 | 94 => CargoType::HazardousCategoryD,
614 15 | 25 | 45 | 65 | 75 | 85 | 95 => CargoType::Reserved5,
615 16 | 26 | 46 | 66 | 76 | 86 | 96 => CargoType::Reserved6,
616 17 | 27 | 47 | 67 | 77 | 87 | 97 => CargoType::Reserved7,
617 18 | 28 | 48 | 68 | 78 | 88 | 98 => CargoType::Reserved8,
618 19 | 29 | 49 | 69 | 79 | 89 | 99 => CargoType::Reserved9,
619 _ => {
620 warn!("Unexpected ship and cargo type: {}", raw);
621 CargoType::Undefined
622 }
623 }
624 }
625
626 pub fn to_value(&self) -> u8 {
627 *self as u8
628 }
629}
630
631impl core::fmt::Display for CargoType {
632 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
633 match self {
634 CargoType::Undefined => write!(f, "undefined"),
635 CargoType::HazardousCategoryA => write!(f, "hazardous category A"),
636 CargoType::HazardousCategoryB => write!(f, "hazardous category B"),
637 CargoType::HazardousCategoryC => write!(f, "hazardous category C"),
638 CargoType::HazardousCategoryD => write!(f, "hazardous category D"),
639 CargoType::Reserved5 => write!(f, "(reserved)"),
640 CargoType::Reserved6 => write!(f, "(reserved)"),
641 CargoType::Reserved7 => write!(f, "(reserved)"),
642 CargoType::Reserved8 => write!(f, "(reserved)"),
643 CargoType::Reserved9 => write!(f, "(reserved)"),
644 }
645 }
646}
647
648impl Default for CargoType {
649 fn default() -> CargoType {
650 CargoType::Undefined
651 }
652}
653
654#[derive(Clone, Copy, Debug, PartialEq)]
658pub enum PositionFixType {
659 Undefined = 0, GPS = 1, GLONASS = 2, GPSGLONASS = 3, LoranC = 4, Chayka = 5, IntegratedNavigationSystem = 6, Surveyed = 7, Galileo = 8, }
669
670impl PositionFixType {
671 pub fn new(raw: u8) -> PositionFixType {
672 match raw {
673 0 => PositionFixType::Undefined,
674 1 => PositionFixType::GPS,
675 2 => PositionFixType::GLONASS,
676 3 => PositionFixType::GPSGLONASS,
677 4 => PositionFixType::LoranC,
678 5 => PositionFixType::Chayka,
679 6 => PositionFixType::IntegratedNavigationSystem,
680 7 => PositionFixType::Surveyed,
681 8 => PositionFixType::Galileo,
682 _ => {
683 warn!("Unrecognized position fix type: {}", raw);
684 PositionFixType::Undefined
685 }
686 }
687 }
688
689 pub fn to_value(&self) -> u8 {
690 *self as u8
691 }
692}
693
694impl core::fmt::Display for PositionFixType {
695 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
696 match self {
697 PositionFixType::Undefined => write!(f, "undefined"),
698 PositionFixType::GPS => write!(f, "GPS"),
699 PositionFixType::GLONASS => write!(f, "GLONASS"),
700 PositionFixType::GPSGLONASS => write!(f, "GPS/GLONASS"),
701 PositionFixType::LoranC => write!(f, "Loran-C"),
702 PositionFixType::Chayka => write!(f, "Chayka"),
703 PositionFixType::IntegratedNavigationSystem => {
704 write!(f, "integrated navigation system")
705 }
706 PositionFixType::Surveyed => write!(f, "surveyed"),
707 PositionFixType::Galileo => write!(f, "Galileo"),
708 }
709 }
710}
711
712impl VesselStaticData {
713 pub fn country(&self) -> Option<&'static str> {
715 match self.mmsi / 1000000 {
716 201 => Some("AL"), 202 => Some("AD"), 203 => Some("AT"), 204 => Some("PT"), 205 => Some("BE"), 206 => Some("BY"), 207 => Some("BG"), 208 => Some("VA"), 209 => Some("CY"), 210 => Some("CY"), 211 => Some("DE"), 212 => Some("CY"), 213 => Some("GE"), 214 => Some("MD"), 215 => Some("MT"), 216 => Some("AM"), 218 => Some("DE"), 219 => Some("DK"), 220 => Some("DK"), 224 => Some("ES"), 225 => Some("ES"), 226 => Some("FR"), 227 => Some("FR"), 228 => Some("FR"), 229 => Some("MT"), 230 => Some("FI"), 231 => Some("FO"), 232 => Some("GB"), 233 => Some("GB"), 234 => Some("GB"), 235 => Some("GB"), 236 => Some("GI"), 237 => Some("GR"), 238 => Some("HR"), 239 => Some("GR"), 240 => Some("GR"), 241 => Some("GR"), 242 => Some("MA"), 243 => Some("HU"), 244 => Some("NL"), 245 => Some("NL"), 246 => Some("NL"), 247 => Some("IT"), 248 => Some("MT"), 249 => Some("MT"), 250 => Some("IE"), 251 => Some("IS"), 252 => Some("LI"), 253 => Some("LU"), 254 => Some("MC"), 255 => Some("PT"), 256 => Some("MT"), 257 => Some("NO"), 258 => Some("NO"), 259 => Some("NO"), 261 => Some("PL"), 262 => Some("ME"), 263 => Some("PT"), 264 => Some("RO"), 265 => Some("SE"), 266 => Some("SE"), 267 => Some("SK"), 268 => Some("SM"), 269 => Some("CH"), 270 => Some("CZ"), 271 => Some("TR"), 272 => Some("UA"), 273 => Some("RU"), 274 => Some("MK"), 275 => Some("LV"), 276 => Some("EE"), 277 => Some("LT"), 278 => Some("SI"), 279 => Some("RS"), 301 => Some("AI"), 303 => Some("US"), 304 => Some("AG"), 305 => Some("AG"), 306 => Some("BQ"), 307 => Some("AW"), 308 => Some("BS"), 309 => Some("BS"), 310 => Some("BM"), 311 => Some("BS"), 312 => Some("BZ"), 314 => Some("BB"), 316 => Some("CA"), 319 => Some("KY"), 321 => Some("CR"), 323 => Some("CU"), 325 => Some("DM"), 327 => Some("DO"), 329 => Some("GP"), 330 => Some("GD"), 331 => Some("GL"), 332 => Some("GT"), 334 => Some("HN"), 336 => Some("HT"), 338 => Some("US"), 339 => Some("JM"), 341 => Some("KN"), 343 => Some("LC"), 345 => Some("MX"), 347 => Some("MQ"), 348 => Some("MS"), 350 => Some("NI"), 351 => Some("PA"), 352 => Some("PA"), 353 => Some("PA"), 354 => Some("PA"), 355 => Some("PA"), 356 => Some("PA"), 357 => Some("PA"), 358 => Some("PR"), 359 => Some("SV"), 361 => Some("PM"), 362 => Some("TT"), 364 => Some("TC"), 366 => Some("US"), 367 => Some("US"), 368 => Some("US"), 369 => Some("US"), 370 => Some("PA"), 371 => Some("PA"), 372 => Some("PA"), 373 => Some("PA"), 374 => Some("PA"), 375 => Some("VC"), 376 => Some("VC"), 377 => Some("VC"), 378 => Some("VG"), 379 => Some("VI"), 401 => Some("AF"), 403 => Some("SA"), 405 => Some("BD"), 408 => Some("BH"), 410 => Some("BT"), 412 => Some("CN"), 413 => Some("CN"), 414 => Some("CN"), 416 => Some("TW"), 417 => Some("LK"), 419 => Some("IN"), 422 => Some("IR"), 423 => Some("AZ"), 425 => Some("IQ"), 428 => Some("IL"), 431 => Some("JP"), 432 => Some("JP"), 434 => Some("TM"), 436 => Some("KZ"), 437 => Some("UZ"), 438 => Some("JO"), 440 => Some("KR"), 441 => Some("KR"), 443 => Some("PS"), 445 => Some("KR"), 447 => Some("KW"), 450 => Some("LB"), 451 => Some("KG"), 453 => Some("MO"), 455 => Some("MV"), 457 => Some("MN"), 459 => Some("NP"), 461 => Some("OM"), 463 => Some("PK"), 466 => Some("QA"), 468 => Some("SY"), 470 => Some("AE"), 471 => Some("AE"), 472 => Some("TJ"), 473 => Some("YE"), 475 => Some("YE"), 477 => Some("HK"), 478 => Some("BA"), 501 => Some("TF"), 503 => Some("AU"), 506 => Some("MM"), 508 => Some("BN"), 510 => Some("FM"), 511 => Some("PW"), 512 => Some("NZ"), 514 => Some("KH"), 515 => Some("KH"), 516 => Some("CX"), 518 => Some("CK"), 520 => Some("FJ"), 523 => Some("CC"), 525 => Some("ID"), 529 => Some("KI"), 531 => Some("LA"), 533 => Some("MY"), 536 => Some("MP"), 538 => Some("MH"), 540 => Some("NC"), 542 => Some("NU"), 544 => Some("NR"), 546 => Some("PF"), 548 => Some("PH"), 550 => Some("TL"), 553 => Some("PG"), 555 => Some("PN"), 557 => Some("SB"), 559 => Some("AS"), 561 => Some("WS"), 563 => Some("SG"), 564 => Some("SG"), 565 => Some("SG"), 566 => Some("SG"), 567 => Some("TH"), 570 => Some("TO"), 572 => Some("TV"), 574 => Some("VN"), 576 => Some("VU"), 577 => Some("VU"), 578 => Some("WF"), 601 => Some("ZA"), 603 => Some("AO"), 605 => Some("DZ"), 607 => Some("TF"), 608 => Some("SH"), 609 => Some("BI"), 610 => Some("BJ"), 611 => Some("BW"), 612 => Some("CF"), 613 => Some("CM"), 615 => Some("CG"), 616 => Some("KM"), 617 => Some("CV"), 618 => Some("TF"), 619 => Some("CI"), 620 => Some("KM"), 621 => Some("DJ"), 622 => Some("EG"), 624 => Some("ET"), 625 => Some("ER"), 626 => Some("GA"), 627 => Some("GH"), 629 => Some("GM"), 630 => Some("GW"), 631 => Some("GQ"), 632 => Some("GN"), 633 => Some("BF"), 634 => Some("KE"), 635 => Some("TF"), 636 => Some("LR"), 637 => Some("LR"), 638 => Some("SS"), 642 => Some("LY"), 644 => Some("LS"), 645 => Some("MU"), 647 => Some("MG"), 649 => Some("ML"), 650 => Some("MZ"), 654 => Some("MR"), 655 => Some("MW"), 656 => Some("NE"), 657 => Some("NG"), 659 => Some("NA"), 660 => Some("TF"), 661 => Some("RW"), 662 => Some("SD"), 663 => Some("SN"), 664 => Some("SC"), 665 => Some("SH"), 666 => Some("SO"), 667 => Some("SL"), 668 => Some("ST"), 669 => Some("SZ"), 670 => Some("TD"), 671 => Some("TG"), 672 => Some("TN"), 674 => Some("TZ"), 675 => Some("UG"), 676 => Some("CG"), 677 => Some("TZ"), 678 => Some("ZM"), 679 => Some("ZW"), 701 => Some("AR"), 710 => Some("BR"), 720 => Some("BO"), 725 => Some("CL"), 730 => Some("CO"), 735 => Some("EC"), 740 => Some("FK"), 745 => Some("GF"), 750 => Some("GY"), 755 => Some("PY"), 760 => Some("PE"), 765 => Some("SR"), 770 => Some("UY"), 775 => Some("VE"), _ => None,
1012 }
1013 }
1014}