1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub enum RubidiumIsotope {
6 Rb71,
8 Rb72,
10 Rb73,
12 Rb74,
14 Rb75,
16 Rb76,
18 Rb77,
20 Rb78,
22 Rb79,
24 Rb80,
26 Rb81,
28 Rb82,
30 Rb83,
32 Rb84,
34 Rb85,
36 Rb86,
38 Rb87,
40 Rb88,
42 Rb89,
44 Rb90,
46 Rb91,
48 Rb92,
50 Rb93,
52 Rb94,
54 Rb95,
56 Rb96,
58 Rb97,
60 Rb98,
62 Rb99,
64 Rb100,
66 Rb101,
68 Rb102,
70 Rb103,
72}
73impl super::RelativeAtomicMass for RubidiumIsotope {
74 #[inline]
75 fn relative_atomic_mass(&self) -> f64 {
76 match self {
77 Self::Rb71 => 70.96532f64,
78 Self::Rb72 => 71.95908f64,
79 Self::Rb73 => 72.95053f64,
80 Self::Rb74 => 73.9442659f64,
81 Self::Rb75 => 74.9385732f64,
82 Self::Rb76 => 75.935073f64,
83 Self::Rb77 => 76.9304016f64,
84 Self::Rb78 => 77.9281419f64,
85 Self::Rb79 => 78.9239899f64,
86 Self::Rb80 => 79.9225164f64,
87 Self::Rb81 => 80.9189939f64,
88 Self::Rb82 => 81.918209f64,
89 Self::Rb83 => 82.9151142f64,
90 Self::Rb84 => 83.9143752f64,
91 Self::Rb85 => 84.9117897379f64,
92 Self::Rb86 => 85.91116743f64,
93 Self::Rb87 => 86.909180531f64,
94 Self::Rb88 => 87.91131559f64,
95 Self::Rb89 => 88.9122783f64,
96 Self::Rb90 => 89.9147985f64,
97 Self::Rb91 => 90.9165372f64,
98 Self::Rb92 => 91.9197284f64,
99 Self::Rb93 => 92.9220393f64,
100 Self::Rb94 => 93.9263948f64,
101 Self::Rb95 => 94.92926f64,
102 Self::Rb96 => 95.9341334f64,
103 Self::Rb97 => 96.9371771f64,
104 Self::Rb98 => 97.9416869f64,
105 Self::Rb99 => 98.94503f64,
106 Self::Rb100 => 99.95003f64,
107 Self::Rb101 => 100.95404f64,
108 Self::Rb102 => 101.95952f64,
109 Self::Rb103 => 102.96392f64,
110 }
111 }
112}
113impl super::ElementVariant for RubidiumIsotope {
114 #[inline]
115 fn element(&self) -> crate::Element {
116 crate::Element::Rb
117 }
118}
119impl super::MassNumber for RubidiumIsotope {
120 #[inline]
121 fn mass_number(&self) -> u16 {
122 match self {
123 Self::Rb71 => 71u16,
124 Self::Rb72 => 72u16,
125 Self::Rb73 => 73u16,
126 Self::Rb74 => 74u16,
127 Self::Rb75 => 75u16,
128 Self::Rb76 => 76u16,
129 Self::Rb77 => 77u16,
130 Self::Rb78 => 78u16,
131 Self::Rb79 => 79u16,
132 Self::Rb80 => 80u16,
133 Self::Rb81 => 81u16,
134 Self::Rb82 => 82u16,
135 Self::Rb83 => 83u16,
136 Self::Rb84 => 84u16,
137 Self::Rb85 => 85u16,
138 Self::Rb86 => 86u16,
139 Self::Rb87 => 87u16,
140 Self::Rb88 => 88u16,
141 Self::Rb89 => 89u16,
142 Self::Rb90 => 90u16,
143 Self::Rb91 => 91u16,
144 Self::Rb92 => 92u16,
145 Self::Rb93 => 93u16,
146 Self::Rb94 => 94u16,
147 Self::Rb95 => 95u16,
148 Self::Rb96 => 96u16,
149 Self::Rb97 => 97u16,
150 Self::Rb98 => 98u16,
151 Self::Rb99 => 99u16,
152 Self::Rb100 => 100u16,
153 Self::Rb101 => 101u16,
154 Self::Rb102 => 102u16,
155 Self::Rb103 => 103u16,
156 }
157 }
158}
159impl super::IsotopicComposition for RubidiumIsotope {
160 #[inline]
161 fn isotopic_composition(&self) -> Option<f64> {
162 match self {
163 Self::Rb85 => Some(0.7217f64),
164 Self::Rb87 => Some(0.2783f64),
165 _ => None,
166 }
167 }
168}
169impl super::MostAbundantIsotope for RubidiumIsotope {
170 fn most_abundant_isotope() -> Self {
171 Self::Rb85
172 }
173}
174impl From<RubidiumIsotope> for crate::Isotope {
175 fn from(isotope: RubidiumIsotope) -> Self {
176 crate::Isotope::Rb(isotope)
177 }
178}
179impl From<RubidiumIsotope> for crate::Element {
180 fn from(_isotope: RubidiumIsotope) -> Self {
181 crate::Element::Rb
182 }
183}
184impl TryFrom<u64> for RubidiumIsotope {
185 type Error = crate::errors::Error;
186 fn try_from(value: u64) -> Result<Self, Self::Error> {
187 match value {
188 71u64 => Ok(Self::Rb71),
189 72u64 => Ok(Self::Rb72),
190 73u64 => Ok(Self::Rb73),
191 74u64 => Ok(Self::Rb74),
192 75u64 => Ok(Self::Rb75),
193 76u64 => Ok(Self::Rb76),
194 77u64 => Ok(Self::Rb77),
195 78u64 => Ok(Self::Rb78),
196 79u64 => Ok(Self::Rb79),
197 80u64 => Ok(Self::Rb80),
198 81u64 => Ok(Self::Rb81),
199 82u64 => Ok(Self::Rb82),
200 83u64 => Ok(Self::Rb83),
201 84u64 => Ok(Self::Rb84),
202 85u64 => Ok(Self::Rb85),
203 86u64 => Ok(Self::Rb86),
204 87u64 => Ok(Self::Rb87),
205 88u64 => Ok(Self::Rb88),
206 89u64 => Ok(Self::Rb89),
207 90u64 => Ok(Self::Rb90),
208 91u64 => Ok(Self::Rb91),
209 92u64 => Ok(Self::Rb92),
210 93u64 => Ok(Self::Rb93),
211 94u64 => Ok(Self::Rb94),
212 95u64 => Ok(Self::Rb95),
213 96u64 => Ok(Self::Rb96),
214 97u64 => Ok(Self::Rb97),
215 98u64 => Ok(Self::Rb98),
216 99u64 => Ok(Self::Rb99),
217 100u64 => Ok(Self::Rb100),
218 101u64 => Ok(Self::Rb101),
219 102u64 => Ok(Self::Rb102),
220 103u64 => Ok(Self::Rb103),
221 _ => Err(crate::errors::Error::Isotope(crate::Element::Rb, value)),
222 }
223 }
224}
225impl TryFrom<u8> for RubidiumIsotope {
226 type Error = crate::errors::Error;
227 fn try_from(value: u8) -> Result<Self, Self::Error> {
228 Self::try_from(u64::from(value))
229 }
230}
231impl TryFrom<u16> for RubidiumIsotope {
232 type Error = crate::errors::Error;
233 fn try_from(value: u16) -> Result<Self, Self::Error> {
234 Self::try_from(u64::from(value))
235 }
236}
237impl TryFrom<u32> for RubidiumIsotope {
238 type Error = crate::errors::Error;
239 fn try_from(value: u32) -> Result<Self, Self::Error> {
240 Self::try_from(u64::from(value))
241 }
242}
243impl core::fmt::Display for RubidiumIsotope {
244 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
245 match self {
246 Self::Rb71 => write!(f, "Rb71"),
247 Self::Rb72 => write!(f, "Rb72"),
248 Self::Rb73 => write!(f, "Rb73"),
249 Self::Rb74 => write!(f, "Rb74"),
250 Self::Rb75 => write!(f, "Rb75"),
251 Self::Rb76 => write!(f, "Rb76"),
252 Self::Rb77 => write!(f, "Rb77"),
253 Self::Rb78 => write!(f, "Rb78"),
254 Self::Rb79 => write!(f, "Rb79"),
255 Self::Rb80 => write!(f, "Rb80"),
256 Self::Rb81 => write!(f, "Rb81"),
257 Self::Rb82 => write!(f, "Rb82"),
258 Self::Rb83 => write!(f, "Rb83"),
259 Self::Rb84 => write!(f, "Rb84"),
260 Self::Rb85 => write!(f, "Rb85"),
261 Self::Rb86 => write!(f, "Rb86"),
262 Self::Rb87 => write!(f, "Rb87"),
263 Self::Rb88 => write!(f, "Rb88"),
264 Self::Rb89 => write!(f, "Rb89"),
265 Self::Rb90 => write!(f, "Rb90"),
266 Self::Rb91 => write!(f, "Rb91"),
267 Self::Rb92 => write!(f, "Rb92"),
268 Self::Rb93 => write!(f, "Rb93"),
269 Self::Rb94 => write!(f, "Rb94"),
270 Self::Rb95 => write!(f, "Rb95"),
271 Self::Rb96 => write!(f, "Rb96"),
272 Self::Rb97 => write!(f, "Rb97"),
273 Self::Rb98 => write!(f, "Rb98"),
274 Self::Rb99 => write!(f, "Rb99"),
275 Self::Rb100 => write!(f, "Rb100"),
276 Self::Rb101 => write!(f, "Rb101"),
277 Self::Rb102 => write!(f, "Rb102"),
278 Self::Rb103 => write!(f, "Rb103"),
279 }
280 }
281}
282#[cfg(test)]
283mod tests {
284 use strum::IntoEnumIterator;
285
286 use super::*;
287 use crate::isotopes::{
288 ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
289 };
290 #[test]
291 fn test_relative_atomic_mass() {
292 for isotope in RubidiumIsotope::iter() {
293 let mass = isotope.relative_atomic_mass();
294 assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
295 }
296 }
297 #[test]
298 fn test_element() {
299 for isotope in RubidiumIsotope::iter() {
300 let element = isotope.element();
301 assert_eq!(element, crate::Element::Rb, "Element should be correct for {isotope:?}");
302 }
303 }
304 #[test]
305 fn test_mass_number() {
306 for isotope in RubidiumIsotope::iter() {
307 let mass_number = isotope.mass_number();
308 assert!(
309 mass_number > 0 && mass_number < 300,
310 "Mass number should be reasonable for {isotope:?}"
311 );
312 }
313 }
314 #[test]
315 fn test_isotopic_composition() {
316 for isotope in RubidiumIsotope::iter() {
317 let comp = isotope.isotopic_composition();
318 if let Some(c) = comp {
319 assert!(
320 (0.0..=1.0).contains(&c),
321 "Composition should be between 0 and 1 for {isotope:?}"
322 );
323 }
324 }
325 }
326 #[test]
327 fn test_most_abundant() {
328 let most_abundant = RubidiumIsotope::most_abundant_isotope();
329 let _ = most_abundant.relative_atomic_mass();
330 }
331 #[test]
332 fn test_from_isotope() {
333 for isotope in RubidiumIsotope::iter() {
334 let iso: crate::Isotope = isotope.into();
335 match iso {
336 crate::Isotope::Rb(i) => assert_eq!(i, isotope),
337 _ => panic!("Wrong isotope type"),
338 }
339 }
340 }
341 #[test]
342 fn test_from_element() {
343 for isotope in RubidiumIsotope::iter() {
344 let elem: crate::Element = isotope.into();
345 assert_eq!(elem, crate::Element::Rb);
346 }
347 }
348 #[test]
349 fn test_try_from_mass_number() {
350 for isotope in RubidiumIsotope::iter() {
351 let mass = isotope.mass_number();
352 let iso = RubidiumIsotope::try_from(mass).unwrap();
353 assert_eq!(iso, isotope);
354 let iso_u32 = RubidiumIsotope::try_from(u32::from(mass)).unwrap();
355 assert_eq!(iso_u32, isotope);
356 if let Ok(mass_u8) = u8::try_from(mass) {
357 let iso_u8 = RubidiumIsotope::try_from(mass_u8).unwrap();
358 assert_eq!(iso_u8, isotope);
359 }
360 }
361 assert!(RubidiumIsotope::try_from(0_u16).is_err());
362 assert!(RubidiumIsotope::try_from(1000_u16).is_err());
363 assert!(RubidiumIsotope::try_from(0_u32).is_err());
364 assert!(RubidiumIsotope::try_from(1000_u32).is_err());
365 assert!(RubidiumIsotope::try_from(0_u8).is_err());
366 }
367 #[test]
368 fn test_display() {
369 for isotope in RubidiumIsotope::iter() {
370 let s = alloc::format!("{isotope}");
371 assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
372 }
373 }
374}