bep/
one_or_many.rs

1/// Struct containing either a single item or a list of items of type T.
2/// If a single item is present, `first` will contain it and `rest` will be empty.
3/// If multiple items are present, `first` will contain the first item and `rest` will contain the rest.
4/// IMPORTANT: this struct cannot be created with an empty vector.
5/// OneOrMany objects can only be created using OneOrMany::from() or OneOrMany::try_from().
6#[derive(PartialEq, Eq, Debug, Clone)]
7pub struct OneOrMany<T> {
8    /// First item in the list.
9    first: T,
10    /// Rest of the items in the list.
11    rest: Vec<T>,
12}
13
14/// Error type for when trying to create a OneOrMany object with an empty vector.
15#[derive(Debug, thiserror::Error)]
16#[error("Cannot create OneOrMany with an empty vector.")]
17pub struct EmptyListError;
18
19impl<T: Clone> OneOrMany<T> {
20    /// Get the first item in the list.
21    pub fn first(&self) -> T {
22        self.first.clone()
23    }
24
25    /// Get the rest of the items in the list (excluding the first one).
26    pub fn rest(&self) -> Vec<T> {
27        self.rest.clone()
28    }
29
30    /// After `OneOrMany<T>` is created, add an item of type T to the `rest`.
31    pub fn push(&mut self, item: T) {
32        self.rest.push(item);
33    }
34
35    /// Length of all items in `OneOrMany<T>`.
36    pub fn len(&self) -> usize {
37        1 + self.rest.len()
38    }
39
40    /// If `OneOrMany<T>` is empty. This will always be false because you cannot create an empty `OneOrMany<T>`.
41    /// This method is required when the method `len` exists.
42    pub fn is_empty(&self) -> bool {
43        false
44    }
45
46    /// Create a OneOrMany object with a single item of any type.
47    pub fn one(item: T) -> Self {
48        OneOrMany {
49            first: item,
50            rest: vec![],
51        }
52    }
53
54    /// Create a OneOrMany object with a vector of items of any type.
55    pub fn many(items: Vec<T>) -> Result<Self, EmptyListError> {
56        let mut iter = items.into_iter();
57        Ok(OneOrMany {
58            first: match iter.next() {
59                Some(item) => item,
60                None => return Err(EmptyListError),
61            },
62            rest: iter.collect(),
63        })
64    }
65
66    /// Merge a list of OneOrMany items into a single OneOrMany item.
67    pub fn merge(one_or_many_items: Vec<OneOrMany<T>>) -> Result<Self, EmptyListError> {
68        let items = one_or_many_items
69            .into_iter()
70            .flat_map(|one_or_many| one_or_many.into_iter())
71            .collect::<Vec<_>>();
72
73        OneOrMany::many(items)
74    }
75
76    pub fn iter(&self) -> Iter<T> {
77        Iter {
78            first: Some(&self.first),
79            rest: self.rest.iter(),
80        }
81    }
82
83    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
84        IterMut {
85            first: Some(&mut self.first),
86            rest: self.rest.iter_mut(),
87        }
88    }
89}
90
91// ================================================================
92// Implementations of Iterator for OneOrMany
93//   - OneOrMany<T>::iter() -> iterate over references of T objects
94//   - OneOrMany<T>::into_iter() -> iterate over owned T objects
95//   - OneOrMany<T>::iter_mut() -> iterate over mutable references of T objects
96// ================================================================
97
98/// Struct returned by call to `OneOrMany::iter()`.
99pub struct Iter<'a, T> {
100    // References.
101    first: Option<&'a T>,
102    rest: std::slice::Iter<'a, T>,
103}
104
105/// Implement `Iterator` for `Iter<T>`.
106/// The Item type of the `Iterator` trait is a reference of `T`.
107impl<'a, T> Iterator for Iter<'a, T> {
108    type Item = &'a T;
109
110    fn next(&mut self) -> Option<Self::Item> {
111        if let Some(first) = self.first.take() {
112            Some(first)
113        } else {
114            self.rest.next()
115        }
116    }
117}
118
119/// Struct returned by call to `OneOrMany::into_iter()`.
120pub struct IntoIter<T> {
121    // Owned.
122    first: Option<T>,
123    rest: std::vec::IntoIter<T>,
124}
125
126/// Implement `Iterator` for `IntoIter<T>`.
127impl<T: Clone> IntoIterator for OneOrMany<T> {
128    type Item = T;
129    type IntoIter = IntoIter<T>;
130
131    fn into_iter(self) -> Self::IntoIter {
132        IntoIter {
133            first: Some(self.first),
134            rest: self.rest.into_iter(),
135        }
136    }
137}
138
139/// Implement `Iterator` for `IntoIter<T>`.
140/// The Item type of the `Iterator` trait is an owned `T`.
141impl<T: Clone> Iterator for IntoIter<T> {
142    type Item = T;
143
144    fn next(&mut self) -> Option<Self::Item> {
145        if let Some(first) = self.first.take() {
146            Some(first)
147        } else {
148            self.rest.next()
149        }
150    }
151}
152
153/// Struct returned by call to `OneOrMany::iter_mut()`.
154pub struct IterMut<'a, T> {
155    // Mutable references.
156    first: Option<&'a mut T>,
157    rest: std::slice::IterMut<'a, T>,
158}
159
160// Implement `Iterator` for `IterMut<T>`.
161// The Item type of the `Iterator` trait is a mutable reference of `OneOrMany<T>`.
162impl<'a, T> Iterator for IterMut<'a, T> {
163    type Item = &'a mut T;
164
165    fn next(&mut self) -> Option<Self::Item> {
166        if let Some(first) = self.first.take() {
167            Some(first)
168        } else {
169            self.rest.next()
170        }
171    }
172}
173
174#[cfg(test)]
175mod test {
176    use super::OneOrMany;
177
178    #[test]
179    fn test_single() {
180        let one_or_many = OneOrMany::one("hello".to_string());
181
182        assert_eq!(one_or_many.iter().count(), 1);
183
184        one_or_many.iter().for_each(|i| {
185            assert_eq!(i, "hello");
186        });
187    }
188
189    #[test]
190    fn test() {
191        let one_or_many = OneOrMany::many(vec!["hello".to_string(), "word".to_string()]).unwrap();
192
193        assert_eq!(one_or_many.iter().count(), 2);
194
195        one_or_many.iter().enumerate().for_each(|(i, item)| {
196            if i == 0 {
197                assert_eq!(item, "hello");
198            }
199            if i == 1 {
200                assert_eq!(item, "word");
201            }
202        });
203    }
204
205    #[test]
206    fn test_one_or_many_into_iter_single() {
207        let one_or_many = OneOrMany::one("hello".to_string());
208
209        assert_eq!(one_or_many.clone().into_iter().count(), 1);
210
211        one_or_many.into_iter().for_each(|i| {
212            assert_eq!(i, "hello".to_string());
213        });
214    }
215
216    #[test]
217    fn test_one_or_many_into_iter() {
218        let one_or_many = OneOrMany::many(vec!["hello".to_string(), "word".to_string()]).unwrap();
219
220        assert_eq!(one_or_many.clone().into_iter().count(), 2);
221
222        one_or_many.into_iter().enumerate().for_each(|(i, item)| {
223            if i == 0 {
224                assert_eq!(item, "hello".to_string());
225            }
226            if i == 1 {
227                assert_eq!(item, "word".to_string());
228            }
229        });
230    }
231
232    #[test]
233    fn test_one_or_many_merge() {
234        let one_or_many_1 = OneOrMany::many(vec!["hello".to_string(), "word".to_string()]).unwrap();
235
236        let one_or_many_2 = OneOrMany::one("sup".to_string());
237
238        let merged = OneOrMany::merge(vec![one_or_many_1, one_or_many_2]).unwrap();
239
240        assert_eq!(merged.iter().count(), 3);
241
242        merged.iter().enumerate().for_each(|(i, item)| {
243            if i == 0 {
244                assert_eq!(item, "hello");
245            }
246            if i == 1 {
247                assert_eq!(item, "word");
248            }
249            if i == 2 {
250                assert_eq!(item, "sup");
251            }
252        });
253    }
254
255    #[test]
256    fn test_mut_single() {
257        let mut one_or_many = OneOrMany::one("hello".to_string());
258
259        assert_eq!(one_or_many.iter_mut().count(), 1);
260
261        one_or_many.iter_mut().for_each(|i| {
262            assert_eq!(i, "hello");
263        });
264    }
265
266    #[test]
267    fn test_mut() {
268        let mut one_or_many =
269            OneOrMany::many(vec!["hello".to_string(), "word".to_string()]).unwrap();
270
271        assert_eq!(one_or_many.iter_mut().count(), 2);
272
273        one_or_many.iter_mut().enumerate().for_each(|(i, item)| {
274            if i == 0 {
275                item.push_str(" world");
276                assert_eq!(item, "hello world");
277            }
278            if i == 1 {
279                assert_eq!(item, "word");
280            }
281        });
282    }
283
284    #[test]
285    fn test_one_or_many_error() {
286        assert!(OneOrMany::<String>::many(vec![]).is_err())
287    }
288
289    #[test]
290    fn test_len_single() {
291        let one_or_many = OneOrMany::one("hello".to_string());
292
293        assert_eq!(one_or_many.len(), 1);
294    }
295
296    #[test]
297    fn test_len_many() {
298        let one_or_many = OneOrMany::many(vec!["hello".to_string(), "word".to_string()]).unwrap();
299
300        assert_eq!(one_or_many.len(), 2);
301    }
302}