cml/
one_or_many.rs
1use std::fmt::{self, Display, Formatter};
6use std::{slice, vec};
7
8#[derive(Debug, Clone, Ord, PartialOrd, Eq)]
11pub enum OneOrMany<T> {
12 One(T),
14 Many(Vec<T>),
16}
17
18impl<T> OneOrMany<T> {
19 pub fn is_many(&self) -> bool {
21 match self {
22 Self::One(_) => false,
23 Self::Many(_) => true,
24 }
25 }
26
27 pub fn iter(&self) -> Iter<'_, T> {
29 match self {
30 Self::One(item) => Iter { inner_one: Some(item), inner_many: None },
31 Self::Many(items) => Iter { inner_one: None, inner_many: Some(items.iter()) },
32 }
33 }
34
35 pub fn len(&self) -> usize {
37 match self {
38 Self::One(_) => 1,
39 Self::Many(v) => v.len(),
40 }
41 }
42
43 pub fn as_ref(&self) -> OneOrMany<&T> {
45 match self {
46 Self::One(o) => OneOrMany::<&T>::One(o),
47 Self::Many(v) => OneOrMany::<&T>::Many(v.iter().collect()),
48 }
49 }
50}
51
52impl<T> OneOrMany<T>
53where
54 T: Ord + Clone,
55{
56 pub fn canonicalize(&mut self) {
60 let mut replace_with = None;
61 match self {
62 OneOrMany::One(_) => {}
63 OneOrMany::Many(many) => {
64 if many.len() == 1 {
65 replace_with = Some(many.first().unwrap().clone());
66 } else {
67 many.sort();
68 }
69 }
70 }
71 if let Some(t) = replace_with {
72 *self = OneOrMany::One(t);
73 }
74 }
75}
76
77impl<T> OneOrMany<T>
78where
79 T: PartialEq,
80{
81 pub fn contains(&self, e: &T) -> bool {
83 match self {
84 Self::One(item) => item == e,
85 Self::Many(items) => items.contains(e),
86 }
87 }
88}
89
90impl<T> PartialEq for OneOrMany<T>
91where
92 T: PartialEq,
93{
94 fn eq(&self, other: &Self) -> bool {
95 self.iter().eq(other.into_iter())
96 }
97}
98
99impl<'a, T> IntoIterator for &'a OneOrMany<T> {
100 type Item = &'a T;
101 type IntoIter = Iter<'a, T>;
102
103 fn into_iter(self) -> Iter<'a, T> {
104 self.iter()
105 }
106}
107
108impl<T> IntoIterator for OneOrMany<T> {
109 type Item = T;
110 type IntoIter = IntoIter<T>;
111
112 fn into_iter(self) -> IntoIter<T> {
113 match self {
114 OneOrMany::One(item) => IntoIter { inner_one: Some(item), inner_many: None },
115 OneOrMany::Many(items) => {
116 IntoIter { inner_one: None, inner_many: Some(items.into_iter()) }
117 }
118 }
119 }
120}
121
122impl<T> FromIterator<T> for OneOrMany<T> {
123 fn from_iter<I>(iter: I) -> Self
124 where
125 I: IntoIterator<Item = T> + Sized,
126 {
127 let mut iter = iter.into_iter();
128 if let Some(first) = iter.next() {
129 let rest: Vec<_> = iter.collect();
130 if rest.is_empty() {
131 Self::One(first)
132 } else {
133 let mut out = vec![first];
134 out.extend(rest);
135 Self::Many(out)
136 }
137 } else {
138 Self::Many(vec![])
139 }
140 }
141}
142
143impl<T> From<T> for OneOrMany<T> {
144 fn from(item: T) -> Self {
145 Self::One(item)
146 }
147}
148
149impl<'a, T: Display> Display for OneOrMany<T> {
150 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
151 match self {
152 OneOrMany::One(item) => Display::fmt(item, f),
153 OneOrMany::Many(items) => {
154 let mut iter = items.iter();
155 if let Some(first_item) = iter.next() {
156 Display::fmt(first_item, f)?;
157 }
158 for item in iter {
159 f.write_str(", ")?;
160 Display::fmt(item, f)?;
161 }
162 Ok(())
163 }
164 }
165 }
166}
167
168pub struct Iter<'a, T> {
173 inner_one: Option<&'a T>,
174 inner_many: Option<slice::Iter<'a, T>>,
175}
176
177impl<'a, T> Iterator for Iter<'a, T> {
178 type Item = &'a T;
179
180 fn next(&mut self) -> Option<Self::Item> {
181 if let Some(item) = self.inner_one.take() {
182 Some(item)
183 } else if let Some(ref mut iter) = &mut self.inner_many {
184 iter.next()
185 } else {
186 None
187 }
188 }
189
190 fn size_hint(&self) -> (usize, Option<usize>) {
191 if let Some(_) = self.inner_one {
192 (1, Some(1))
193 } else if let Some(iter) = &self.inner_many {
194 iter.size_hint()
195 } else {
196 (0, Some(0))
197 }
198 }
199}
200
201impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
202
203pub struct IntoIter<T> {
209 inner_one: Option<T>,
210 inner_many: Option<vec::IntoIter<T>>,
211}
212
213impl<T> Iterator for IntoIter<T> {
214 type Item = T;
215
216 fn next(&mut self) -> Option<Self::Item> {
217 if let Some(item) = self.inner_one.take() {
218 Some(item)
219 } else if let Some(ref mut iter) = &mut self.inner_many {
220 iter.next()
221 } else {
222 None
223 }
224 }
225
226 fn size_hint(&self) -> (usize, Option<usize>) {
227 if let Some(_) = self.inner_one {
228 (1, Some(1))
229 } else if let Some(iter) = &self.inner_many {
230 iter.size_hint()
231 } else {
232 (0, Some(0))
233 }
234 }
235}
236
237impl<T> ExactSizeIterator for IntoIter<T> {}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242 use assert_matches::assert_matches;
243
244 #[test]
245 fn test_iter_one() {
246 let v = OneOrMany::One(34);
247 let mut iter = v.iter();
248 assert_matches!(iter.next(), Some(&34));
249 assert_matches!(iter.next(), None);
250 }
251
252 #[test]
253 fn test_iter_many() {
254 let v = OneOrMany::Many(vec![1, 2, 3]);
255 let mut iter = v.iter();
256 assert_matches!(iter.next(), Some(&1));
257 assert_matches!(iter.next(), Some(&2));
258 assert_matches!(iter.next(), Some(&3));
259 assert_matches!(iter.next(), None);
260 }
261
262 #[test]
263 fn test_is_many() {
264 let v = OneOrMany::One(34);
265 assert_eq!(v.is_many(), false);
266
267 let v = OneOrMany::Many(vec![1, 2, 3]);
268 assert_eq!(v.is_many(), true);
269 }
270
271 #[test]
272 fn test_from_iter() {
273 let o: OneOrMany<i64> = [34].into_iter().collect();
274 assert_eq!(o, OneOrMany::One(34));
275
276 let o: OneOrMany<i64> = [1, 2, 3].into_iter().collect();
277 assert_eq!(o, OneOrMany::Many(vec![1, 2, 3]));
278
279 let o: OneOrMany<i64> = [].into_iter().collect();
280 assert_eq!(o, OneOrMany::Many(vec![]));
281 }
282
283 #[test]
284 fn test_display() {
285 let val = 34;
286 let v = OneOrMany::One(val);
287 assert_eq!(v.to_string(), "34");
288
289 let val = vec![1, 2, 3];
290 let v = OneOrMany::Many(val);
291 assert_eq!(v.to_string(), "1, 2, 3");
292 }
293}