1use crate::{AnyRef, ContextSpanned};
6use std::fmt::{self, Display, Formatter};
7use std::{slice, vec};
8
9#[derive(Debug, Clone, Ord, PartialOrd, Eq)]
12pub enum OneOrMany<T> {
13 One(T),
15 Many(Vec<T>),
17}
18
19impl<T> OneOrMany<T> {
20 pub fn is_many(&self) -> bool {
22 match self {
23 Self::One(_) => false,
24 Self::Many(_) => true,
25 }
26 }
27
28 pub fn iter(&self) -> Iter<'_, T> {
30 match self {
31 Self::One(item) => Iter { inner_one: Some(item), inner_many: None },
32 Self::Many(items) => Iter { inner_one: None, inner_many: Some(items.iter()) },
33 }
34 }
35
36 pub fn len(&self) -> usize {
38 match self {
39 Self::One(_) => 1,
40 Self::Many(v) => v.len(),
41 }
42 }
43
44 pub fn as_ref<S>(&self) -> OneOrMany<&S>
46 where
47 T: AsRef<S>,
48 S: ?Sized,
49 {
50 match self {
51 Self::One(o) => OneOrMany::<&S>::One(o.as_ref()),
52 Self::Many(v) => OneOrMany::<&S>::Many(v.iter().map(|o| o.as_ref()).collect()),
53 }
54 }
55}
56
57impl<T> OneOrMany<T>
58where
59 T: Ord + Clone,
60{
61 pub fn canonicalize(&mut self) {
65 let mut replace_with = None;
66 match self {
67 OneOrMany::One(_) => {}
68 OneOrMany::Many(many) => {
69 if many.len() == 1 {
70 replace_with = Some(many.first().unwrap().clone());
71 } else {
72 many.sort();
73 }
74 }
75 }
76 if let Some(t) = replace_with {
77 *self = OneOrMany::One(t);
78 }
79 }
80}
81
82impl<T> OneOrMany<T>
83where
84 T: Ord + Clone,
85{
86 pub fn canonicalize_context(&mut self) {
90 let mut replace_with = None;
91 match self {
92 OneOrMany::One(_) => {}
93 OneOrMany::Many(many) => {
94 if many.len() == 1 {
95 replace_with = Some(many.first().unwrap().clone());
96 } else {
97 many.sort();
98 }
99 }
100 }
101 if let Some(t) = replace_with {
102 *self = OneOrMany::One(t);
103 }
104 }
105}
106
107impl<T> OneOrMany<T>
108where
109 T: PartialEq,
110{
111 pub fn contains(&self, e: &T) -> bool {
113 match self {
114 Self::One(item) => item == e,
115 Self::Many(items) => items.contains(e),
116 }
117 }
118}
119
120impl<T> PartialEq for OneOrMany<T>
121where
122 T: PartialEq,
123{
124 fn eq(&self, other: &Self) -> bool {
125 self.iter().eq(other.into_iter())
126 }
127}
128
129impl<'a, T> IntoIterator for &'a OneOrMany<T> {
130 type Item = &'a T;
131 type IntoIter = Iter<'a, T>;
132
133 fn into_iter(self) -> Iter<'a, T> {
134 self.iter()
135 }
136}
137
138impl<T> IntoIterator for OneOrMany<T> {
139 type Item = T;
140 type IntoIter = IntoIter<T>;
141
142 fn into_iter(self) -> IntoIter<T> {
143 match self {
144 OneOrMany::One(item) => IntoIter { inner_one: Some(item), inner_many: None },
145 OneOrMany::Many(items) => {
146 IntoIter { inner_one: None, inner_many: Some(items.into_iter()) }
147 }
148 }
149 }
150}
151
152impl<T> FromIterator<T> for OneOrMany<T> {
153 fn from_iter<I>(iter: I) -> Self
154 where
155 I: IntoIterator<Item = T> + Sized,
156 {
157 let mut iter = iter.into_iter();
158 if let Some(first) = iter.next() {
159 let rest: Vec<_> = iter.collect();
160 if rest.is_empty() {
161 Self::One(first)
162 } else {
163 let mut out = vec![first];
164 out.extend(rest);
165 Self::Many(out)
166 }
167 } else {
168 Self::Many(vec![])
169 }
170 }
171}
172
173impl<T> From<T> for OneOrMany<T> {
174 fn from(item: T) -> Self {
175 Self::One(item)
176 }
177}
178
179impl<'a, T: Display> Display for OneOrMany<T> {
180 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
181 match self {
182 OneOrMany::One(item) => Display::fmt(item, f),
183 OneOrMany::Many(items) => {
184 let mut iter = items.iter();
185 if let Some(first_item) = iter.next() {
186 Display::fmt(first_item, f)?;
187 }
188 for item in iter {
189 f.write_str(", ")?;
190 Display::fmt(item, f)?;
191 }
192 Ok(())
193 }
194 }
195 }
196}
197
198pub struct Iter<'a, T> {
203 inner_one: Option<&'a T>,
204 inner_many: Option<slice::Iter<'a, T>>,
205}
206
207impl<'a, T> Iterator for Iter<'a, T> {
208 type Item = &'a T;
209
210 fn next(&mut self) -> Option<Self::Item> {
211 if let Some(item) = self.inner_one.take() {
212 Some(item)
213 } else if let Some(iter) = &mut self.inner_many {
214 iter.next()
215 } else {
216 None
217 }
218 }
219
220 fn size_hint(&self) -> (usize, Option<usize>) {
221 if let Some(_) = self.inner_one {
222 (1, Some(1))
223 } else if let Some(iter) = &self.inner_many {
224 iter.size_hint()
225 } else {
226 (0, Some(0))
227 }
228 }
229}
230
231impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
232
233pub struct IntoIter<T> {
239 inner_one: Option<T>,
240 inner_many: Option<vec::IntoIter<T>>,
241}
242
243impl<T> Iterator for IntoIter<T> {
244 type Item = T;
245
246 fn next(&mut self) -> Option<Self::Item> {
247 if let Some(item) = self.inner_one.take() {
248 Some(item)
249 } else if let Some(iter) = &mut self.inner_many {
250 iter.next()
251 } else {
252 None
253 }
254 }
255
256 fn size_hint(&self) -> (usize, Option<usize>) {
257 if let Some(_) = self.inner_one {
258 (1, Some(1))
259 } else if let Some(iter) = &self.inner_many {
260 iter.size_hint()
261 } else {
262 (0, Some(0))
263 }
264 }
265}
266
267impl<T> ExactSizeIterator for IntoIter<T> {}
268
269pub(crate) fn always_one<T>(o: Option<OneOrMany<T>>) -> Option<T> {
270 o.map(|o| match o {
271 OneOrMany::One(o) => o,
272 OneOrMany::Many(_) => panic!("many is impossible"),
273 })
274}
275
276pub(crate) fn always_one_context<T>(
277 o: Option<ContextSpanned<OneOrMany<T>>>,
278) -> Option<ContextSpanned<T>> {
279 o.map(|spanned| {
280 let single_val = match spanned.value {
281 OneOrMany::One(val) => val,
282 OneOrMany::Many(_) => panic!("many is impossible"),
283 };
284
285 ContextSpanned { value: single_val, origin: spanned.origin }
286 })
287}
288
289pub(crate) fn option_one_or_many_as_ref<T, S: ?Sized>(
290 o: &Option<OneOrMany<T>>,
291) -> Option<OneOrMany<&S>>
292where
293 T: AsRef<S>,
294{
295 o.as_ref().map(|o| o.as_ref())
296}
297
298pub(crate) fn one_or_many_from_impl<'a, T>(from: &'a OneOrMany<T>) -> OneOrMany<AnyRef<'a>>
299where
300 AnyRef<'a>: From<&'a T>,
301 T: 'a,
302{
303 let r = match from {
304 OneOrMany::One(r) => OneOrMany::One(r.into()),
305 OneOrMany::Many(v) => OneOrMany::Many(v.into_iter().map(|r| r.into()).collect()),
306 };
307 r.into()
308}
309
310pub(crate) fn one_or_many_from_context<'a, T>(
311 from: &'a ContextSpanned<OneOrMany<T>>,
312) -> ContextSpanned<OneOrMany<AnyRef<'a>>>
313where
314 AnyRef<'a>: From<&'a T>,
315 T: 'a,
316{
317 let origin = from.origin.clone();
318
319 let converted_value = match &from.value {
320 OneOrMany::One(r) => OneOrMany::One(r.into()),
321 OneOrMany::Many(v) => {
322 let converted_vec = v.iter().map(|r| r.into()).collect();
323 OneOrMany::Many(converted_vec)
324 }
325 };
326
327 ContextSpanned { value: converted_value, origin }
328}
329
330#[cfg(test)]
331mod tests {
332 use super::*;
333 use assert_matches::assert_matches;
334
335 #[test]
336 fn test_iter_one() {
337 let v = OneOrMany::One(34);
338 let mut iter = v.iter();
339 assert_matches!(iter.next(), Some(&34));
340 assert_matches!(iter.next(), None);
341 }
342
343 #[test]
344 fn test_iter_many() {
345 let v = OneOrMany::Many(vec![1, 2, 3]);
346 let mut iter = v.iter();
347 assert_matches!(iter.next(), Some(&1));
348 assert_matches!(iter.next(), Some(&2));
349 assert_matches!(iter.next(), Some(&3));
350 assert_matches!(iter.next(), None);
351 }
352
353 #[test]
354 fn test_is_many() {
355 let v = OneOrMany::One(34);
356 assert_eq!(v.is_many(), false);
357
358 let v = OneOrMany::Many(vec![1, 2, 3]);
359 assert_eq!(v.is_many(), true);
360 }
361
362 #[test]
363 fn test_from_iter() {
364 let o: OneOrMany<i64> = [34].into_iter().collect();
365 assert_eq!(o, OneOrMany::One(34));
366
367 let o: OneOrMany<i64> = [1, 2, 3].into_iter().collect();
368 assert_eq!(o, OneOrMany::Many(vec![1, 2, 3]));
369
370 let o: OneOrMany<i64> = [].into_iter().collect();
371 assert_eq!(o, OneOrMany::Many(vec![]));
372 }
373
374 #[test]
375 fn test_display() {
376 let val = 34;
377 let v = OneOrMany::One(val);
378 assert_eq!(v.to_string(), "34");
379
380 let val = vec![1, 2, 3];
381 let v = OneOrMany::Many(val);
382 assert_eq!(v.to_string(), "1, 2, 3");
383 }
384}