1use std::collections::HashMap;
7
8#[derive(Debug, Clone)]
13pub struct SectionNameDict {
14 name_to_id: HashMap<&'static str, &'static str>,
16 id_to_name: HashMap<&'static str, &'static str>,
18}
19
20impl SectionNameDict {
21 pub fn new() -> Self {
23 let mut name_to_id = HashMap::new();
24 let mut id_to_name = HashMap::new();
25
26 let mut add = |name: &'static str, id: &'static str| {
28 name_to_id.insert(name, id);
29 id_to_name.insert(id, name);
30 };
31
32 add("config", "c");
34 add("forge", "f");
35 add("stack", "k");
36 add("style", "y");
37 add("ui", "u");
38 add("media", "m");
39 add("i18n", "i");
40 add("icon", "o");
41 add("font", "t");
42 add("driven", "d");
43 add("generator", "g");
44 add("scripts", "s");
45 add("dependencies", "x");
46 add("js", "j");
47 add("python", "p");
48 add("rust", "r");
49
50 Self {
51 name_to_id,
52 id_to_name,
53 }
54 }
55
56 pub fn name_to_id(&self, name: &str) -> String {
60 self.name_to_id
61 .get(name)
62 .map(|s| s.to_string())
63 .unwrap_or_else(|| name.to_string())
64 }
65
66 pub fn id_to_name(&self, id: &str) -> String {
70 self.id_to_name
71 .get(id)
72 .map(|s| s.to_string())
73 .unwrap_or_else(|| id.to_string())
74 }
75
76 pub fn has_name(&self, name: &str) -> bool {
78 self.name_to_id.contains_key(name)
79 }
80
81 pub fn has_id(&self, id: &str) -> bool {
83 self.id_to_name.contains_key(id)
84 }
85
86 pub fn len(&self) -> usize {
88 self.name_to_id.len()
89 }
90
91 pub fn is_empty(&self) -> bool {
93 self.name_to_id.is_empty()
94 }
95}
96
97impl Default for SectionNameDict {
98 fn default() -> Self {
99 Self::new()
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 #[test]
108 fn test_section_name_dict_has_all_mappings() {
109 let dict = SectionNameDict::new();
110 assert_eq!(dict.len(), 16, "Should have 16 section mappings");
111 }
112
113 #[test]
114 fn test_name_to_id() {
115 let dict = SectionNameDict::new();
116
117 assert_eq!(dict.name_to_id("config"), "c");
118 assert_eq!(dict.name_to_id("forge"), "f");
119 assert_eq!(dict.name_to_id("stack"), "k");
120 assert_eq!(dict.name_to_id("style"), "y");
121 assert_eq!(dict.name_to_id("ui"), "u");
122 assert_eq!(dict.name_to_id("media"), "m");
123 assert_eq!(dict.name_to_id("i18n"), "i");
124 assert_eq!(dict.name_to_id("icon"), "o");
125 assert_eq!(dict.name_to_id("font"), "t");
126 assert_eq!(dict.name_to_id("driven"), "d");
127 assert_eq!(dict.name_to_id("generator"), "g");
128 assert_eq!(dict.name_to_id("scripts"), "s");
129 assert_eq!(dict.name_to_id("dependencies"), "x");
130 assert_eq!(dict.name_to_id("js"), "j");
131 assert_eq!(dict.name_to_id("python"), "p");
132 assert_eq!(dict.name_to_id("rust"), "r");
133 }
134
135 #[test]
136 fn test_id_to_name() {
137 let dict = SectionNameDict::new();
138
139 assert_eq!(dict.id_to_name("c"), "config");
140 assert_eq!(dict.id_to_name("f"), "forge");
141 assert_eq!(dict.id_to_name("k"), "stack");
142 assert_eq!(dict.id_to_name("y"), "style");
143 assert_eq!(dict.id_to_name("u"), "ui");
144 assert_eq!(dict.id_to_name("m"), "media");
145 assert_eq!(dict.id_to_name("i"), "i18n");
146 assert_eq!(dict.id_to_name("o"), "icon");
147 assert_eq!(dict.id_to_name("t"), "font");
148 assert_eq!(dict.id_to_name("d"), "driven");
149 assert_eq!(dict.id_to_name("g"), "generator");
150 assert_eq!(dict.id_to_name("s"), "scripts");
151 assert_eq!(dict.id_to_name("x"), "dependencies");
152 assert_eq!(dict.id_to_name("j"), "js");
153 assert_eq!(dict.id_to_name("p"), "python");
154 assert_eq!(dict.id_to_name("r"), "rust");
155 }
156
157 #[test]
158 fn test_unknown_passthrough() {
159 let dict = SectionNameDict::new();
160
161 assert_eq!(dict.name_to_id("unknown"), "unknown");
163 assert_eq!(dict.name_to_id("custom_section"), "custom_section");
164
165 assert_eq!(dict.id_to_name("z"), "z");
167 assert_eq!(dict.id_to_name("custom"), "custom");
168 }
169
170 #[test]
171 fn test_round_trip() {
172 let dict = SectionNameDict::new();
173
174 let names = [
176 "config",
177 "forge",
178 "stack",
179 "style",
180 "ui",
181 "media",
182 "i18n",
183 "icon",
184 "font",
185 "driven",
186 "generator",
187 "scripts",
188 "dependencies",
189 "js",
190 "python",
191 "rust",
192 ];
193
194 for name in names {
195 let id = dict.name_to_id(name);
196 let back = dict.id_to_name(&id);
197 assert_eq!(back, name, "Round-trip failed for {}", name);
198 }
199 }
200
201 #[test]
202 fn test_has_name_and_id() {
203 let dict = SectionNameDict::new();
204
205 assert!(dict.has_name("forge"));
206 assert!(dict.has_name("style"));
207 assert!(!dict.has_name("unknown"));
208
209 assert!(dict.has_id("f"));
210 assert!(dict.has_id("y"));
211 assert!(!dict.has_id("z"));
212 }
213}