one_or_many/
iter.rs

1use crate::OneOrMany;
2
3impl<T: ToOwned<Owned = T>> FromIterator<T> for OneOrMany<T> {
4    #[inline]
5    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
6        let mut result: Self = Self::None;
7        result.extend(iter);
8        result
9    }
10}
11
12#[allow(clippy::module_name_repetitions)]
13pub struct Iter<'a, T> {
14    inner: &'a OneOrMany<T>,
15    index: usize,
16}
17
18impl<T> OneOrMany<T> {
19    /// Returns an iterator over the values in the `OneOrMany`.
20    #[inline]
21    #[must_use]
22    pub const fn iter(&self) -> Iter<'_, T> {
23        Iter {
24            inner: self,
25            index: 0,
26        }
27    }
28}
29
30impl<'a, T> IntoIterator for &'a OneOrMany<T> {
31    type IntoIter = Iter<'a, T>;
32    type Item = &'a T;
33
34    #[inline]
35    fn into_iter(self) -> Self::IntoIter {
36        self.iter()
37    }
38}
39
40impl<'a, T> Iterator for Iter<'a, T> {
41    type Item = &'a T;
42
43    #[inline]
44    fn next(&mut self) -> Option<Self::Item> {
45        let result = self.inner.get(self.index);
46        self.index += 1;
47        result
48    }
49}
50
51/// A consuming iterator over the values in a `OneOrMany`.
52///
53/// This is really just a wrapper around other iterators.
54///
55/// TODO: find a better way to do this
56#[allow(clippy::module_name_repetitions)]
57pub struct IntoIter<T> {
58    inner_iter: InnerIntoIter<T>,
59}
60
61enum InnerIntoIter<T> {
62    One(Option<T>),
63    Many(std::vec::IntoIter<T>),
64    None,
65}
66
67impl<T> IntoIterator for OneOrMany<T> {
68    type IntoIter = IntoIter<T>;
69    type Item = T;
70
71    #[inline]
72    fn into_iter(self) -> Self::IntoIter {
73        let inner_iter = match self {
74            Self::One(t) => InnerIntoIter::One(Some(*t)),
75            Self::Many(v) => InnerIntoIter::Many(v.into_iter()),
76            Self::None => InnerIntoIter::None,
77        };
78
79        IntoIter { inner_iter }
80    }
81}
82
83impl<T> Iterator for IntoIter<T> {
84    type Item = T;
85
86    #[inline]
87    fn next(&mut self) -> Option<Self::Item> {
88        match self.inner_iter {
89            InnerIntoIter::One(ref mut t) => t.take(),
90            InnerIntoIter::Many(ref mut v) => v.next(),
91            InnerIntoIter::None => None,
92        }
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use crate::OneOrMany;
99    use pretty_assertions::assert_eq;
100    use rstest::rstest;
101
102    #[rstest]
103    #[case::none(Vec::<usize>::new().into_iter(), OneOrMany::<usize>::None)]
104    #[case::one(vec![1].into_iter(), OneOrMany::from(1))]
105    #[case::many(vec![1,2,3].into_iter(), OneOrMany::Many(vec![1,2,3]))]
106    fn test_from_iter<T, I>(#[case] input: I, #[case] expected: OneOrMany<T>)
107    where
108        T: std::fmt::Debug + Clone + std::cmp::PartialEq,
109        I: Iterator<Item = T>,
110    {
111        let collected = input.collect::<OneOrMany<_>>();
112        assert_eq!(collected, expected);
113    }
114
115    #[rstest]
116    #[case::none(OneOrMany::<usize>::None, vec![None])]
117    #[case::one(OneOrMany::from(1), vec![Some(1), None])]
118    #[case::many(OneOrMany::Many(vec![1, 2, 3]), vec![Some(1), Some(2), Some(3), None])]
119    fn test_iter<T>(#[case] input: OneOrMany<T>, #[case] expected: Vec<Option<T>>)
120    where
121        T: std::fmt::Debug + Clone + std::cmp::PartialEq,
122    {
123        let mut iter = input.iter();
124
125        for item in expected {
126            let next = iter.next();
127            assert_eq!(next, item.as_ref());
128        }
129    }
130
131    #[rstest]
132    #[case::none(OneOrMany::<usize>::None, vec![None])]
133    #[case::one(OneOrMany::from(1), vec![Some(1), None])]
134    #[case::many(OneOrMany::Many(vec![1, 2, 3]), vec![Some(1), Some(2), Some(3), None])]
135    fn test_into_iter_byval<T>(#[case] input: OneOrMany<T>, #[case] expected: Vec<Option<T>>)
136    where
137        T: std::fmt::Debug + Clone + std::cmp::PartialEq,
138    {
139        let mut iter = input.into_iter();
140
141        for item in expected {
142            let next = iter.next();
143            assert_eq!(next, item);
144        }
145    }
146
147    #[rstest]
148    #[case::none(OneOrMany::<usize>::None)]
149    #[case::one(OneOrMany::from(1))]
150    #[case::many(OneOrMany::Many(vec![1, 2, 3]))]
151    fn test_for_loop<T>(#[case] input: OneOrMany<T>)
152    where
153        T: std::fmt::Debug + Clone + std::cmp::PartialEq,
154    {
155        // non-consuming
156        let mut iter = input.iter();
157        for item in &input {
158            assert_eq!(iter.next(), Some(item));
159        }
160        assert_eq!(iter.next(), None);
161
162        // consuming
163        let mut iter = input.clone().into_iter();
164        for item in input {
165            assert_eq!(iter.next(), Some(item));
166        }
167        assert_eq!(iter.next(), None);
168    }
169}