Skip to main content

use_molecule/
atom_label.rs

1use std::fmt;
2
3use use_chemical_formula::ElementSymbol;
4
5use crate::MoleculeValidationError;
6
7/// A validated atom label with a basic element-symbol shape.
8#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
9pub struct AtomLabel(ElementSymbol);
10
11impl AtomLabel {
12    /// Creates an atom label.
13    ///
14    /// # Errors
15    ///
16    /// Returns [`MoleculeValidationError::EmptyAtomLabel`] when `label` is empty after trimming, or
17    /// [`MoleculeValidationError::InvalidAtomLabel`] when the label does not match the supported
18    /// element-symbol shape.
19    pub fn new(label: &str) -> Result<Self, MoleculeValidationError> {
20        let trimmed = label.trim();
21        if trimmed.is_empty() {
22            return Err(MoleculeValidationError::EmptyAtomLabel);
23        }
24
25        ElementSymbol::new(trimmed)
26            .map(Self)
27            .map_err(|_| MoleculeValidationError::InvalidAtomLabel(trimmed.to_owned()))
28    }
29
30    /// Returns the atom label text.
31    #[must_use]
32    pub fn as_str(&self) -> &str {
33        self.0.as_str()
34    }
35
36    /// Returns the wrapped formula element-symbol value.
37    #[must_use]
38    pub const fn as_element_symbol(&self) -> &ElementSymbol {
39        &self.0
40    }
41}
42
43impl AsRef<str> for AtomLabel {
44    fn as_ref(&self) -> &str {
45        self.as_str()
46    }
47}
48
49impl TryFrom<&str> for AtomLabel {
50    type Error = MoleculeValidationError;
51
52    fn try_from(value: &str) -> Result<Self, Self::Error> {
53        Self::new(value)
54    }
55}
56
57impl fmt::Display for AtomLabel {
58    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
59        formatter.write_str(self.as_str())
60    }
61}