]> git.proxmox.com Git - rustc.git/blob - src/libsyntax/util/small_vector.rs
Imported Upstream version 1.0.0~beta
[rustc.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::{IntoIterator, 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: IntoIterator<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: IntoIterator<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!(v, Vec::new());
230
231 let v = SmallVector::one(1);
232 assert_eq!(v.into_iter().collect::<Vec<_>>(), [1]);
233
234 let v = SmallVector::many(vec![1, 2, 3]);
235 assert_eq!(v.into_iter().collect::<Vec<_>>(), [1, 2, 3]);
236 }
237
238 #[test]
239 #[should_panic]
240 fn test_expect_one_zero() {
241 let _: isize = SmallVector::zero().expect_one("");
242 }
243
244 #[test]
245 #[should_panic]
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 }