use_molecule/
molecular_atom.rs1use std::fmt;
2
3use crate::{AtomLabel, MoleculeValidationError};
4
5#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
7pub struct MolecularAtomId(String);
8
9impl MolecularAtomId {
10 pub fn new(id: &str) -> Result<Self, MoleculeValidationError> {
16 let trimmed = id.trim();
17 if trimmed.is_empty() {
18 Err(MoleculeValidationError::EmptyAtomId)
19 } else {
20 Ok(Self(trimmed.to_owned()))
21 }
22 }
23
24 #[must_use]
26 pub fn as_str(&self) -> &str {
27 &self.0
28 }
29
30 #[must_use]
32 pub fn into_string(self) -> String {
33 self.0
34 }
35}
36
37impl AsRef<str> for MolecularAtomId {
38 fn as_ref(&self) -> &str {
39 self.as_str()
40 }
41}
42
43impl TryFrom<&str> for MolecularAtomId {
44 type Error = MoleculeValidationError;
45
46 fn try_from(value: &str) -> Result<Self, Self::Error> {
47 Self::new(value)
48 }
49}
50
51impl fmt::Display for MolecularAtomId {
52 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
53 formatter.write_str(self.as_str())
54 }
55}
56
57#[derive(Clone, Debug, Eq, PartialEq)]
59pub struct MolecularAtom {
60 label: AtomLabel,
61 id: Option<MolecularAtomId>,
62}
63
64impl MolecularAtom {
65 pub fn new(label: &str) -> Result<Self, MoleculeValidationError> {
72 Ok(Self {
73 label: AtomLabel::new(label)?,
74 id: None,
75 })
76 }
77
78 #[must_use]
80 pub const fn label(&self) -> &AtomLabel {
81 &self.label
82 }
83
84 #[must_use]
86 pub const fn id(&self) -> Option<&MolecularAtomId> {
87 self.id.as_ref()
88 }
89
90 #[must_use]
92 pub fn with_id(mut self, id: MolecularAtomId) -> Self {
93 self.id = Some(id);
94 self
95 }
96
97 pub fn try_with_id(self, id: &str) -> Result<Self, MoleculeValidationError> {
103 Ok(self.with_id(MolecularAtomId::new(id)?))
104 }
105}
106
107impl fmt::Display for MolecularAtom {
108 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
109 match &self.id {
110 Some(id) => write!(formatter, "{}#{id}", self.label),
111 None => write!(formatter, "{}", self.label),
112 }
113 }
114}