1use crate::names::name_to_enum_name;
2use std::fs;
3
4mod names;
5
6const NAMES_DATA: &str = include_str!("../countries-names.txt");
7const CODES_2_DATA: &str = include_str!("../countries-two.txt");
8const CODES_3_DATA: &str = include_str!("../countries-three.txt");
9const COUNTRIES_TO_CONTINENTS: &str = include_str!("../countries-to-continents.txt");
10const DMA: &str = include_str!("../dma.txt");
11
12trait PushMut<T> {
13 fn add(self, item: T) -> Self;
14}
15
16impl<T> PushMut<T> for Vec<T> {
17 fn add(self, item: T) -> Self {
18 let mut new = self;
19 new.push(item);
20 new
21 }
22}
23
24macro_rules! codes {
25 ($data: expr, $enum_names: expr) => {
26 &$data
27 .split('\n')
28 .enumerate()
29 .map(|(i, code)| format!("Country::{} => \"{}\"", $enum_names[i], code))
30 .collect::<Vec<String>>()
31 .join(",\n")
32 };
33}
34
35macro_rules! codes_reverse {
36 ($data: expr, $enum_names: expr) => {{
37 $data
38 .split('\n')
39 .enumerate()
40 .map(|(i, code)| format!("\"{}\" => Some(Country::{})", code, $enum_names[i]))
41 .collect::<Vec<String>>()
42 .add("_ => None".to_string())
43 .join(",\n")
44 }};
45}
46
47macro_rules! _save_content {
48 ($data: expr, $file_name: expr) => {
49 let out_dir = std::env::var("OUT_DIR").unwrap();
50 fs::write(
51 format!("{out_dir}/{}", $file_name),
52 $data
53 )
54 .unwrap();
55 };
56}
57
58macro_rules! save_content {
59 (result $data: expr, $value: expr, $file_name: expr) => {
60 _save_content!(
61 format!(
62 r#"Ok(match {} {{
63 {}
64 }}?)"#,
65 $value,
66 $data
67 ),
68 $file_name
69 )
70 };
71
72 ($data: expr, $value: expr, $file_name: expr) => {
73 _save_content!(
74 format!(
75 r#"match {} {{
76 {}
77 }}"#,
78 $value,
79 $data
80 ),
81 $file_name
82 )
83 };
84}
85
86macro_rules! codes_with_fs_write {
87 (reverse $data: expr, $enum_names: expr, $file_name: expr) => {
88 save_content!(codes_reverse!($data, $enum_names), "value", $file_name);
89 };
90
91 ($data: expr, $enum_names: expr, $file_name: expr) => {
92 save_content!(codes!($data, $enum_names), "self", $file_name);
93 };
94}
95
96pub fn run() {
97 const OFFSET: u8 = 1;
98 let names_by_line = NAMES_DATA.split("\n");
99 let enum_names = names_by_line
100 .clone()
101 .map(name_to_enum_name)
102 .collect::<Vec<String>>();
103
104 let out_dir = std::env::var("OUT_DIR").unwrap();
105
106 let enum_content = &*enum_names.join(", \n\t");
107 fs::write(
108 format!("{out_dir}/countries-enum-values"),
109 format!(
110 r#"
111 #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
112 pub enum Country {{
113 {enum_content}
114 }}"#
115 ),
116 )
117 .unwrap();
118
119 codes_with_fs_write!(CODES_2_DATA, enum_names, "countries-codes-2");
120 codes_with_fs_write!(CODES_3_DATA, enum_names, "countries-codes-3");
121 codes_with_fs_write!(reverse CODES_2_DATA, enum_names, "countries-codes-2-reverse");
122 codes_with_fs_write!(reverse CODES_3_DATA, enum_names, "countries-codes-3-reverse");
123
124 let match_pattern = names_by_line
125 .clone()
126 .enumerate()
127 .map(|(i, name)| format!("Country::{} => f.write_str(\"{name}\")", enum_names[i]))
128 .collect::<Vec<String>>()
129 .join(",\n");
130 save_content!(result match_pattern, "self", "countries-to-names");
131
132 let match_pattern = enum_names
133 .iter()
134 .enumerate()
135 .map(|(i, name)| format!("{} => Some(Country::{name})", i as u8 + OFFSET))
136 .collect::<Vec<String>>()
137 .add("_ => None".to_string())
138 .join(",\n");
139 save_content!(match_pattern, "value", "countries-from-buffer");
140
141 let match_pattern = COUNTRIES_TO_CONTINENTS
142 .split('\n')
143 .enumerate()
144 .map(|(i, continent)| {
145 if continent.is_empty() {
146 format!("Country::{} => None", enum_names[i])
147 } else {
148 format!("Country::{} => Some(Continent::{continent})", enum_names[i])
149 }
150 })
151 .collect::<Vec<String>>()
152 .join(",\n");
153 save_content!(match_pattern, "value", "country-to-continent");
154
155 let match_pattern = DMA.split('\n')
156 .map(|dma| {
157 let data: Vec<&str> = dma.split("; ").collect();
158 format!("{} => f.write_str(\"{}\")", data[0], data[1])
159 })
160 .collect::<Vec<String>>()
161 .add("_ => f.write_str(\"Unknown DMA\")".to_string())
162 .join(",\n");
163 save_content!(match_pattern, "value", "dma-code-to-name");
164}