1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub enum RutheniumIsotope {
6 Ru87,
8 Ru88,
10 Ru89,
12 Ru90,
14 Ru91,
16 Ru92,
18 Ru93,
20 Ru94,
22 Ru95,
24 Ru96,
26 Ru97,
28 Ru98,
30 Ru99,
32 Ru100,
34 Ru101,
36 Ru102,
38 Ru103,
40 Ru104,
42 Ru105,
44 Ru106,
46 Ru107,
48 Ru108,
50 Ru109,
52 Ru110,
54 Ru111,
56 Ru112,
58 Ru113,
60 Ru114,
62 Ru115,
64 Ru116,
66 Ru117,
68 Ru118,
70 Ru119,
72 Ru120,
74 Ru121,
76 Ru122,
78 Ru123,
80 Ru124,
82}
83impl super::RelativeAtomicMass for RutheniumIsotope {
84 #[inline]
85 fn relative_atomic_mass(&self) -> f64 {
86 match self {
87 Self::Ru87 => 86.95069f64,
88 Self::Ru88 => 87.9416f64,
89 Self::Ru89 => 88.93762f64,
90 Self::Ru90 => 89.9303444f64,
91 Self::Ru91 => 90.9267419f64,
92 Self::Ru92 => 91.9202344f64,
93 Self::Ru93 => 92.9171044f64,
94 Self::Ru94 => 93.9113429f64,
95 Self::Ru95 => 94.910406f64,
96 Self::Ru96 => 95.90759025f64,
97 Self::Ru97 => 96.9075471f64,
98 Self::Ru98 => 97.9052868f64,
99 Self::Ru99 => 98.9059341f64,
100 Self::Ru100 => 99.9042143f64,
101 Self::Ru101 => 100.9055769f64,
102 Self::Ru102 => 101.9043441f64,
103 Self::Ru103 => 102.9063186f64,
104 Self::Ru104 => 103.9054275f64,
105 Self::Ru105 => 104.9077476f64,
106 Self::Ru106 => 105.9073291f64,
107 Self::Ru107 => 106.909972f64,
108 Self::Ru108 => 107.910188f64,
109 Self::Ru109 => 108.913326f64,
110 Self::Ru110 => 109.9140407f64,
111 Self::Ru111 => 110.91757f64,
112 Self::Ru112 => 111.918809f64,
113 Self::Ru113 => 112.922844f64,
114 Self::Ru114 => 113.9246136f64,
115 Self::Ru115 => 114.92882f64,
116 Self::Ru116 => 115.9312192f64,
117 Self::Ru117 => 116.9361f64,
118 Self::Ru118 => 117.93853f64,
119 Self::Ru119 => 118.94357f64,
120 Self::Ru120 => 119.94631f64,
121 Self::Ru121 => 120.95164f64,
122 Self::Ru122 => 121.95447f64,
123 Self::Ru123 => 122.95989f64,
124 Self::Ru124 => 123.96305f64,
125 }
126 }
127}
128impl super::ElementVariant for RutheniumIsotope {
129 #[inline]
130 fn element(&self) -> crate::Element {
131 crate::Element::Ru
132 }
133}
134impl super::MassNumber for RutheniumIsotope {
135 #[inline]
136 fn mass_number(&self) -> u16 {
137 match self {
138 Self::Ru87 => 87u16,
139 Self::Ru88 => 88u16,
140 Self::Ru89 => 89u16,
141 Self::Ru90 => 90u16,
142 Self::Ru91 => 91u16,
143 Self::Ru92 => 92u16,
144 Self::Ru93 => 93u16,
145 Self::Ru94 => 94u16,
146 Self::Ru95 => 95u16,
147 Self::Ru96 => 96u16,
148 Self::Ru97 => 97u16,
149 Self::Ru98 => 98u16,
150 Self::Ru99 => 99u16,
151 Self::Ru100 => 100u16,
152 Self::Ru101 => 101u16,
153 Self::Ru102 => 102u16,
154 Self::Ru103 => 103u16,
155 Self::Ru104 => 104u16,
156 Self::Ru105 => 105u16,
157 Self::Ru106 => 106u16,
158 Self::Ru107 => 107u16,
159 Self::Ru108 => 108u16,
160 Self::Ru109 => 109u16,
161 Self::Ru110 => 110u16,
162 Self::Ru111 => 111u16,
163 Self::Ru112 => 112u16,
164 Self::Ru113 => 113u16,
165 Self::Ru114 => 114u16,
166 Self::Ru115 => 115u16,
167 Self::Ru116 => 116u16,
168 Self::Ru117 => 117u16,
169 Self::Ru118 => 118u16,
170 Self::Ru119 => 119u16,
171 Self::Ru120 => 120u16,
172 Self::Ru121 => 121u16,
173 Self::Ru122 => 122u16,
174 Self::Ru123 => 123u16,
175 Self::Ru124 => 124u16,
176 }
177 }
178}
179impl super::IsotopicComposition for RutheniumIsotope {
180 #[inline]
181 fn isotopic_composition(&self) -> Option<f64> {
182 match self {
183 Self::Ru96 => Some(0.0554f64),
184 Self::Ru98 => Some(0.0187f64),
185 Self::Ru99 => Some(0.1276f64),
186 Self::Ru100 => Some(0.126f64),
187 Self::Ru101 => Some(0.1706f64),
188 Self::Ru102 => Some(0.3155f64),
189 Self::Ru104 => Some(0.1862f64),
190 _ => None,
191 }
192 }
193}
194impl super::MostAbundantIsotope for RutheniumIsotope {
195 fn most_abundant_isotope() -> Self {
196 Self::Ru102
197 }
198}
199impl From<RutheniumIsotope> for crate::Isotope {
200 fn from(isotope: RutheniumIsotope) -> Self {
201 crate::Isotope::Ru(isotope)
202 }
203}
204impl From<RutheniumIsotope> for crate::Element {
205 fn from(_isotope: RutheniumIsotope) -> Self {
206 crate::Element::Ru
207 }
208}
209impl TryFrom<u64> for RutheniumIsotope {
210 type Error = crate::errors::Error;
211 fn try_from(value: u64) -> Result<Self, Self::Error> {
212 match value {
213 87u64 => Ok(Self::Ru87),
214 88u64 => Ok(Self::Ru88),
215 89u64 => Ok(Self::Ru89),
216 90u64 => Ok(Self::Ru90),
217 91u64 => Ok(Self::Ru91),
218 92u64 => Ok(Self::Ru92),
219 93u64 => Ok(Self::Ru93),
220 94u64 => Ok(Self::Ru94),
221 95u64 => Ok(Self::Ru95),
222 96u64 => Ok(Self::Ru96),
223 97u64 => Ok(Self::Ru97),
224 98u64 => Ok(Self::Ru98),
225 99u64 => Ok(Self::Ru99),
226 100u64 => Ok(Self::Ru100),
227 101u64 => Ok(Self::Ru101),
228 102u64 => Ok(Self::Ru102),
229 103u64 => Ok(Self::Ru103),
230 104u64 => Ok(Self::Ru104),
231 105u64 => Ok(Self::Ru105),
232 106u64 => Ok(Self::Ru106),
233 107u64 => Ok(Self::Ru107),
234 108u64 => Ok(Self::Ru108),
235 109u64 => Ok(Self::Ru109),
236 110u64 => Ok(Self::Ru110),
237 111u64 => Ok(Self::Ru111),
238 112u64 => Ok(Self::Ru112),
239 113u64 => Ok(Self::Ru113),
240 114u64 => Ok(Self::Ru114),
241 115u64 => Ok(Self::Ru115),
242 116u64 => Ok(Self::Ru116),
243 117u64 => Ok(Self::Ru117),
244 118u64 => Ok(Self::Ru118),
245 119u64 => Ok(Self::Ru119),
246 120u64 => Ok(Self::Ru120),
247 121u64 => Ok(Self::Ru121),
248 122u64 => Ok(Self::Ru122),
249 123u64 => Ok(Self::Ru123),
250 124u64 => Ok(Self::Ru124),
251 _ => Err(crate::errors::Error::Isotope(crate::Element::Ru, value)),
252 }
253 }
254}
255impl TryFrom<u8> for RutheniumIsotope {
256 type Error = crate::errors::Error;
257 fn try_from(value: u8) -> Result<Self, Self::Error> {
258 Self::try_from(u64::from(value))
259 }
260}
261impl TryFrom<u16> for RutheniumIsotope {
262 type Error = crate::errors::Error;
263 fn try_from(value: u16) -> Result<Self, Self::Error> {
264 Self::try_from(u64::from(value))
265 }
266}
267impl TryFrom<u32> for RutheniumIsotope {
268 type Error = crate::errors::Error;
269 fn try_from(value: u32) -> Result<Self, Self::Error> {
270 Self::try_from(u64::from(value))
271 }
272}
273impl core::fmt::Display for RutheniumIsotope {
274 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
275 match self {
276 Self::Ru87 => write!(f, "Ru87"),
277 Self::Ru88 => write!(f, "Ru88"),
278 Self::Ru89 => write!(f, "Ru89"),
279 Self::Ru90 => write!(f, "Ru90"),
280 Self::Ru91 => write!(f, "Ru91"),
281 Self::Ru92 => write!(f, "Ru92"),
282 Self::Ru93 => write!(f, "Ru93"),
283 Self::Ru94 => write!(f, "Ru94"),
284 Self::Ru95 => write!(f, "Ru95"),
285 Self::Ru96 => write!(f, "Ru96"),
286 Self::Ru97 => write!(f, "Ru97"),
287 Self::Ru98 => write!(f, "Ru98"),
288 Self::Ru99 => write!(f, "Ru99"),
289 Self::Ru100 => write!(f, "Ru100"),
290 Self::Ru101 => write!(f, "Ru101"),
291 Self::Ru102 => write!(f, "Ru102"),
292 Self::Ru103 => write!(f, "Ru103"),
293 Self::Ru104 => write!(f, "Ru104"),
294 Self::Ru105 => write!(f, "Ru105"),
295 Self::Ru106 => write!(f, "Ru106"),
296 Self::Ru107 => write!(f, "Ru107"),
297 Self::Ru108 => write!(f, "Ru108"),
298 Self::Ru109 => write!(f, "Ru109"),
299 Self::Ru110 => write!(f, "Ru110"),
300 Self::Ru111 => write!(f, "Ru111"),
301 Self::Ru112 => write!(f, "Ru112"),
302 Self::Ru113 => write!(f, "Ru113"),
303 Self::Ru114 => write!(f, "Ru114"),
304 Self::Ru115 => write!(f, "Ru115"),
305 Self::Ru116 => write!(f, "Ru116"),
306 Self::Ru117 => write!(f, "Ru117"),
307 Self::Ru118 => write!(f, "Ru118"),
308 Self::Ru119 => write!(f, "Ru119"),
309 Self::Ru120 => write!(f, "Ru120"),
310 Self::Ru121 => write!(f, "Ru121"),
311 Self::Ru122 => write!(f, "Ru122"),
312 Self::Ru123 => write!(f, "Ru123"),
313 Self::Ru124 => write!(f, "Ru124"),
314 }
315 }
316}
317#[cfg(test)]
318mod tests {
319 use strum::IntoEnumIterator;
320
321 use super::*;
322 use crate::isotopes::{
323 ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
324 };
325 #[test]
326 fn test_relative_atomic_mass() {
327 for isotope in RutheniumIsotope::iter() {
328 let mass = isotope.relative_atomic_mass();
329 assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
330 }
331 }
332 #[test]
333 fn test_element() {
334 for isotope in RutheniumIsotope::iter() {
335 let element = isotope.element();
336 assert_eq!(element, crate::Element::Ru, "Element should be correct for {isotope:?}");
337 }
338 }
339 #[test]
340 fn test_mass_number() {
341 for isotope in RutheniumIsotope::iter() {
342 let mass_number = isotope.mass_number();
343 assert!(
344 mass_number > 0 && mass_number < 300,
345 "Mass number should be reasonable for {isotope:?}"
346 );
347 }
348 }
349 #[test]
350 fn test_isotopic_composition() {
351 for isotope in RutheniumIsotope::iter() {
352 let comp = isotope.isotopic_composition();
353 if let Some(c) = comp {
354 assert!(
355 (0.0..=1.0).contains(&c),
356 "Composition should be between 0 and 1 for {isotope:?}"
357 );
358 }
359 }
360 }
361 #[test]
362 fn test_most_abundant() {
363 let most_abundant = RutheniumIsotope::most_abundant_isotope();
364 let _ = most_abundant.relative_atomic_mass();
365 }
366 #[test]
367 fn test_from_isotope() {
368 for isotope in RutheniumIsotope::iter() {
369 let iso: crate::Isotope = isotope.into();
370 match iso {
371 crate::Isotope::Ru(i) => assert_eq!(i, isotope),
372 _ => panic!("Wrong isotope type"),
373 }
374 }
375 }
376 #[test]
377 fn test_from_element() {
378 for isotope in RutheniumIsotope::iter() {
379 let elem: crate::Element = isotope.into();
380 assert_eq!(elem, crate::Element::Ru);
381 }
382 }
383 #[test]
384 fn test_try_from_mass_number() {
385 for isotope in RutheniumIsotope::iter() {
386 let mass = isotope.mass_number();
387 let iso = RutheniumIsotope::try_from(mass).unwrap();
388 assert_eq!(iso, isotope);
389 let iso_u32 = RutheniumIsotope::try_from(u32::from(mass)).unwrap();
390 assert_eq!(iso_u32, isotope);
391 if let Ok(mass_u8) = u8::try_from(mass) {
392 let iso_u8 = RutheniumIsotope::try_from(mass_u8).unwrap();
393 assert_eq!(iso_u8, isotope);
394 }
395 }
396 assert!(RutheniumIsotope::try_from(0_u16).is_err());
397 assert!(RutheniumIsotope::try_from(1000_u16).is_err());
398 assert!(RutheniumIsotope::try_from(0_u32).is_err());
399 assert!(RutheniumIsotope::try_from(1000_u32).is_err());
400 assert!(RutheniumIsotope::try_from(0_u8).is_err());
401 }
402 #[test]
403 fn test_display() {
404 for isotope in RutheniumIsotope::iter() {
405 let s = alloc::format!("{isotope}");
406 assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
407 }
408 }
409}