periodic_table_on_an_enum/
lib.rs1use std::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
21use std::mem;
22
23include!(concat!(env!("OUT_DIR"), "/data.rs"));
24
25#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
26pub enum GroupBlock {
27 AlkaliMetal,
28 AlkalineEarthMetal,
29 Lanthanide,
30 Actinide,
31 TransitionMetal,
32 PostTransitionMetal,
33 Metalloid,
34 NonMetal,
35 Halogen,
36 NobleGas,
37}
38
39macro_rules! lookup {
40 ($table:expr, $term:expr) => {{
41 let mut l = 0;
43 let mut r = 117;
44 while l <= r {
45 let m = l + (r - l) / 2;
46 if $table[m].0 == $term {
47 return Some(unsafe { Element::from_id($table[m].1) });
48 }
49 if $table[m].0 < $term {
50 l = m + 1;
51 }
52 if $table[m].0 > $term {
53 r = m - 1;
54 }
55 }
56 None
57 }};
58}
59
60impl Element {
61 pub fn get_oxidation_states(&self) -> &'static [i8] {
62 &OXIDATION_STATES_DATA[OXIDATION_STATES[*self as usize].0 as usize
63 ..OXIDATION_STATES[*self as usize].0 as usize
64 + OXIDATION_STATES[*self as usize].1 as usize][..]
65 }
66
67 #[inline(always)]
69 pub unsafe fn from_id(id: u8) -> Element {
70 mem::transmute(id)
71 }
72
73 pub fn from_symbol(sym: &str) -> Option<Element> {
74 lookup!(SYMBOLS_SORTED_ALPHABETICALLY, sym)
75 }
76
77 pub fn from_name(name: &str) -> Option<Element> {
79 lookup!(LOWERCASE_NAMES_SORTED_ALPHABETICALLY, name)
80 }
81
82 pub fn from_name_case_insensitive(name: &str) -> Option<Element> {
83 Element::from_name(&name.to_lowercase())
84 }
85
86 pub fn from_atomic_number(z: usize) -> Option<Element> {
87 if z > 118 || z == 0 {
88 return None;
89 }
90 Some(unsafe { mem::transmute((z - 1) as u8) })
91 }
92
93 #[inline(always)]
94 pub fn get_atomic_number(&self) -> usize {
95 *self as usize + 1
96 }
97
98 #[inline(always)]
99 pub fn get_atomic_mass(&self) -> f32 {
100 ATOMIC_MASSES[*self as usize]
101 }
102
103 #[inline(always)]
104 pub fn get_atomic_radius(&self) -> u16 {
105 ATOMIC_RADIUS[*self as usize]
106 }
107
108 #[inline(always)]
109 pub fn get_electronegativity(&self) -> f32 {
110 ELECTRONEGATIVITIES[*self as usize]
111 }
112
113 #[inline(always)]
114 pub fn get_electron_affinity(&self) -> f32 {
115 ELECTRON_AFFINITIES[*self as usize]
116 }
117
118 #[inline(always)]
119 #[deprecated]
120 pub fn get_electron_configuration(&self) -> &'static str {
121 ELECTRON_CONFIGURATIONS[*self as usize]
122 }
123
124 #[inline(always)]
125 pub fn get_electronic_configuration(&self) -> ElectronicConfiguration {
126 ELECTRONIC_CONFIGURATION_PARSED[*self as usize]
127 }
128
129 #[inline(always)]
130 pub fn get_electronic_configuration_str(&self) -> &'static str {
131 ELECTRON_CONFIGURATIONS[*self as usize]
132 }
133
134 #[inline(always)]
135 pub fn get_ionization_energy(&self) -> f32 {
136 IONIZATION_ENERGIES[*self as usize]
137 }
138
139 #[inline(always)]
140 pub fn get_density(&self) -> f32 {
141 DENSITIES[*self as usize]
142 }
143
144 #[inline(always)]
145 pub fn get_melting_point(&self) -> f32 {
146 MELTING_POINTS[*self as usize]
147 }
148
149 #[inline(always)]
150 pub fn get_boiling_point(&self) -> f32 {
151 BOILING_POINTS[*self as usize]
152 }
153
154 #[inline(always)]
155 pub fn get_standard_state(&self) -> StateOfMatter {
156 STANDARD_STATES[*self as usize]
157 }
158
159 #[inline(always)]
160 pub fn get_symbol(&self) -> &'static str {
161 SYMBOLS[*self as usize]
162 }
163
164 #[inline(always)]
165 pub fn get_name(&self) -> &'static str {
166 NAMES[*self as usize]
167 }
168
169 #[inline(always)]
170 pub fn get_year_discovered(&self) -> u16 {
171 YEARS_OF_DISCOVERED[*self as usize]
172 }
173
174 #[inline(always)]
175 pub fn get_group(&self) -> GroupBlock {
176 GROUPS[*self as usize]
177 }
178
179 #[inline(always)]
180 pub fn get_cpk(&self) -> [u8; 3] {
181 CPK[*self as usize]
182 }
183
184 #[inline(always)]
186 pub fn get_id(&self) -> u8 {
187 *self as u8
188 }
189}
190
191pub struct PeriodicTableIterator {
192 r: i8,
193 l: i8,
194}
195
196pub fn periodic_table() -> PeriodicTableIterator {
197 PeriodicTableIterator { l: -1, r: 118 }
198}
199
200impl Iterator for PeriodicTableIterator {
201 type Item = Element;
202
203 fn next(&mut self) -> Option<Self::Item> {
204 self.l += 1;
205 if self.l >= self.r {
206 return None;
207 }
208 let e = unsafe { Element::from_id(self.l as u8) };
209 Some(e)
210 }
211}
212
213impl DoubleEndedIterator for PeriodicTableIterator {
214 fn next_back(&mut self) -> Option<Self::Item> {
215 self.r -= 1;
216 if self.r <= self.l {
217 return None;
218 }
219 let e = unsafe { Element::from_id(self.r as u8) };
220 Some(e)
221 }
222}
223
224impl FusedIterator for PeriodicTableIterator {}
225
226impl ExactSizeIterator for PeriodicTableIterator {
227 fn len(&self) -> usize {
228 (self.r - self.l) as usize
229 }
230}
231
232#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
233pub enum StateOfMatter {
234 Solid,
235 Liquid,
236 Gas,
237}
238
239#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
240pub struct ElectronicConfiguration {
241 pub s: [u8; 7],
242 pub p: [u8; 6],
243 pub d: [u8; 4],
244 pub f: [u8; 2],
245}