1use std::fmt;
2
3use use_chemical_formula::ChemicalFormula;
4
5use crate::{Ion, IonCharge, IonKind, IonValidationError};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct MonatomicIon(Ion);
10
11impl MonatomicIon {
12 pub fn new(formula: ChemicalFormula, charge: IonCharge) -> Result<Self, IonValidationError> {
19 Self::from_ion(Ion::new(formula, charge))
20 }
21
22 pub fn from_ion(ion: Ion) -> Result<Self, IonValidationError> {
29 if is_monatomic(ion.formula()) {
30 Ok(Self(ion.with_kind(IonKind::Monatomic)))
31 } else {
32 Err(IonValidationError::ExpectedMonatomicFormula)
33 }
34 }
35
36 #[must_use]
38 pub const fn as_ion(&self) -> &Ion {
39 &self.0
40 }
41
42 #[must_use]
44 pub fn into_ion(self) -> Ion {
45 self.0
46 }
47}
48
49impl fmt::Display for MonatomicIon {
50 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
51 write!(formatter, "{}", self.0)
52 }
53}
54
55fn is_monatomic(formula: &ChemicalFormula) -> bool {
56 let counts = formula.element_counts();
57 counts.len() == 1 && counts.values().copied().sum::<u64>() == 1
58}