#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "mem_size", derive(mem_dbg::MemSize))]
#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg))]
#[cfg_attr(feature = "mem_size", mem_size(flat))]
pub enum RutheniumIsotope {
Ru85,
Ru86,
Ru87,
Ru88,
Ru89,
Ru90,
Ru91,
Ru92,
Ru93,
Ru94,
Ru95,
Ru96,
Ru97,
Ru98,
Ru99,
Ru100,
Ru101,
Ru102,
Ru103,
Ru104,
Ru105,
Ru106,
Ru107,
Ru108,
Ru109,
Ru110,
Ru111,
Ru112,
Ru113,
Ru114,
Ru115,
Ru116,
Ru117,
Ru118,
Ru119,
Ru120,
Ru121,
Ru122,
Ru123,
Ru124,
Ru125,
}
impl super::RelativeAtomicMass for RutheniumIsotope {
#[inline]
fn relative_atomic_mass(&self) -> f64 {
match self {
Self::Ru85 => 84.967117f64,
Self::Ru86 => 85.957305f64,
Self::Ru87 => 86.95069f64,
Self::Ru88 => 87.9416f64,
Self::Ru89 => 88.93762f64,
Self::Ru90 => 89.9303444f64,
Self::Ru91 => 90.9267419f64,
Self::Ru92 => 91.9202344f64,
Self::Ru93 => 92.9171044f64,
Self::Ru94 => 93.9113429f64,
Self::Ru95 => 94.910406f64,
Self::Ru96 => 95.90759025f64,
Self::Ru97 => 96.9075471f64,
Self::Ru98 => 97.9052868f64,
Self::Ru99 => 98.9059341f64,
Self::Ru100 => 99.9042143f64,
Self::Ru101 => 100.9055769f64,
Self::Ru102 => 101.9043441f64,
Self::Ru103 => 102.9063186f64,
Self::Ru104 => 103.9054275f64,
Self::Ru105 => 104.9077476f64,
Self::Ru106 => 105.9073291f64,
Self::Ru107 => 106.909972f64,
Self::Ru108 => 107.910188f64,
Self::Ru109 => 108.913326f64,
Self::Ru110 => 109.9140407f64,
Self::Ru111 => 110.91757f64,
Self::Ru112 => 111.918809f64,
Self::Ru113 => 112.922844f64,
Self::Ru114 => 113.9246136f64,
Self::Ru115 => 114.92882f64,
Self::Ru116 => 115.9312192f64,
Self::Ru117 => 116.9361f64,
Self::Ru118 => 117.93853f64,
Self::Ru119 => 118.94357f64,
Self::Ru120 => 119.94631f64,
Self::Ru121 => 120.95164f64,
Self::Ru122 => 121.95447f64,
Self::Ru123 => 122.95989f64,
Self::Ru124 => 123.96305f64,
Self::Ru125 => 124.969544f64,
}
}
}
impl super::ElementVariant for RutheniumIsotope {
#[inline]
fn element(&self) -> crate::Element {
crate::Element::Ru
}
}
impl super::MassNumber for RutheniumIsotope {
#[inline]
fn mass_number(&self) -> u16 {
match self {
Self::Ru85 => 85u16,
Self::Ru86 => 86u16,
Self::Ru87 => 87u16,
Self::Ru88 => 88u16,
Self::Ru89 => 89u16,
Self::Ru90 => 90u16,
Self::Ru91 => 91u16,
Self::Ru92 => 92u16,
Self::Ru93 => 93u16,
Self::Ru94 => 94u16,
Self::Ru95 => 95u16,
Self::Ru96 => 96u16,
Self::Ru97 => 97u16,
Self::Ru98 => 98u16,
Self::Ru99 => 99u16,
Self::Ru100 => 100u16,
Self::Ru101 => 101u16,
Self::Ru102 => 102u16,
Self::Ru103 => 103u16,
Self::Ru104 => 104u16,
Self::Ru105 => 105u16,
Self::Ru106 => 106u16,
Self::Ru107 => 107u16,
Self::Ru108 => 108u16,
Self::Ru109 => 109u16,
Self::Ru110 => 110u16,
Self::Ru111 => 111u16,
Self::Ru112 => 112u16,
Self::Ru113 => 113u16,
Self::Ru114 => 114u16,
Self::Ru115 => 115u16,
Self::Ru116 => 116u16,
Self::Ru117 => 117u16,
Self::Ru118 => 118u16,
Self::Ru119 => 119u16,
Self::Ru120 => 120u16,
Self::Ru121 => 121u16,
Self::Ru122 => 122u16,
Self::Ru123 => 123u16,
Self::Ru124 => 124u16,
Self::Ru125 => 125u16,
}
}
}
impl super::IsotopicComposition for RutheniumIsotope {
#[inline]
fn isotopic_composition(&self) -> Option<f64> {
match self {
Self::Ru96 => Some(0.0554f64),
Self::Ru98 => Some(0.0187f64),
Self::Ru99 => Some(0.1276f64),
Self::Ru100 => Some(0.126f64),
Self::Ru101 => Some(0.1706f64),
Self::Ru102 => Some(0.3155f64),
Self::Ru104 => Some(0.1862f64),
_ => None,
}
}
}
impl super::MostAbundantIsotope for RutheniumIsotope {
fn most_abundant_isotope() -> Self {
Self::Ru102
}
}
impl From<RutheniumIsotope> for crate::Isotope {
fn from(isotope: RutheniumIsotope) -> Self {
crate::Isotope::Ru(isotope)
}
}
impl From<RutheniumIsotope> for crate::Element {
fn from(_isotope: RutheniumIsotope) -> Self {
crate::Element::Ru
}
}
impl TryFrom<u64> for RutheniumIsotope {
type Error = crate::errors::Error;
fn try_from(value: u64) -> Result<Self, Self::Error> {
match value {
85u64 => Ok(Self::Ru85),
86u64 => Ok(Self::Ru86),
87u64 => Ok(Self::Ru87),
88u64 => Ok(Self::Ru88),
89u64 => Ok(Self::Ru89),
90u64 => Ok(Self::Ru90),
91u64 => Ok(Self::Ru91),
92u64 => Ok(Self::Ru92),
93u64 => Ok(Self::Ru93),
94u64 => Ok(Self::Ru94),
95u64 => Ok(Self::Ru95),
96u64 => Ok(Self::Ru96),
97u64 => Ok(Self::Ru97),
98u64 => Ok(Self::Ru98),
99u64 => Ok(Self::Ru99),
100u64 => Ok(Self::Ru100),
101u64 => Ok(Self::Ru101),
102u64 => Ok(Self::Ru102),
103u64 => Ok(Self::Ru103),
104u64 => Ok(Self::Ru104),
105u64 => Ok(Self::Ru105),
106u64 => Ok(Self::Ru106),
107u64 => Ok(Self::Ru107),
108u64 => Ok(Self::Ru108),
109u64 => Ok(Self::Ru109),
110u64 => Ok(Self::Ru110),
111u64 => Ok(Self::Ru111),
112u64 => Ok(Self::Ru112),
113u64 => Ok(Self::Ru113),
114u64 => Ok(Self::Ru114),
115u64 => Ok(Self::Ru115),
116u64 => Ok(Self::Ru116),
117u64 => Ok(Self::Ru117),
118u64 => Ok(Self::Ru118),
119u64 => Ok(Self::Ru119),
120u64 => Ok(Self::Ru120),
121u64 => Ok(Self::Ru121),
122u64 => Ok(Self::Ru122),
123u64 => Ok(Self::Ru123),
124u64 => Ok(Self::Ru124),
125u64 => Ok(Self::Ru125),
_ => Err(crate::errors::Error::Isotope(crate::Element::Ru, value)),
}
}
}
impl TryFrom<u8> for RutheniumIsotope {
type Error = crate::errors::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
Self::try_from(u64::from(value))
}
}
impl TryFrom<u16> for RutheniumIsotope {
type Error = crate::errors::Error;
fn try_from(value: u16) -> Result<Self, Self::Error> {
Self::try_from(u64::from(value))
}
}
impl TryFrom<u32> for RutheniumIsotope {
type Error = crate::errors::Error;
fn try_from(value: u32) -> Result<Self, Self::Error> {
Self::try_from(u64::from(value))
}
}
impl core::fmt::Display for RutheniumIsotope {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Ru85 => write!(f, "Ru85"),
Self::Ru86 => write!(f, "Ru86"),
Self::Ru87 => write!(f, "Ru87"),
Self::Ru88 => write!(f, "Ru88"),
Self::Ru89 => write!(f, "Ru89"),
Self::Ru90 => write!(f, "Ru90"),
Self::Ru91 => write!(f, "Ru91"),
Self::Ru92 => write!(f, "Ru92"),
Self::Ru93 => write!(f, "Ru93"),
Self::Ru94 => write!(f, "Ru94"),
Self::Ru95 => write!(f, "Ru95"),
Self::Ru96 => write!(f, "Ru96"),
Self::Ru97 => write!(f, "Ru97"),
Self::Ru98 => write!(f, "Ru98"),
Self::Ru99 => write!(f, "Ru99"),
Self::Ru100 => write!(f, "Ru100"),
Self::Ru101 => write!(f, "Ru101"),
Self::Ru102 => write!(f, "Ru102"),
Self::Ru103 => write!(f, "Ru103"),
Self::Ru104 => write!(f, "Ru104"),
Self::Ru105 => write!(f, "Ru105"),
Self::Ru106 => write!(f, "Ru106"),
Self::Ru107 => write!(f, "Ru107"),
Self::Ru108 => write!(f, "Ru108"),
Self::Ru109 => write!(f, "Ru109"),
Self::Ru110 => write!(f, "Ru110"),
Self::Ru111 => write!(f, "Ru111"),
Self::Ru112 => write!(f, "Ru112"),
Self::Ru113 => write!(f, "Ru113"),
Self::Ru114 => write!(f, "Ru114"),
Self::Ru115 => write!(f, "Ru115"),
Self::Ru116 => write!(f, "Ru116"),
Self::Ru117 => write!(f, "Ru117"),
Self::Ru118 => write!(f, "Ru118"),
Self::Ru119 => write!(f, "Ru119"),
Self::Ru120 => write!(f, "Ru120"),
Self::Ru121 => write!(f, "Ru121"),
Self::Ru122 => write!(f, "Ru122"),
Self::Ru123 => write!(f, "Ru123"),
Self::Ru124 => write!(f, "Ru124"),
Self::Ru125 => write!(f, "Ru125"),
}
}
}
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use super::*;
use crate::isotopes::{
ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
};
#[test]
fn test_relative_atomic_mass() {
for isotope in RutheniumIsotope::iter() {
let mass = isotope.relative_atomic_mass();
assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
}
}
#[test]
fn test_element() {
for isotope in RutheniumIsotope::iter() {
let element = isotope.element();
assert_eq!(element, crate::Element::Ru, "Element should be correct for {isotope:?}");
}
}
#[test]
fn test_mass_number() {
for isotope in RutheniumIsotope::iter() {
let mass_number = isotope.mass_number();
assert!(
mass_number > 0 && mass_number < 300,
"Mass number should be reasonable for {isotope:?}"
);
}
}
#[test]
fn test_isotopic_composition() {
for isotope in RutheniumIsotope::iter() {
let comp = isotope.isotopic_composition();
if let Some(c) = comp {
assert!(
(0.0..=1.0).contains(&c),
"Composition should be between 0 and 1 for {isotope:?}"
);
}
}
}
#[test]
fn test_most_abundant() {
let most_abundant = RutheniumIsotope::most_abundant_isotope();
let _ = most_abundant.relative_atomic_mass();
}
#[test]
fn test_from_isotope() {
for isotope in RutheniumIsotope::iter() {
let iso: crate::Isotope = isotope.into();
match iso {
crate::Isotope::Ru(i) => assert_eq!(i, isotope),
_ => panic!("Wrong isotope type"),
}
}
}
#[test]
fn test_from_element() {
for isotope in RutheniumIsotope::iter() {
let elem: crate::Element = isotope.into();
assert_eq!(elem, crate::Element::Ru);
}
}
#[test]
fn test_try_from_mass_number() {
for isotope in RutheniumIsotope::iter() {
let mass = isotope.mass_number();
let iso = RutheniumIsotope::try_from(mass).unwrap();
assert_eq!(iso, isotope);
let iso_u32 = RutheniumIsotope::try_from(u32::from(mass)).unwrap();
assert_eq!(iso_u32, isotope);
if let Ok(mass_u8) = u8::try_from(mass) {
let iso_u8 = RutheniumIsotope::try_from(mass_u8).unwrap();
assert_eq!(iso_u8, isotope);
}
}
assert!(RutheniumIsotope::try_from(0_u16).is_err());
assert!(RutheniumIsotope::try_from(1000_u16).is_err());
assert!(RutheniumIsotope::try_from(0_u32).is_err());
assert!(RutheniumIsotope::try_from(1000_u32).is_err());
assert!(RutheniumIsotope::try_from(0_u8).is_err());
}
#[test]
fn test_display() {
for isotope in RutheniumIsotope::iter() {
let s = alloc::format!("{isotope}");
assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
}
}
}