Skip to main content

rustrade_integration/collection/
one_or_many.rs

1use crate::collection::none_one_or_many::NoneOneOrMany;
2use itertools::Either;
3use serde::{Deserialize, Serialize};
4use std::{
5    borrow::{Borrow, BorrowMut},
6    convert::AsRef,
7};
8
9#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
10pub enum OneOrMany<T> {
11    One(T),
12    Many(Vec<T>),
13}
14
15// Utility methods
16impl<T> OneOrMany<T> {
17    pub fn map<U, F>(self, f: F) -> OneOrMany<U>
18    where
19        F: Fn(T) -> U,
20    {
21        match self {
22            Self::One(x) => OneOrMany::One(f(x)),
23            Self::Many(vec) => OneOrMany::Many(vec.into_iter().map(f).collect()),
24        }
25    }
26
27    pub fn extend<Iter>(self, other: Iter) -> Self
28    where
29        Iter: IntoIterator<Item = T>,
30    {
31        let other = Self::from_iter(other);
32
33        use OneOrMany::*;
34        match (self, other) {
35            (One(left), One(right)) => Many(vec![left, right]),
36            (One(left), Many(mut right)) => {
37                right.push(left);
38                Many(right)
39            }
40            (Many(mut left), One(right)) => {
41                left.push(right);
42                Many(left)
43            }
44            (Many(mut left), Many(right)) => {
45                left.extend(right);
46                Many(left)
47            }
48        }
49    }
50
51    pub fn contains(&self, item: &T) -> bool
52    where
53        T: PartialEq,
54    {
55        match self {
56            Self::One(value) => value == item,
57            Self::Many(values) => values.contains(item),
58        }
59    }
60
61    #[allow(clippy::len_without_is_empty)]
62    pub fn len(&self) -> usize {
63        match self {
64            Self::One(_) => 1,
65            Self::Many(items) => items.len(),
66        }
67    }
68
69    pub fn is_one(&self) -> bool {
70        matches!(self, Self::One(_))
71    }
72
73    pub fn is_many(&self) -> bool {
74        matches!(self, Self::Many(_))
75    }
76
77    pub fn into_vec(self) -> Vec<T> {
78        match self {
79            Self::One(item) => vec![item],
80            Self::Many(items) => items,
81        }
82    }
83
84    pub fn iter(&self) -> std::slice::Iter<'_, T> {
85        self.as_ref().iter()
86    }
87}
88
89// Default implementation if T implements Default
90impl<T: Default> Default for OneOrMany<T> {
91    fn default() -> Self {
92        OneOrMany::One(T::default())
93    }
94}
95
96// AsRef implementation for slice access
97impl<T> AsRef<[T]> for OneOrMany<T> {
98    fn as_ref(&self) -> &[T] {
99        match self {
100            Self::One(item) => std::slice::from_ref(item),
101            Self::Many(items) => items.as_slice(),
102        }
103    }
104}
105
106// Borrow implementation for slice access
107impl<T> Borrow<[T]> for OneOrMany<T> {
108    fn borrow(&self) -> &[T] {
109        self.as_ref()
110    }
111}
112
113// BorrowMut implementation for mutable slice access
114impl<T> BorrowMut<[T]> for OneOrMany<T> {
115    fn borrow_mut(&mut self) -> &mut [T] {
116        match self {
117            Self::One(item) => std::slice::from_mut(item),
118            Self::Many(items) => items.as_mut_slice(),
119        }
120    }
121}
122
123// From implementations for various types
124impl<T> From<T> for OneOrMany<T> {
125    fn from(item: T) -> Self {
126        OneOrMany::One(item)
127    }
128}
129
130impl<T> From<Vec<T>> for OneOrMany<T> {
131    fn from(mut items: Vec<T>) -> Self {
132        match items.len() {
133            0 => panic!("Cannot create OneOrMany from empty Vec"),
134            1 => OneOrMany::One(items.remove(0)),
135            _ => OneOrMany::Many(items),
136        }
137    }
138}
139
140impl<T> From<NoneOneOrMany<T>> for Option<OneOrMany<T>> {
141    fn from(value: NoneOneOrMany<T>) -> Self {
142        match value {
143            NoneOneOrMany::None => None,
144            NoneOneOrMany::One(value) => Some(OneOrMany::One(value)),
145            NoneOneOrMany::Many(values) => Some(OneOrMany::Many(values)),
146        }
147    }
148}
149
150// FromIterator implementation
151impl<T> FromIterator<T> for OneOrMany<T> {
152    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
153        let mut collection = iter.into_iter().collect::<Vec<_>>();
154        match collection.len() {
155            1 => Self::One(collection.swap_remove(0)),
156            _ => Self::Many(collection),
157        }
158    }
159}
160
161// IntoIterator implementation
162impl<T> IntoIterator for OneOrMany<T> {
163    type Item = T;
164    type IntoIter = Either<std::iter::Once<T>, std::vec::IntoIter<T>>;
165
166    fn into_iter(self) -> Self::IntoIter {
167        match self {
168            OneOrMany::One(item) => Either::Left(std::iter::once(item)),
169            OneOrMany::Many(items) => Either::Right(items.into_iter()),
170        }
171    }
172}
173
174// IntoIterator implementation for references
175impl<'a, T> IntoIterator for &'a OneOrMany<T> {
176    type Item = &'a T;
177    type IntoIter = Either<std::iter::Once<&'a T>, std::slice::Iter<'a, T>>;
178
179    fn into_iter(self) -> Self::IntoIter {
180        match self {
181            OneOrMany::One(item) => Either::Left(std::iter::once(item)),
182            OneOrMany::Many(items) => Either::Right(items.iter()),
183        }
184    }
185}
186
187// IntoIterator implementation for mutable references
188impl<'a, T> IntoIterator for &'a mut OneOrMany<T> {
189    type Item = &'a mut T;
190    type IntoIter = Either<std::iter::Once<&'a mut T>, std::slice::IterMut<'a, T>>;
191
192    fn into_iter(self) -> Self::IntoIter {
193        match self {
194            OneOrMany::One(item) => Either::Left(std::iter::once(item)),
195            OneOrMany::Many(items) => Either::Right(items.iter_mut()),
196        }
197    }
198}