circomspect_program_structure/utils/
nonempty_vec.rs

1use anyhow::{anyhow, Error};
2use std::convert::TryFrom;
3use std::ops::{Index, IndexMut};
4
5/// A vector type which is guaranteed to be non-empty.
6///
7/// New instances must be created with an initial element to ensure that the
8/// vector is non-empty. This means that the methods `first` and `last` always
9/// produce an element of type `T`.
10///
11/// ```
12/// # use circomspect_program_structure::nonempty_vec::NonEmptyVec;
13///
14/// let v = NonEmptyVec::new(1);
15/// assert_eq!(*v.first(), 1);
16/// assert_eq!(*v.last(), 1);
17/// ```
18///
19/// It is possible to `push` new elements into the vector, but `pop` will return
20/// `None` if there is only one element left to ensure that the vector is always
21/// nonempty.
22///
23/// ```
24/// # use circomspect_program_structure::nonempty_vec::NonEmptyVec;
25///
26/// let mut v = NonEmptyVec::new(1);
27/// v.push(2);
28/// assert_eq!(v.pop(), Some(2));
29/// assert_eq!(v.pop(), None);
30/// ```
31#[derive(Clone, PartialEq, Eq)]
32pub struct NonEmptyVec<T> {
33    head: T,
34    tail: Vec<T>,
35}
36
37impl<T> NonEmptyVec<T> {
38    pub fn new(x: T) -> NonEmptyVec<T> {
39        NonEmptyVec { head: x, tail: Vec::new() }
40    }
41
42    pub fn first(&self) -> &T {
43        &self.head
44    }
45
46    pub fn first_mut(&mut self) -> &mut T {
47        &mut self.head
48    }
49
50    /// Returns a reference to the last element.
51    pub fn last(&self) -> &T {
52        match self.tail.last() {
53            Some(x) => x,
54            None => &self.head,
55        }
56    }
57
58    /// Returns a mutable reference to the last element.
59    pub fn last_mut(&mut self) -> &mut T {
60        match self.tail.last_mut() {
61            Some(x) => x,
62            None => &mut self.head,
63        }
64    }
65
66    /// Append an element to the vector.
67    pub fn push(&mut self, x: T) {
68        self.tail.push(x);
69    }
70
71    /// Pops the last element of the vector.
72    ///
73    /// This method will return `None` when there is one element left in the
74    /// vector to ensure that the vector remains non-empty.
75    ///
76    /// ```
77    /// # use circomspect_program_structure::nonempty_vec::NonEmptyVec;
78    ///
79    /// let mut v = NonEmptyVec::new(1);
80    /// v.push(2);
81    /// assert_eq!(v.pop(), Some(2));
82    /// assert_eq!(v.pop(), None);
83    /// ```
84    pub fn pop(&mut self) -> Option<T> {
85        self.tail.pop()
86    }
87
88    /// Returns the length of the vector.
89    ///
90    /// ```
91    /// # use circomspect_program_structure::nonempty_vec::NonEmptyVec;
92    ///
93    /// let mut v = NonEmptyVec::new(1);
94    /// v.push(2);
95    /// v.push(3);
96    /// assert_eq!(v.len(), 3);
97    /// ```
98    pub fn len(&self) -> usize {
99        self.tail.len() + 1
100    }
101
102    /// Always returns false.
103    pub fn is_empty(&self) -> bool {
104        false
105    }
106
107    /// Returns an iterator over the vector.
108    pub fn iter(&self) -> NonEmptyIter<'_, T> {
109        NonEmptyIter::new(self)
110    }
111}
112
113/// Allows for constructions on the form `for t in ts`.
114impl<'a, T> IntoIterator for &'a NonEmptyVec<T> {
115    type Item = &'a T;
116    type IntoIter = NonEmptyIter<'a, T>;
117
118    fn into_iter(self) -> Self::IntoIter {
119        NonEmptyIter::new(self)
120    }
121}
122
123/// An iterator over a non-empty vector.
124///
125/// ```
126/// # use circomspect_program_structure::nonempty_vec::NonEmptyVec;
127/// # use std::convert::TryFrom;
128/// let v = NonEmptyVec::try_from(&[1, 2, 3]).unwrap();
129///
130/// let mut iter = v.iter();
131/// assert_eq!(iter.next(), Some(&1));
132/// assert_eq!(iter.next(), Some(&2));
133/// assert_eq!(iter.next(), Some(&3));
134/// assert_eq!(iter.next(), None);
135/// ```
136pub struct NonEmptyIter<'a, T> {
137    index: usize,
138    vec: &'a NonEmptyVec<T>,
139}
140
141impl<'a, T> NonEmptyIter<'a, T> {
142    fn new(vec: &'a NonEmptyVec<T>) -> NonEmptyIter<'a, T> {
143        NonEmptyIter { index: 0, vec }
144    }
145}
146
147impl<'a, T> Iterator for NonEmptyIter<'a, T> {
148    type Item = &'a T;
149
150    fn next(&mut self) -> Option<Self::Item> {
151        let x = if self.index == 0 {
152            Some(&self.vec.head)
153        } else {
154            // self.index > 0 here so the subtraction cannot underflow.
155            self.vec.tail.get(self.index - 1)
156        };
157        self.index += 1;
158        x
159    }
160}
161
162impl<T> Index<usize> for NonEmptyVec<T> {
163    type Output = T;
164
165    fn index(&self, index: usize) -> &Self::Output {
166        match index {
167            0 => &self.head,
168            n => &self.tail[n - 1],
169        }
170    }
171}
172
173impl<T> Index<&usize> for NonEmptyVec<T> {
174    type Output = T;
175
176    fn index(&self, index: &usize) -> &Self::Output {
177        match index {
178            0 => &self.head,
179            n => &self.tail[n - 1],
180        }
181    }
182}
183
184impl<T> IndexMut<usize> for NonEmptyVec<T> {
185    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
186        match index {
187            0 => &mut self.head,
188            n => &mut self.tail[n - 1],
189        }
190    }
191}
192
193impl<T> IndexMut<&usize> for NonEmptyVec<T> {
194    fn index_mut(&mut self, index: &usize) -> &mut Self::Output {
195        match index {
196            0 => &mut self.head,
197            n => &mut self.tail[n - 1],
198        }
199    }
200}
201
202impl<T> From<NonEmptyVec<T>> for Vec<T> {
203    fn from(xs: NonEmptyVec<T>) -> Vec<T> {
204        let mut res = Vec::with_capacity(xs.len());
205        res.push(xs.head);
206        res.extend(xs.tail);
207        res
208    }
209}
210
211impl<T: Clone> From<&NonEmptyVec<T>> for Vec<T> {
212    fn from(xs: &NonEmptyVec<T>) -> Vec<T> {
213        xs.iter().cloned().collect()
214    }
215}
216
217impl<T> TryFrom<Vec<T>> for NonEmptyVec<T> {
218    type Error = Error;
219
220    fn try_from(mut xs: Vec<T>) -> Result<NonEmptyVec<T>, Error> {
221        if let Some(x) = xs.pop() {
222            Ok(NonEmptyVec { head: x, tail: xs })
223        } else {
224            Err(anyhow!("cannot create a non-empty vector from an empty vector"))
225        }
226    }
227}
228
229impl<T: Clone> TryFrom<&Vec<T>> for NonEmptyVec<T> {
230    type Error = Error;
231
232    fn try_from(xs: &Vec<T>) -> Result<NonEmptyVec<T>, Error> {
233        if let Some(x) = xs.first() {
234            Ok(NonEmptyVec { head: x.clone(), tail: xs[1..].to_vec() })
235        } else {
236            Err(anyhow!("cannot create a non-empty vector from an empty vector"))
237        }
238    }
239}
240
241impl<T: Clone> TryFrom<&[T]> for NonEmptyVec<T> {
242    type Error = Error;
243
244    fn try_from(xs: &[T]) -> Result<NonEmptyVec<T>, Error> {
245        if let Some(x) = xs.first() {
246            Ok(NonEmptyVec { head: x.clone(), tail: xs[1..].to_vec() })
247        } else {
248            Err(anyhow!("cannot create a non-empty vector from an empty vector"))
249        }
250    }
251}
252
253impl<T: Clone, const N: usize> TryFrom<&[T; N]> for NonEmptyVec<T> {
254    type Error = Error;
255
256    fn try_from(xs: &[T; N]) -> Result<NonEmptyVec<T>, Error> {
257        if let Some(x) = xs.first() {
258            Ok(NonEmptyVec { head: x.clone(), tail: xs[1..].to_vec() })
259        } else {
260            Err(anyhow!("cannot create a non-empty vector from an empty vector"))
261        }
262    }
263}