non_empty/
lib.rs

1#![feature(try_from, type_ascription)]
2
3use std::convert::TryFrom;
4
5/// Non-empty list data type.
6#[derive(Debug)]
7pub struct NonEmpty<T>(T, Vec<T>);
8
9impl<T: PartialEq> PartialEq for NonEmpty<T> {
10    /// Equality comparison.
11    fn eq(&self, other: &Self) -> bool {
12        self.0 == other.0 && self.1 == other.1
13    }
14}
15
16impl<T: Default> Default for NonEmpty<T> {
17    /// Default value.
18    fn default() -> Self {
19        NonEmpty(T::default(), Vec::new())
20    }
21}
22
23impl<T> Into<Vec<T>> for NonEmpty<T> {
24    /// Turns a non-empty list into a Vec.
25    fn into(mut self) -> Vec<T> {
26        let mut t = vec![self.0]; 
27        t.append(&mut self.1);
28        t
29    }
30}
31
32/// Error arisen when given an empty vector.
33#[derive(Debug, PartialEq)]
34pub struct EmptyVecError;
35
36impl<T> TryFrom<Vec<T>> for NonEmpty<T> {
37    type Error = EmptyVecError;
38
39    /// Turns a vec into a non-empty list.
40    fn try_from(v: Vec<T>) -> Result<NonEmpty<T>, EmptyVecError> {
41        if v.is_empty() {
42            Err(EmptyVecError)
43        } else {
44            let mut it = v.into_iter();
45            if let Some(n) = it.next() {
46                Ok(NonEmpty(n, it.collect::<Vec<T>>()))
47            } else {
48                Err(EmptyVecError)
49            }
50        }
51    }
52}
53
54#[cfg(test)]
55mod test {
56    use NonEmpty;
57    use EmptyVecError;
58    use std::convert::TryFrom;
59
60    #[test]
61    fn i() {
62        let i1 = NonEmpty(1, vec![2, 3]);
63        assert_eq!(i1.into(): Vec<i32>, vec![1, 2, 3]);
64    }
65
66    #[test]
67    fn f() {
68        let f1 = vec![1, 2, 3];
69        assert_eq!(NonEmpty::try_from(f1), Ok(NonEmpty(1, vec![2, 3])));
70
71        let f2: Vec<i32> = vec![];
72        assert_eq!(NonEmpty::try_from(f2), Err(EmptyVecError))
73    }
74}