Skip to main content

at_collection/
lib.rs

1use failure::bail;
2use failure::format_err;
3use failure::Error;
4use std::convert::TryFrom;
5use std::ops::Deref;
6
7pub trait AtCollection<T>
8where
9    Self: Sized,
10{
11    fn as_slice(&self) -> &[T];
12
13    fn as_vec(self) -> Vec<T>;
14
15    fn into_iter(self) -> std::vec::IntoIter<T> {
16        self.as_vec().into_iter()
17    }
18
19    fn iter(&self) -> std::slice::Iter<T> {
20        self.as_slice().iter()
21    }
22}
23
24macro_rules! atleast {
25    ($name:ident, $n:literal, $($cons:ident),*) => {
26
27        #[derive(Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
28        pub struct $name<T> {
29            raw: Vec<T>,
30        }
31
32        impl<T> $name<T> {
33            pub fn new(
34                $($cons: T),*
35            ) -> $name<T> {
36                $name::new_and($($cons),*, Vec::new())
37            }
38
39            pub fn new_and($($cons: T),*, mut v: Vec<T>) -> $name<T> {
40                let mut raw = vec![$($cons),*];
41                raw.append(&mut v);
42                $name { raw }
43            }
44        }
45
46        impl<T> AtCollection<T> for $name<T> {
47            fn as_slice(&self) -> &[T] {
48                self.raw.as_slice()
49            }
50
51            fn as_vec(self) -> Vec<T> {
52                self.raw
53            }
54        }
55        impl<T> Deref for $name<T> {
56            type Target = [T];
57
58            fn deref(&self) -> &Self::Target {
59                &self.as_slice()
60            }
61        }
62
63        impl<T> TryFrom<Vec<T>> for $name<T> {
64            type Error = Error;
65
66            fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
67                if value.len() < $n {
68                    bail!("{} requires at least {} values", stringify!($name), stringify!($n))
69                } else {
70                    Ok($name { raw: value })
71                }
72            }
73        }
74
75    };
76}
77
78atleast! {AtLeastOne, 1, a}
79atleast! {AtLeastTwo, 2, a, b}
80atleast! {AtLeastThree, 3, a, b, c}
81atleast! {AtLeastFour, 4, a, b, c, d}
82
83impl<T> AtLeastOne<T> {
84    pub fn one(&self) -> Result<&T, Error> {
85        match self.raw.len() {
86            1 => Ok(&self.raw[0]),
87            _ => Err(format_err!("AtLeastOne has more than one element")),
88        }
89    }
90
91    pub fn to_one(&self) -> &T {
92        self.one().unwrap()
93    }
94}
95
96#[macro_export]
97macro_rules! atl1 {
98    ($($cons:expr),*) => {
99        AtLeastOne::try_from(vec![$($cons),*])
100    }
101}
102
103#[macro_export]
104macro_rules! atl2 {
105    ($($cons:expr),*) => {
106        $crate::AtLeastTwo::try_from(vec![$($cons),*])
107    }
108}
109
110#[macro_export]
111macro_rules! atl3 {
112    ($($cons:expr),*) => {
113        AtLeastThree::try_from(vec![$($cons),*])
114    }
115}
116
117#[macro_export]
118macro_rules! atl4 {
119    ($($cons:expr),*) => {
120        AtLeastFour::try_from(vec![$($cons),*])
121    }
122}
123
124pub struct AtMostOne<T> {
125    raw: Vec<T>,
126}
127
128impl<T> AtMostOne<T> {
129    pub fn new(a: T) -> AtMostOne<T> {
130        let raw = vec![a];
131        AtMostOne { raw }
132    }
133}
134
135impl<T> AtCollection<T> for AtMostOne<T> {
136    fn as_slice(&self) -> &[T] {
137        self.raw.as_slice()
138    }
139
140    fn as_vec(self) -> Vec<T> {
141        self.raw
142    }
143}
144
145pub struct AtMostTwo<T> {
146    raw: Vec<T>,
147}
148
149impl<T> AtMostTwo<T> {
150    pub fn new(a: T) -> AtMostTwo<T> {
151        let raw = vec![a];
152        AtMostTwo { raw }
153    }
154}
155
156impl<T> AtCollection<T> for AtMostTwo<T> {
157    fn as_slice(&self) -> &[T] {
158        self.raw.as_slice()
159    }
160
161    fn as_vec(self) -> Vec<T> {
162        self.raw
163    }
164}
165
166pub struct AtMostThree<T> {
167    raw: Vec<T>,
168}
169
170impl<T> AtMostThree<T> {
171    pub fn new(a: T) -> AtMostThree<T> {
172        let raw = vec![a];
173        AtMostThree { raw }
174    }
175}
176
177impl<T> AtCollection<T> for AtMostThree<T> {
178    fn as_slice(&self) -> &[T] {
179        self.raw.as_slice()
180    }
181
182    fn as_vec(self) -> Vec<T> {
183        self.raw
184    }
185}
186
187#[cfg(test)]
188mod tests {
189    use super::*;
190
191    #[test]
192    fn iter() {
193        let alt = AtLeastTwo::new(1, 2);
194
195        let mut i = alt.iter();
196        assert_eq!(i.next(), Some(&1));
197        assert_eq!(i.next(), Some(&2));
198    }
199
200    #[test]
201    fn into_iter() {
202        let alt = AtLeastTwo::new(1, 2);
203
204        let mut i = alt.into_iter();
205        assert_eq!(i.next(), Some(1));
206        assert_eq!(i.next(), Some(2));
207    }
208
209    #[test]
210    fn for_iter() {
211        let alt = AtLeastOne::new(1);
212
213        for i in alt.into_iter() {
214            assert_eq!(i, 1);
215        }
216    }
217
218    #[test]
219    fn length() {
220        let alt = AtLeastTwo::new(1, 2);
221
222        assert_eq!(alt.len(), 2);
223    }
224
225    #[test]
226    fn try_from() {
227        assert!(AtLeastThree::try_from(vec![1, 2, 3]).is_ok());
228        assert!(AtLeastThree::try_from(vec![1, 2]).is_err());
229
230        assert!(AtLeastTwo::try_from(vec![1, 2, 3]).is_ok());
231        assert!(AtLeastTwo::try_from(vec![1]).is_err());
232    }
233
234    #[test]
235    fn at_least_one_macro() {
236        let atl1 = atl1![1].unwrap();
237        assert_eq!(1, atl1.len());
238
239        let atl1 = atl1![1, 2, 3].unwrap();
240        assert_eq!(3, atl1.len());
241    }
242
243    #[test]
244    fn at_least_two_macro() {
245        let atl2 = atl2![1];
246        assert!(atl2.is_err());
247    }
248
249    #[test]
250    fn at_least_two_expr() {
251        let atl2 = atl2![1 + 2, 3 + 4];
252        assert_eq!(atl2.unwrap().len(), 2);
253    }
254
255    #[test]
256    fn to_one() {
257        let ato1 = atl1![1].unwrap();
258        let ato2 = atl1![1, 2].unwrap();
259
260        assert!(ato1.one().is_ok());
261        assert!(ato2.one().is_err());
262
263        assert_eq!(ato1.to_one(), &1);
264    }
265}