1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub enum NeonIsotope {
6 Ne16,
8 Ne17,
10 Ne18,
12 Ne19,
14 Ne20,
16 Ne21,
18 Ne22,
20 Ne23,
22 Ne24,
24 Ne25,
26 Ne26,
28 Ne27,
30 Ne28,
32 Ne29,
34 Ne30,
36 Ne31,
38 Ne32,
40 Ne33,
42 Ne34,
44}
45impl super::RelativeAtomicMass for NeonIsotope {
46 #[inline]
47 fn relative_atomic_mass(&self) -> f64 {
48 match self {
49 Self::Ne16 => 16.02575f64,
50 Self::Ne17 => 17.01771396f64,
51 Self::Ne18 => 18.0057087f64,
52 Self::Ne19 => 19.00188091f64,
53 Self::Ne20 => 19.9924401762f64,
54 Self::Ne21 => 20.993846685f64,
55 Self::Ne22 => 21.991385114f64,
56 Self::Ne23 => 22.99446691f64,
57 Self::Ne24 => 23.99361065f64,
58 Self::Ne25 => 24.997789f64,
59 Self::Ne26 => 26.000515f64,
60 Self::Ne27 => 27.007553f64,
61 Self::Ne28 => 28.01212f64,
62 Self::Ne29 => 29.01975f64,
63 Self::Ne30 => 30.02473f64,
64 Self::Ne31 => 31.0331f64,
65 Self::Ne32 => 32.03972f64,
66 Self::Ne33 => 33.04938f64,
67 Self::Ne34 => 34.05673f64,
68 }
69 }
70}
71impl super::ElementVariant for NeonIsotope {
72 #[inline]
73 fn element(&self) -> crate::Element {
74 crate::Element::Ne
75 }
76}
77impl super::MassNumber for NeonIsotope {
78 #[inline]
79 fn mass_number(&self) -> u16 {
80 match self {
81 Self::Ne16 => 16u16,
82 Self::Ne17 => 17u16,
83 Self::Ne18 => 18u16,
84 Self::Ne19 => 19u16,
85 Self::Ne20 => 20u16,
86 Self::Ne21 => 21u16,
87 Self::Ne22 => 22u16,
88 Self::Ne23 => 23u16,
89 Self::Ne24 => 24u16,
90 Self::Ne25 => 25u16,
91 Self::Ne26 => 26u16,
92 Self::Ne27 => 27u16,
93 Self::Ne28 => 28u16,
94 Self::Ne29 => 29u16,
95 Self::Ne30 => 30u16,
96 Self::Ne31 => 31u16,
97 Self::Ne32 => 32u16,
98 Self::Ne33 => 33u16,
99 Self::Ne34 => 34u16,
100 }
101 }
102}
103impl super::IsotopicComposition for NeonIsotope {
104 #[inline]
105 fn isotopic_composition(&self) -> Option<f64> {
106 match self {
107 Self::Ne20 => Some(0.9048f64),
108 Self::Ne21 => Some(0.0027f64),
109 Self::Ne22 => Some(0.0925f64),
110 _ => None,
111 }
112 }
113}
114impl super::MostAbundantIsotope for NeonIsotope {
115 fn most_abundant_isotope() -> Self {
116 Self::Ne20
117 }
118}
119impl From<NeonIsotope> for crate::Isotope {
120 fn from(isotope: NeonIsotope) -> Self {
121 crate::Isotope::Ne(isotope)
122 }
123}
124impl From<NeonIsotope> for crate::Element {
125 fn from(_isotope: NeonIsotope) -> Self {
126 crate::Element::Ne
127 }
128}
129impl TryFrom<u64> for NeonIsotope {
130 type Error = crate::errors::Error;
131 fn try_from(value: u64) -> Result<Self, Self::Error> {
132 match value {
133 16u64 => Ok(Self::Ne16),
134 17u64 => Ok(Self::Ne17),
135 18u64 => Ok(Self::Ne18),
136 19u64 => Ok(Self::Ne19),
137 20u64 => Ok(Self::Ne20),
138 21u64 => Ok(Self::Ne21),
139 22u64 => Ok(Self::Ne22),
140 23u64 => Ok(Self::Ne23),
141 24u64 => Ok(Self::Ne24),
142 25u64 => Ok(Self::Ne25),
143 26u64 => Ok(Self::Ne26),
144 27u64 => Ok(Self::Ne27),
145 28u64 => Ok(Self::Ne28),
146 29u64 => Ok(Self::Ne29),
147 30u64 => Ok(Self::Ne30),
148 31u64 => Ok(Self::Ne31),
149 32u64 => Ok(Self::Ne32),
150 33u64 => Ok(Self::Ne33),
151 34u64 => Ok(Self::Ne34),
152 _ => Err(crate::errors::Error::Isotope(crate::Element::Ne, value)),
153 }
154 }
155}
156impl TryFrom<u8> for NeonIsotope {
157 type Error = crate::errors::Error;
158 fn try_from(value: u8) -> Result<Self, Self::Error> {
159 Self::try_from(u64::from(value))
160 }
161}
162impl TryFrom<u16> for NeonIsotope {
163 type Error = crate::errors::Error;
164 fn try_from(value: u16) -> Result<Self, Self::Error> {
165 Self::try_from(u64::from(value))
166 }
167}
168impl TryFrom<u32> for NeonIsotope {
169 type Error = crate::errors::Error;
170 fn try_from(value: u32) -> Result<Self, Self::Error> {
171 Self::try_from(u64::from(value))
172 }
173}
174impl core::fmt::Display for NeonIsotope {
175 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
176 match self {
177 Self::Ne16 => write!(f, "Ne16"),
178 Self::Ne17 => write!(f, "Ne17"),
179 Self::Ne18 => write!(f, "Ne18"),
180 Self::Ne19 => write!(f, "Ne19"),
181 Self::Ne20 => write!(f, "Ne20"),
182 Self::Ne21 => write!(f, "Ne21"),
183 Self::Ne22 => write!(f, "Ne22"),
184 Self::Ne23 => write!(f, "Ne23"),
185 Self::Ne24 => write!(f, "Ne24"),
186 Self::Ne25 => write!(f, "Ne25"),
187 Self::Ne26 => write!(f, "Ne26"),
188 Self::Ne27 => write!(f, "Ne27"),
189 Self::Ne28 => write!(f, "Ne28"),
190 Self::Ne29 => write!(f, "Ne29"),
191 Self::Ne30 => write!(f, "Ne30"),
192 Self::Ne31 => write!(f, "Ne31"),
193 Self::Ne32 => write!(f, "Ne32"),
194 Self::Ne33 => write!(f, "Ne33"),
195 Self::Ne34 => write!(f, "Ne34"),
196 }
197 }
198}
199#[cfg(test)]
200mod tests {
201 use strum::IntoEnumIterator;
202
203 use super::*;
204 use crate::isotopes::{
205 ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
206 };
207 #[test]
208 fn test_relative_atomic_mass() {
209 for isotope in NeonIsotope::iter() {
210 let mass = isotope.relative_atomic_mass();
211 assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
212 }
213 }
214 #[test]
215 fn test_element() {
216 for isotope in NeonIsotope::iter() {
217 let element = isotope.element();
218 assert_eq!(element, crate::Element::Ne, "Element should be correct for {isotope:?}");
219 }
220 }
221 #[test]
222 fn test_mass_number() {
223 for isotope in NeonIsotope::iter() {
224 let mass_number = isotope.mass_number();
225 assert!(
226 mass_number > 0 && mass_number < 300,
227 "Mass number should be reasonable for {isotope:?}"
228 );
229 }
230 }
231 #[test]
232 fn test_isotopic_composition() {
233 for isotope in NeonIsotope::iter() {
234 let comp = isotope.isotopic_composition();
235 if let Some(c) = comp {
236 assert!(
237 (0.0..=1.0).contains(&c),
238 "Composition should be between 0 and 1 for {isotope:?}"
239 );
240 }
241 }
242 }
243 #[test]
244 fn test_most_abundant() {
245 let most_abundant = NeonIsotope::most_abundant_isotope();
246 let _ = most_abundant.relative_atomic_mass();
247 }
248 #[test]
249 fn test_from_isotope() {
250 for isotope in NeonIsotope::iter() {
251 let iso: crate::Isotope = isotope.into();
252 match iso {
253 crate::Isotope::Ne(i) => assert_eq!(i, isotope),
254 _ => panic!("Wrong isotope type"),
255 }
256 }
257 }
258 #[test]
259 fn test_from_element() {
260 for isotope in NeonIsotope::iter() {
261 let elem: crate::Element = isotope.into();
262 assert_eq!(elem, crate::Element::Ne);
263 }
264 }
265 #[test]
266 fn test_try_from_mass_number() {
267 for isotope in NeonIsotope::iter() {
268 let mass = isotope.mass_number();
269 let iso = NeonIsotope::try_from(mass).unwrap();
270 assert_eq!(iso, isotope);
271 let iso_u32 = NeonIsotope::try_from(u32::from(mass)).unwrap();
272 assert_eq!(iso_u32, isotope);
273 if let Ok(mass_u8) = u8::try_from(mass) {
274 let iso_u8 = NeonIsotope::try_from(mass_u8).unwrap();
275 assert_eq!(iso_u8, isotope);
276 }
277 }
278 assert!(NeonIsotope::try_from(0_u16).is_err());
279 assert!(NeonIsotope::try_from(1000_u16).is_err());
280 assert!(NeonIsotope::try_from(0_u32).is_err());
281 assert!(NeonIsotope::try_from(1000_u32).is_err());
282 assert!(NeonIsotope::try_from(0_u8).is_err());
283 }
284 #[test]
285 fn test_display() {
286 for isotope in NeonIsotope::iter() {
287 let s = alloc::format!("{isotope}");
288 assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
289 }
290 }
291}