1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
5pub enum BromineIsotope {
7 Br67,
9 Br68,
11 Br69,
13 Br70,
15 Br71,
17 Br72,
19 Br73,
21 Br74,
23 Br75,
25 Br76,
27 Br77,
29 Br78,
31 Br79,
33 Br80,
35 Br81,
37 Br82,
39 Br83,
41 Br84,
43 Br85,
45 Br86,
47 Br87,
49 Br88,
51 Br89,
53 Br90,
55 Br91,
57 Br92,
59 Br93,
61 Br94,
63 Br95,
65 Br96,
67 Br97,
69 Br98,
71}
72impl super::RelativeAtomicMass for BromineIsotope {
73 #[inline]
74 fn relative_atomic_mass(&self) -> f64 {
75 match self {
76 Self::Br67 => 66.96465f64,
77 Self::Br68 => 67.95873f64,
78 Self::Br69 => 68.950497f64,
79 Self::Br70 => 69.944792f64,
80 Self::Br71 => 70.9393422f64,
81 Self::Br72 => 71.9365886f64,
82 Self::Br73 => 72.9316715f64,
83 Self::Br74 => 73.9299102f64,
84 Self::Br75 => 74.9258105f64,
85 Self::Br76 => 75.924542f64,
86 Self::Br77 => 76.9213792f64,
87 Self::Br78 => 77.9211459f64,
88 Self::Br79 => 78.9183376f64,
89 Self::Br80 => 79.9185298f64,
90 Self::Br81 => 80.9162897f64,
91 Self::Br82 => 81.9168032f64,
92 Self::Br83 => 82.9151756f64,
93 Self::Br84 => 83.916496f64,
94 Self::Br85 => 84.9156458f64,
95 Self::Br86 => 85.9188054f64,
96 Self::Br87 => 86.920674f64,
97 Self::Br88 => 87.9240833f64,
98 Self::Br89 => 88.9267046f64,
99 Self::Br90 => 89.9312928f64,
100 Self::Br91 => 90.9343986f64,
101 Self::Br92 => 91.9396316f64,
102 Self::Br93 => 92.94313f64,
103 Self::Br94 => 93.9489f64,
104 Self::Br95 => 94.95301f64,
105 Self::Br96 => 95.95903f64,
106 Self::Br97 => 96.96344f64,
107 Self::Br98 => 97.96946f64,
108 }
109 }
110}
111impl super::ElementVariant for BromineIsotope {
112 #[inline]
113 fn element(&self) -> crate::Element {
114 crate::Element::Br
115 }
116}
117impl super::MassNumber for BromineIsotope {
118 #[inline]
119 fn mass_number(&self) -> u16 {
120 match self {
121 Self::Br67 => 67u16,
122 Self::Br68 => 68u16,
123 Self::Br69 => 69u16,
124 Self::Br70 => 70u16,
125 Self::Br71 => 71u16,
126 Self::Br72 => 72u16,
127 Self::Br73 => 73u16,
128 Self::Br74 => 74u16,
129 Self::Br75 => 75u16,
130 Self::Br76 => 76u16,
131 Self::Br77 => 77u16,
132 Self::Br78 => 78u16,
133 Self::Br79 => 79u16,
134 Self::Br80 => 80u16,
135 Self::Br81 => 81u16,
136 Self::Br82 => 82u16,
137 Self::Br83 => 83u16,
138 Self::Br84 => 84u16,
139 Self::Br85 => 85u16,
140 Self::Br86 => 86u16,
141 Self::Br87 => 87u16,
142 Self::Br88 => 88u16,
143 Self::Br89 => 89u16,
144 Self::Br90 => 90u16,
145 Self::Br91 => 91u16,
146 Self::Br92 => 92u16,
147 Self::Br93 => 93u16,
148 Self::Br94 => 94u16,
149 Self::Br95 => 95u16,
150 Self::Br96 => 96u16,
151 Self::Br97 => 97u16,
152 Self::Br98 => 98u16,
153 }
154 }
155}
156impl super::IsotopicComposition for BromineIsotope {
157 #[inline]
158 fn isotopic_composition(&self) -> Option<f64> {
159 match self {
160 Self::Br79 => Some(0.5069f64),
161 Self::Br81 => Some(0.4931f64),
162 _ => None,
163 }
164 }
165}
166impl super::MostAbundantIsotope for BromineIsotope {
167 fn most_abundant_isotope() -> Self {
168 Self::Br79
169 }
170}
171impl From<BromineIsotope> for crate::Isotope {
172 fn from(isotope: BromineIsotope) -> Self {
173 crate::Isotope::Br(isotope)
174 }
175}
176impl From<BromineIsotope> for crate::Element {
177 fn from(_isotope: BromineIsotope) -> Self {
178 crate::Element::Br
179 }
180}
181impl TryFrom<u64> for BromineIsotope {
182 type Error = crate::errors::Error;
183 fn try_from(value: u64) -> Result<Self, Self::Error> {
184 match value {
185 67u64 => Ok(Self::Br67),
186 68u64 => Ok(Self::Br68),
187 69u64 => Ok(Self::Br69),
188 70u64 => Ok(Self::Br70),
189 71u64 => Ok(Self::Br71),
190 72u64 => Ok(Self::Br72),
191 73u64 => Ok(Self::Br73),
192 74u64 => Ok(Self::Br74),
193 75u64 => Ok(Self::Br75),
194 76u64 => Ok(Self::Br76),
195 77u64 => Ok(Self::Br77),
196 78u64 => Ok(Self::Br78),
197 79u64 => Ok(Self::Br79),
198 80u64 => Ok(Self::Br80),
199 81u64 => Ok(Self::Br81),
200 82u64 => Ok(Self::Br82),
201 83u64 => Ok(Self::Br83),
202 84u64 => Ok(Self::Br84),
203 85u64 => Ok(Self::Br85),
204 86u64 => Ok(Self::Br86),
205 87u64 => Ok(Self::Br87),
206 88u64 => Ok(Self::Br88),
207 89u64 => Ok(Self::Br89),
208 90u64 => Ok(Self::Br90),
209 91u64 => Ok(Self::Br91),
210 92u64 => Ok(Self::Br92),
211 93u64 => Ok(Self::Br93),
212 94u64 => Ok(Self::Br94),
213 95u64 => Ok(Self::Br95),
214 96u64 => Ok(Self::Br96),
215 97u64 => Ok(Self::Br97),
216 98u64 => Ok(Self::Br98),
217 _ => Err(crate::errors::Error::Isotope(crate::Element::Br, value)),
218 }
219 }
220}
221impl TryFrom<u8> for BromineIsotope {
222 type Error = crate::errors::Error;
223 fn try_from(value: u8) -> Result<Self, Self::Error> {
224 Self::try_from(u64::from(value))
225 }
226}
227impl TryFrom<u16> for BromineIsotope {
228 type Error = crate::errors::Error;
229 fn try_from(value: u16) -> Result<Self, Self::Error> {
230 Self::try_from(u64::from(value))
231 }
232}
233impl TryFrom<u32> for BromineIsotope {
234 type Error = crate::errors::Error;
235 fn try_from(value: u32) -> Result<Self, Self::Error> {
236 Self::try_from(u64::from(value))
237 }
238}
239impl core::fmt::Display for BromineIsotope {
240 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
241 match self {
242 Self::Br67 => write!(f, "Br67"),
243 Self::Br68 => write!(f, "Br68"),
244 Self::Br69 => write!(f, "Br69"),
245 Self::Br70 => write!(f, "Br70"),
246 Self::Br71 => write!(f, "Br71"),
247 Self::Br72 => write!(f, "Br72"),
248 Self::Br73 => write!(f, "Br73"),
249 Self::Br74 => write!(f, "Br74"),
250 Self::Br75 => write!(f, "Br75"),
251 Self::Br76 => write!(f, "Br76"),
252 Self::Br77 => write!(f, "Br77"),
253 Self::Br78 => write!(f, "Br78"),
254 Self::Br79 => write!(f, "Br79"),
255 Self::Br80 => write!(f, "Br80"),
256 Self::Br81 => write!(f, "Br81"),
257 Self::Br82 => write!(f, "Br82"),
258 Self::Br83 => write!(f, "Br83"),
259 Self::Br84 => write!(f, "Br84"),
260 Self::Br85 => write!(f, "Br85"),
261 Self::Br86 => write!(f, "Br86"),
262 Self::Br87 => write!(f, "Br87"),
263 Self::Br88 => write!(f, "Br88"),
264 Self::Br89 => write!(f, "Br89"),
265 Self::Br90 => write!(f, "Br90"),
266 Self::Br91 => write!(f, "Br91"),
267 Self::Br92 => write!(f, "Br92"),
268 Self::Br93 => write!(f, "Br93"),
269 Self::Br94 => write!(f, "Br94"),
270 Self::Br95 => write!(f, "Br95"),
271 Self::Br96 => write!(f, "Br96"),
272 Self::Br97 => write!(f, "Br97"),
273 Self::Br98 => write!(f, "Br98"),
274 }
275 }
276}
277#[cfg(test)]
278mod tests {
279 use strum::IntoEnumIterator;
280
281 use super::*;
282 use crate::isotopes::{
283 ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
284 };
285 #[test]
286 fn test_relative_atomic_mass() {
287 for isotope in BromineIsotope::iter() {
288 let mass = isotope.relative_atomic_mass();
289 assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
290 }
291 }
292 #[test]
293 fn test_element() {
294 for isotope in BromineIsotope::iter() {
295 let element = isotope.element();
296 assert_eq!(element, crate::Element::Br, "Element should be correct for {isotope:?}");
297 }
298 }
299 #[test]
300 fn test_mass_number() {
301 for isotope in BromineIsotope::iter() {
302 let mass_number = isotope.mass_number();
303 assert!(
304 mass_number > 0 && mass_number < 300,
305 "Mass number should be reasonable for {isotope:?}"
306 );
307 }
308 }
309 #[test]
310 fn test_isotopic_composition() {
311 for isotope in BromineIsotope::iter() {
312 let comp = isotope.isotopic_composition();
313 if let Some(c) = comp {
314 assert!(
315 (0.0..=1.0).contains(&c),
316 "Composition should be between 0 and 1 for {isotope:?}"
317 );
318 }
319 }
320 }
321 #[test]
322 fn test_most_abundant() {
323 let most_abundant = BromineIsotope::most_abundant_isotope();
324 let _ = most_abundant.relative_atomic_mass();
325 }
326 #[test]
327 fn test_from_isotope() {
328 for isotope in BromineIsotope::iter() {
329 let iso: crate::Isotope = isotope.into();
330 match iso {
331 crate::Isotope::Br(i) => assert_eq!(i, isotope),
332 _ => panic!("Wrong isotope type"),
333 }
334 }
335 }
336 #[test]
337 fn test_from_element() {
338 for isotope in BromineIsotope::iter() {
339 let elem: crate::Element = isotope.into();
340 assert_eq!(elem, crate::Element::Br);
341 }
342 }
343 #[test]
344 fn test_try_from_mass_number() {
345 for isotope in BromineIsotope::iter() {
346 let mass = isotope.mass_number();
347 let iso = BromineIsotope::try_from(mass).unwrap();
348 assert_eq!(iso, isotope);
349 let iso_u32 = BromineIsotope::try_from(u32::from(mass)).unwrap();
350 assert_eq!(iso_u32, isotope);
351 if let Ok(mass_u8) = u8::try_from(mass) {
352 let iso_u8 = BromineIsotope::try_from(mass_u8).unwrap();
353 assert_eq!(iso_u8, isotope);
354 }
355 }
356 assert!(BromineIsotope::try_from(0_u16).is_err());
357 assert!(BromineIsotope::try_from(1000_u16).is_err());
358 assert!(BromineIsotope::try_from(0_u32).is_err());
359 assert!(BromineIsotope::try_from(1000_u32).is_err());
360 assert!(BromineIsotope::try_from(0_u8).is_err());
361 }
362 #[test]
363 fn test_display() {
364 for isotope in BromineIsotope::iter() {
365 let s = alloc::format!("{isotope}");
366 assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
367 }
368 }
369}