]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/util/small_vector.rs
Auto merge of #22517 - brson:relnotes, r=Gankro
[rust.git] / src / libsyntax / util / small_vector.rs
1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use self::SmallVectorRepr::*;
12 use self::IntoIterRepr::*;
13
14 use std::iter::FromIterator;
15 use std::mem;
16 use std::slice;
17 use std::vec;
18
19 use fold::MoveMap;
20
21 /// A vector type optimized for cases where the size is almost always 0 or 1
22 pub struct SmallVector<T> {
23     repr: SmallVectorRepr<T>,
24 }
25
26 enum SmallVectorRepr<T> {
27     Zero,
28     One(T),
29     Many(Vec<T>),
30 }
31
32 impl<T> FromIterator<T> for SmallVector<T> {
33     fn from_iter<I: Iterator<Item=T>>(iter: I) -> SmallVector<T> {
34         let mut v = SmallVector::zero();
35         v.extend(iter);
36         v
37     }
38 }
39
40 impl<T> Extend<T> for SmallVector<T> {
41     fn extend<I: Iterator<Item=T>>(&mut self, iter: I) {
42         for val in iter {
43             self.push(val);
44         }
45     }
46 }
47
48 impl<T> SmallVector<T> {
49     pub fn zero() -> SmallVector<T> {
50         SmallVector { repr: Zero }
51     }
52
53     pub fn one(v: T) -> SmallVector<T> {
54         SmallVector { repr: One(v) }
55     }
56
57     pub fn many(vs: Vec<T>) -> SmallVector<T> {
58         SmallVector { repr: Many(vs) }
59     }
60
61     pub fn as_slice<'a>(&'a self) -> &'a [T] {
62         match self.repr {
63             Zero => {
64                 let result: &[T] = &[];
65                 result
66             }
67             One(ref v) => slice::ref_slice(v),
68             Many(ref vs) => vs
69         }
70     }
71
72     pub fn push(&mut self, v: T) {
73         match self.repr {
74             Zero => self.repr = One(v),
75             One(..) => {
76                 let one = mem::replace(&mut self.repr, Zero);
77                 match one {
78                     One(v1) => mem::replace(&mut self.repr, Many(vec!(v1, v))),
79                     _ => unreachable!()
80                 };
81             }
82             Many(ref mut vs) => vs.push(v)
83         }
84     }
85
86     pub fn push_all(&mut self, other: SmallVector<T>) {
87         for v in other.into_iter() {
88             self.push(v);
89         }
90     }
91
92     pub fn get<'a>(&'a self, idx: usize) -> &'a T {
93         match self.repr {
94             One(ref v) if idx == 0 => v,
95             Many(ref vs) => &vs[idx],
96             _ => panic!("out of bounds access")
97         }
98     }
99
100     pub fn expect_one(self, err: &'static str) -> T {
101         match self.repr {
102             One(v) => v,
103             Many(v) => {
104                 if v.len() == 1 {
105                     v.into_iter().next().unwrap()
106                 } else {
107                     panic!(err)
108                 }
109             }
110             _ => panic!(err)
111         }
112     }
113
114     /// Deprecated: use `into_iter`.
115     #[unstable(feature = "rustc_private")]
116     #[deprecated(since = "1.0.0", reason = "use into_iter")]
117     pub fn move_iter(self) -> IntoIter<T> {
118         self.into_iter()
119     }
120
121     pub fn into_iter(self) -> IntoIter<T> {
122         let repr = match self.repr {
123             Zero => ZeroIterator,
124             One(v) => OneIterator(v),
125             Many(vs) => ManyIterator(vs.into_iter())
126         };
127         IntoIter { repr: repr }
128     }
129
130     pub fn len(&self) -> usize {
131         match self.repr {
132             Zero => 0,
133             One(..) => 1,
134             Many(ref vals) => vals.len()
135         }
136     }
137
138     pub fn is_empty(&self) -> bool { self.len() == 0 }
139 }
140
141 pub struct IntoIter<T> {
142     repr: IntoIterRepr<T>,
143 }
144
145 enum IntoIterRepr<T> {
146     ZeroIterator,
147     OneIterator(T),
148     ManyIterator(vec::IntoIter<T>),
149 }
150
151 impl<T> Iterator for IntoIter<T> {
152     type Item = T;
153
154     fn next(&mut self) -> Option<T> {
155         match self.repr {
156             ZeroIterator => None,
157             OneIterator(..) => {
158                 let mut replacement = ZeroIterator;
159                 mem::swap(&mut self.repr, &mut replacement);
160                 match replacement {
161                     OneIterator(v) => Some(v),
162                     _ => unreachable!()
163                 }
164             }
165             ManyIterator(ref mut inner) => inner.next()
166         }
167     }
168
169     fn size_hint(&self) -> (usize, Option<usize>) {
170         match self.repr {
171             ZeroIterator => (0, Some(0)),
172             OneIterator(..) => (1, Some(1)),
173             ManyIterator(ref inner) => inner.size_hint()
174         }
175     }
176 }
177
178 impl<T> MoveMap<T> for SmallVector<T> {
179     fn move_map<F>(self, mut f: F) -> SmallVector<T> where F: FnMut(T) -> T {
180         let repr = match self.repr {
181             Zero => Zero,
182             One(v) => One(f(v)),
183             Many(vs) => Many(vs.move_map(f))
184         };
185         SmallVector { repr: repr }
186     }
187 }
188
189 #[cfg(test)]
190 mod test {
191     use super::*;
192
193     #[test]
194     fn test_len() {
195         let v: SmallVector<isize> = SmallVector::zero();
196         assert_eq!(0, v.len());
197
198         assert_eq!(1, SmallVector::one(1).len());
199         assert_eq!(5, SmallVector::many(vec![1, 2, 3, 4, 5]).len());
200     }
201
202     #[test]
203     fn test_push_get() {
204         let mut v = SmallVector::zero();
205         v.push(1);
206         assert_eq!(1, v.len());
207         assert_eq!(&1, v.get(0));
208         v.push(2);
209         assert_eq!(2, v.len());
210         assert_eq!(&2, v.get(1));
211         v.push(3);
212         assert_eq!(3, v.len());
213         assert_eq!(&3, v.get(2));
214     }
215
216     #[test]
217     fn test_from_iter() {
218         let v: SmallVector<isize> = (vec![1, 2, 3]).into_iter().collect();
219         assert_eq!(3, v.len());
220         assert_eq!(&1, v.get(0));
221         assert_eq!(&2, v.get(1));
222         assert_eq!(&3, v.get(2));
223     }
224
225     #[test]
226     fn test_move_iter() {
227         let v = SmallVector::zero();
228         let v: Vec<isize> = v.into_iter().collect();
229         assert_eq!(Vec::new(), v);
230
231         let v = SmallVector::one(1);
232         assert_eq!(vec![1], v.into_iter().collect::<Vec<_>>());
233
234         let v = SmallVector::many(vec![1, 2, 3]);
235         assert_eq!(vec!(1, 2, 3), v.into_iter().collect::<Vec<_>>());
236     }
237
238     #[test]
239     #[should_fail]
240     fn test_expect_one_zero() {
241         let _: isize = SmallVector::zero().expect_one("");
242     }
243
244     #[test]
245     #[should_fail]
246     fn test_expect_one_many() {
247         SmallVector::many(vec!(1, 2)).expect_one("");
248     }
249
250     #[test]
251     fn test_expect_one_one() {
252         assert_eq!(1, SmallVector::one(1).expect_one(""));
253         assert_eq!(1, SmallVector::many(vec!(1)).expect_one(""));
254     }
255 }