assembler/
collections.rs

1//! Containers, including [`OneOrMore`].
2use std::error::Error;
3use std::fmt::{Display, Formatter};
4
5/// Indicates  failure  of  an  attempt   to  create  an  instance  of
6/// `OneOrMore<T>` when there are zero items to construct it from.
7#[derive(Debug, PartialEq, Eq, Clone)]
8pub struct NoItems {}
9
10impl Display for NoItems {
11    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
12        f.write_str("cannot create an instance of OneOrMore from zero items")
13    }
14}
15
16impl Error for NoItems {}
17
18/// A container for at least one item.  As a convenience, we don't
19/// implement methods that reduce the length of the container (so
20/// that, for example, we don't have to implement a fallible
21/// equivalent of `pop()`).  However, the container is mutable in the
22/// sense that the items stored in it can be mutated.
23#[derive(Debug, PartialEq, Eq, Clone)]
24pub struct OneOrMore<T> {
25    head: T,
26    tail: Vec<T>,
27}
28
29impl<T> OneOrMore<T> {
30    /// Create an instance of `OneOrMore<T>` from a single `T`.
31    pub fn new(head: T) -> OneOrMore<T> {
32        OneOrMore::with_tail(head, Vec::new())
33    }
34
35    /// Create an instance of `OneOrMore<T>` from a single `T` value
36    /// and zero or more additional `T` values.
37    pub fn with_tail(head: T, tail: Vec<T>) -> OneOrMore<T> {
38        OneOrMore { head, tail }
39    }
40
41    /// Return a reference to the first item.
42    pub fn first(&self) -> &T {
43        &self.head
44    }
45
46    /// Return a reference to the last item.
47    pub fn last(&self) -> &T {
48        match self.tail.last() {
49            Some(b) => b,
50            None => &self.head,
51        }
52    }
53
54    /// Append an item.
55    pub fn push(&mut self, item: T) {
56        self.tail.push(item);
57    }
58
59    /// Return an iterator for the collection.
60    pub fn iter(&self) -> OneOrMoreIter<'_, T> {
61        OneOrMoreIter {
62            inner: std::iter::once(&self.head).chain(self.tail.iter()),
63        }
64    }
65
66    /// Convert the collection into an iterator over the items of the
67    /// collection.
68    pub fn into_iter(self) -> OneOrMoreIntoIter<T> {
69        let Self { head, tail } = self;
70        OneOrMoreIntoIter {
71            inner: std::iter::once(head).chain(tail),
72        }
73    }
74
75    /// Return a iterator for the collection which allows the items
76    /// within it (but not the number of items) to be modified.
77    pub fn iter_mut(&mut self) -> OneOrMoreIterMut<'_, T> {
78        OneOrMoreIterMut {
79            inner: std::iter::once(&mut self.head).chain(self.tail.iter_mut()),
80        }
81    }
82
83    /// Return the number of items in the collection.
84    pub fn len(&self) -> usize {
85        self.tail.len() + 1
86    }
87
88    /// Build an instance of `OneOrMore<T>` from a sequence of items,
89    /// or fail (because there were no items).
90    pub fn try_from_iter<I: Iterator<Item = T>>(mut it: I) -> Result<Self, NoItems> {
91        match it.next() {
92            Some(head) => Ok(Self {
93                head,
94                tail: it.collect(),
95            }),
96            _ => Err(NoItems {}),
97        }
98    }
99
100    /// Append a (possibly empty) sequence of items.
101    pub fn extend<I: Iterator<Item = T>>(&mut self, items: I) {
102        self.tail.extend(items);
103    }
104
105    /// Attempt to convert an instance of `OneOrMore<T>` from a
106    /// `Vec<T>`.  This fails if the vector is empty.
107    pub fn try_from_vec(mut value: Vec<T>) -> Result<OneOrMore<T>, NoItems> {
108        if value.is_empty() {
109            Err(NoItems {})
110        } else {
111            let tail = value.split_off(1);
112            Ok(OneOrMore::with_tail(
113                value.pop().expect("known to be non-empty"),
114                tail,
115            ))
116        }
117    }
118
119    /// Return a reference the head of the collection (i.e. the first
120    /// item) and a reference to the remaining items.
121    pub fn as_parts(&self) -> (&T, &Vec<T>) {
122        (&self.head, &self.tail)
123    }
124
125    /// Create a non-empty collection by computing a mapping on the
126    /// items on this collection.
127    pub fn map<U, F: FnMut(&T) -> U>(&self, mut f: F) -> OneOrMore<U> {
128        OneOrMore {
129            head: f(&self.head),
130            tail: self.tail.iter().map(f).collect(),
131        }
132    }
133
134    /// Create a non-empty collection by computing a mapping on the
135    /// items on this collection; this collection is dropped.
136    pub fn into_map<U, F: FnMut(T) -> U>(self, mut f: F) -> OneOrMore<U> {
137        OneOrMore {
138            head: f(self.head),
139            tail: self.tail.into_iter().map(f).collect(),
140        }
141    }
142}
143
144pub struct OneOrMoreIter<'a, T> {
145    inner: std::iter::Chain<std::iter::Once<&'a T>, std::slice::Iter<'a, T>>,
146}
147
148impl<'a, T> Iterator for OneOrMoreIter<'a, T> {
149    type Item = &'a T;
150
151    fn next(&mut self) -> Option<Self::Item> {
152        self.inner.next()
153    }
154}
155
156pub struct OneOrMoreIntoIter<T> {
157    inner: std::iter::Chain<std::iter::Once<T>, <Vec<T> as IntoIterator>::IntoIter>,
158}
159
160impl<T> Iterator for OneOrMoreIntoIter<T> {
161    type Item = T;
162
163    fn next(&mut self) -> Option<Self::Item> {
164        self.inner.next()
165    }
166}
167
168pub struct OneOrMoreIterMut<'a, T> {
169    inner: std::iter::Chain<std::iter::Once<&'a mut T>, std::slice::IterMut<'a, T>>,
170}
171
172impl<'a, T> Iterator for OneOrMoreIterMut<'a, T> {
173    type Item = &'a mut T;
174
175    fn next(&mut self) -> Option<Self::Item> {
176        self.inner.next()
177    }
178}
179
180impl<T> From<OneOrMore<T>> for Vec<T> {
181    fn from(mut value: OneOrMore<T>) -> Self {
182        let mut result = Vec::with_capacity(value.len());
183        result.push(value.head);
184        result.append(&mut value.tail);
185        result
186    }
187}
188
189impl<T: PartialEq<T>> PartialEq<Vec<T>> for OneOrMore<T> {
190    fn eq(&self, other: &Vec<T>) -> bool {
191        let mut other_it = other.iter();
192        match other_it.next() {
193            Some(first) => {
194                if first != &self.head {
195                    return false;
196                }
197                let mut self_it = self.tail.iter();
198                // We don't want to use zip() here because we want our
199                // comparison to fail when one iterator is shorter
200                // than the other.
201                loop {
202                    match (self_it.next(), other_it.next()) {
203                        (Some(mine), Some(theirs)) => {
204                            if mine != theirs {
205                                return false;
206                            }
207                        }
208                        (None, Some(_)) | (Some(_), None) => {
209                            return false;
210                        }
211                        (None, None) => {
212                            return true;
213                        }
214                    }
215                }
216            }
217            None => false,
218        }
219    }
220}
221
222#[cfg(test)]
223mod one_or_more_tests {
224    use super::{NoItems, OneOrMore};
225
226    #[test]
227    fn test_first() {
228        let mut v: OneOrMore<u32> = OneOrMore::new(12);
229        assert_eq!(v.first(), &12);
230        v.push(8);
231        assert_eq!(v.first(), &12);
232    }
233
234    #[test]
235    fn test_last() {
236        let v: OneOrMore<u32> = OneOrMore::new(200);
237        assert_eq!(v.last(), &200);
238    }
239
240    #[test]
241    fn test_push() {
242        let mut v: OneOrMore<u32> = OneOrMore::new(1);
243        assert_eq!(v.last(), &1);
244        v.push(2);
245        assert_eq!(v.last(), &2);
246    }
247
248    #[test]
249    fn test_iter() {
250        let mut v: OneOrMore<u32> = OneOrMore::new(1);
251        v.push(2);
252        let mut it = v.iter();
253        assert_eq!(it.next(), Some(&1));
254        assert_eq!(it.next(), Some(&2));
255        assert_eq!(it.next(), None);
256    }
257
258    #[test]
259    fn test_into_iter() {
260        let mut v: OneOrMore<i32> = OneOrMore::new(-1);
261        v.push(-2);
262        let mut it = v.into_iter();
263        assert_eq!(it.next(), Some(-1));
264        assert_eq!(it.next(), Some(-2));
265        assert_eq!(it.next(), None);
266    }
267
268    #[test]
269    fn test_len() {
270        let mut v: OneOrMore<u32> = OneOrMore::new(0);
271        assert_eq!(v.len(), 1);
272        v.push(0);
273        assert_eq!(v.len(), 2);
274    }
275
276    #[test]
277    fn test_try_from_iter_nonempty() {
278        let input = [4];
279        assert_eq!(
280            OneOrMore::try_from_iter(input.iter()),
281            Ok(OneOrMore {
282                head: &4,
283                tail: Vec::new()
284            })
285        );
286
287        let input = [4, 8];
288        assert_eq!(
289            OneOrMore::try_from_iter(input.iter()),
290            Ok(OneOrMore {
291                head: &4,
292                tail: vec![&8]
293            })
294        );
295    }
296
297    #[test]
298    fn test_try_from_iter_empty() {
299        let input: Vec<u8> = Vec::new();
300        if let Ok(unexpected) = OneOrMore::try_from_iter(input.iter()) {
301            panic!(
302                "collecting from an empty iterator should fail, but instead we got {unexpected:?}"
303            );
304        }
305    }
306
307    #[test]
308    fn test_iter_mut() {
309        let mut v: OneOrMore<i32> = OneOrMore::try_from_iter([1, 2, 3, 4].into_iter())
310            .expect("collection from non-empty sequence should succeed");
311        for item in v.iter_mut() {
312            *item = item.saturating_add(1);
313        }
314        let values: Vec<i32> = v.into_iter().collect();
315        assert_eq!(values, vec![2, 3, 4, 5]);
316    }
317
318    #[test]
319    fn test_extend() {
320        let mut v: OneOrMore<i32> = OneOrMore::new(1);
321        v.extend([2, 3].into_iter());
322        assert_eq!(v, vec![1, 2, 3]);
323    }
324
325    #[test]
326    fn test_self_eq() {
327        assert_eq!(OneOrMore::new(1), OneOrMore::new(1));
328        assert_ne!(OneOrMore::new(1), OneOrMore::new(2));
329
330        assert_eq!(
331            OneOrMore::with_tail(1, vec![2]),
332            OneOrMore::with_tail(1, vec![2])
333        );
334        assert_ne!(
335            OneOrMore::with_tail(1, vec![2]),
336            OneOrMore::with_tail(1, vec![2, 2])
337        );
338        assert_ne!(
339            OneOrMore::with_tail(1, vec![2, 2]),
340            OneOrMore::with_tail(1, vec![2])
341        );
342    }
343
344    #[test]
345    fn test_from_vec_to_option() {
346        assert_eq!(Err(NoItems {}), OneOrMore::try_from_vec(Vec::<u64>::new()));
347        assert_eq!(Ok(OneOrMore::new(2)), OneOrMore::try_from_vec(vec![2]));
348        assert_eq!(
349            Ok(OneOrMore::with_tail(10, vec![20])),
350            OneOrMore::try_from_vec(vec![10, 20])
351        );
352    }
353
354    #[test]
355    fn test_map() {
356        assert_eq!(
357            OneOrMore::with_tail(1, vec![2]).map(|x| -x),
358            OneOrMore::with_tail(-1, vec![-2])
359        );
360    }
361
362    #[test]
363    fn test_into_map() {
364        assert_eq!(
365            OneOrMore::with_tail(1, vec![2]).into_map(|x| -x),
366            OneOrMore::with_tail(-1, vec![-2])
367        );
368    }
369}