1use serde::*;
3const ELEMENT_DATA: [(&str, &str); 118] = [
7 ("H", "Hydrogen"),
8 ("He", "Helium"),
9 ("Li", "Lithium"),
10 ("Be", "Beryllium"),
11 ("B", "Boron"),
12 ("C", "Carbon"),
13 ("N", "Nitrogen"),
14 ("O", "Oxygen"),
15 ("F", "Fluorine"),
16 ("Ne", "Neon"),
17 ("Na", "Sodium"),
18 ("Mg", "Magnesium"),
19 ("Al", "Aluminum"),
20 ("Si", "Silicon"),
21 ("P", "Phosphorus"),
22 ("S", "Sulfur"),
23 ("Cl", "Chlorine"),
24 ("Ar", "Argon"),
25 ("K", "Potassium"),
26 ("Ca", "Calcium"),
27 ("Sc", "Scandium"),
28 ("Ti", "Titanium"),
29 ("V", "Vanadium"),
30 ("Cr", "Chromium"),
31 ("Mn", "Manganese"),
32 ("Fe", "Iron"),
33 ("Co", "Cobalt"),
34 ("Ni", "Nickel"),
35 ("Cu", "Copper"),
36 ("Zn", "Zinc"),
37 ("Ga", "Gallium"),
38 ("Ge", "Germanium"),
39 ("As", "Arsenic"),
40 ("Se", "Selenium"),
41 ("Br", "Bromine"),
42 ("Kr", "Krypton"),
43 ("Rb", "Rubidium"),
44 ("Sr", "Strontium"),
45 ("Y", "Yttrium"),
46 ("Zr", "Zirconium"),
47 ("Nb", "Niobium"),
48 ("Mo", "Molybdenum"),
49 ("Tc", "Technetium"),
50 ("Ru", "Ruthenium"),
51 ("Rh", "Rhodium"),
52 ("Pd", "Palladium"),
53 ("Ag", "Silver"),
54 ("Cd", "Cadmium"),
55 ("In", "Indium"),
56 ("Sn", "Tin"),
57 ("Sb", "Antimony"),
58 ("Te", "Tellurium"),
59 ("I", "Iodine"),
60 ("Xe", "Xenon"),
61 ("Cs", "Cesium"),
62 ("Ba", "Barium"),
63 ("La", "Lanthanum"),
64 ("Ce", "Cerium"),
65 ("Pr", "Praesodymium"),
66 ("Nd", "Neodymium"),
67 ("Pm", "Promethium"),
68 ("Sm", "Samarium"),
69 ("Eu", "Europium"),
70 ("Gd", "Gadolinium"),
71 ("Tb", "Terbium"),
72 ("Dy", "Dyprosium"),
73 ("Ho", "Holmium"),
74 ("Er", "Erbium"),
75 ("Tm", "Thulium"),
76 ("Yb", "Ytterbium"),
77 ("Lu", "Lutetium"),
78 ("Hf", "Hafnium"),
79 ("Ta", "Tantalium"),
80 ("W", "Wolfram"),
81 ("Re", "Rhenium"),
82 ("Os", "Osmium"),
83 ("Ir", "Iridium"),
84 ("Pt", "Platinum"),
85 ("Au", "Gold"),
86 ("Hg", "Mercury"),
87 ("Tl", "Thallium"),
88 ("Pb", "Lead"),
89 ("Bi", "Bismuth"),
90 ("Po", "Polonium"),
91 ("At", "Astatine"),
92 ("Rn", "Radon"),
93 ("Fr", "Francium"),
94 ("Ra", "Radium"),
95 ("Ac", "Actinium"),
96 ("Th", "Thorium"),
97 ("Pa", "Protactinium"),
98 ("U", "Uranium"),
99 ("Np", "Neptunium"),
100 ("Pu", "Plutonium"),
101 ("Am", "Americium"),
102 ("Cm", "Curium"),
103 ("Bk", "Berkelium"),
104 ("Cf", "Californium"),
105 ("Es", "Einsteinium"),
106 ("Fm", "Fermium"),
107 ("Mv", "Mendelevium"),
108 ("No", "Nobelium"),
109 ("Lr", "Lawrencium"),
110 ("Rf", "Rutherfordium"),
111 ("Db", "Dubnium"),
112 ("Sg", "Seaborgium"),
113 ("Bh", "Bohrium"),
114 ("Hs", "Hassium"),
115 ("Mt", "Meitnerium"),
116 ("Uun", "Ununnilium"),
117 ("Uuu", "Unununium"),
118 ("Uub", "Ununbium"),
119 ("Uut", "Ununtrium"),
120 ("Uuq", "Ununquadium"),
121 ("Uup", "Ununpentium"),
122 ("Uuh", "Ununhexium"),
123 ("Uus", "Ununseptium"),
124 ("Uuo", "Ununoctium"),
125];
126#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
132pub enum AtomKind {
133 Element(usize),
135
136 Dummy(String),
138}
139
140use self::AtomKind::{Dummy, Element};
141
142impl AtomKind {
143 pub fn symbol(&self) -> &str {
145 match &self {
146 Element(num) => ELEMENT_DATA[num - 1].0,
147 Dummy(sym) => sym,
148 }
149 }
150
151 pub fn number(&self) -> usize {
153 match &self {
154 Element(num) => *num,
155 Dummy(_) => 0,
156 }
157 }
158
159 pub fn name(&self) -> &str {
161 match &self {
162 Element(num) => ELEMENT_DATA[num - 1].1,
163 Dummy(sym) => sym,
164 }
165 }
166}
167gut::config::lazy_static! {
171 pub static ref ELEMENTS: std::collections::HashMap<&'static str, usize> = {
173 ELEMENT_DATA.iter().zip(1..).map(|((s, _), i)| (*s, i)).collect()
174 };
175}
176
177impl std::fmt::Display for AtomKind {
178 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
179 write!(f, "{:}", self.symbol())
180 }
181}
182
183impl std::convert::From<usize> for AtomKind {
184 fn from(value: usize) -> Self {
185 match value {
186 0 => Dummy("dummy".into()),
187 _ => Element(value),
188 }
189 }
190}
191
192impl std::convert::From<&str> for AtomKind {
193 fn from(label: &str) -> Self {
194 if let Some(&n) = ELEMENTS.get(label) {
196 return Element(n);
197 }
198
199 if let Ok(x) = label.parse::<usize>() {
201 return Element(x);
202 }
203
204 let sym = label.to_uppercase();
206 for (i, &(s, n)) in ELEMENT_DATA.iter().enumerate() {
207 if s.to_uppercase() == sym || n.to_uppercase() == sym {
208 return Element(i + 1);
209 }
210 }
211
212 Dummy(label.into())
214 }
215}
216
217impl std::convert::From<String> for AtomKind {
218 fn from(label: String) -> Self {
219 Self::from(label.as_str())
220 }
221}
222
223impl std::convert::From<&String> for AtomKind {
224 fn from(label: &String) -> Self {
225 Self::from(label.as_str())
226 }
227}
228#[test]
232fn test_element() {
233 let h1: AtomKind = 1.into();
234 let h2: AtomKind = "H".into();
235 let h3: AtomKind = "h".into();
236 let h4: AtomKind = "1".into();
237
238 assert_eq!(h1, h2);
239 assert_eq!(h1, h3);
240 assert_eq!(h1, h4);
241
242 let si: AtomKind = "SI".into();
243 assert_eq!(si.number(), 14);
244 assert_eq!(si.to_string(), "Si");
245 assert_eq!(si.name(), "Silicon");
246
247 let x: AtomKind = "X".into();
249 assert_eq!(x.symbol(), "X");
250 assert_eq!(x.number(), 0);
251
252 let s = String::from("Fe");
253 let fe: AtomKind = s.into();
254 assert_eq!(fe.symbol(), "Fe");
255}
256