use_oxidation_state/
oxidation_state_set.rs1use std::fmt;
2use std::slice;
3
4use crate::OxidationStateAssignment;
5
6#[derive(Clone, Debug, Default, Eq, PartialEq)]
8pub struct OxidationStateSet {
9 assignments: Vec<OxidationStateAssignment>,
10}
11
12impl OxidationStateSet {
13 #[must_use]
15 pub const fn new() -> Self {
16 Self {
17 assignments: Vec::new(),
18 }
19 }
20
21 #[must_use]
23 pub fn from_assignments(
24 assignments: impl IntoIterator<Item = OxidationStateAssignment>,
25 ) -> Self {
26 let mut set = Self::new();
27
28 for assignment in assignments {
29 set.insert(assignment);
30 }
31
32 set
33 }
34
35 pub fn insert(
37 &mut self,
38 assignment: OxidationStateAssignment,
39 ) -> Option<OxidationStateAssignment> {
40 if let Some(existing) = self
41 .assignments
42 .iter_mut()
43 .find(|existing| existing.label() == assignment.label())
44 {
45 return Some(std::mem::replace(existing, assignment));
46 }
47
48 self.assignments.push(assignment);
49 None
50 }
51
52 #[must_use]
54 pub fn get(&self, label: &str) -> Option<&OxidationStateAssignment> {
55 let label = label.trim();
56 self.assignments
57 .iter()
58 .find(|assignment| assignment.label() == label)
59 }
60
61 #[must_use]
63 pub fn contains_label(&self, label: &str) -> bool {
64 self.get(label).is_some()
65 }
66
67 #[must_use]
69 pub fn len(&self) -> usize {
70 self.assignments.len()
71 }
72
73 #[must_use]
75 pub fn is_empty(&self) -> bool {
76 self.assignments.is_empty()
77 }
78
79 pub fn iter(&self) -> slice::Iter<'_, OxidationStateAssignment> {
81 self.assignments.iter()
82 }
83}
84
85impl fmt::Display for OxidationStateSet {
86 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
87 let mut assignments = self.assignments.iter();
88
89 let Some(first) = assignments.next() else {
90 return Ok(());
91 };
92
93 write!(formatter, "{first}")?;
94
95 for assignment in assignments {
96 write!(formatter, ", {assignment}")?;
97 }
98
99 Ok(())
100 }
101}
102
103impl IntoIterator for OxidationStateSet {
104 type IntoIter = std::vec::IntoIter<Self::Item>;
105 type Item = OxidationStateAssignment;
106
107 fn into_iter(self) -> Self::IntoIter {
108 self.assignments.into_iter()
109 }
110}
111
112impl<'a> IntoIterator for &'a OxidationStateSet {
113 type IntoIter = slice::Iter<'a, OxidationStateAssignment>;
114 type Item = &'a OxidationStateAssignment;
115
116 fn into_iter(self) -> Self::IntoIter {
117 self.iter()
118 }
119}