Skip to content

Commit 09f84aa

Browse files
committed
Add SmallVector to libsyntax
1 parent e9a1869 commit 09f84aa

File tree

2 files changed

+214
-0
lines changed

2 files changed

+214
-0
lines changed

src/libsyntax/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub mod util {
3131
pub mod interner;
3232
#[cfg(test)]
3333
pub mod parser_testing;
34+
pub mod small_vector;
3435
}
3536

3637
pub mod syntax {

src/libsyntax/util/small_vector.rs

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
// Copyright 2013 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+
use std::vec::MoveIterator;
11+
use std::util;
12+
13+
/// A vector type optimized for cases where the size is almost always 0 or 1
14+
pub enum SmallVector<T> {
15+
priv Zero,
16+
priv One(T),
17+
priv Many(~[T]),
18+
}
19+
20+
impl<T> Container for SmallVector<T> {
21+
fn len(&self) -> uint {
22+
match *self {
23+
Zero => 0,
24+
One(*) => 1,
25+
Many(ref vals) => vals.len()
26+
}
27+
}
28+
}
29+
30+
impl<T> FromIterator<T> for SmallVector<T> {
31+
fn from_iterator<I: Iterator<T>>(iter: &mut I) -> SmallVector<T> {
32+
let mut v = Zero;
33+
for val in *iter {
34+
v.push(val);
35+
}
36+
v
37+
}
38+
}
39+
40+
impl<T> SmallVector<T> {
41+
pub fn zero() -> SmallVector<T> {
42+
Zero
43+
}
44+
45+
pub fn one(v: T) -> SmallVector<T> {
46+
One(v)
47+
}
48+
49+
pub fn many(vs: ~[T]) -> SmallVector<T> {
50+
Many(vs)
51+
}
52+
53+
pub fn push(&mut self, v: T) {
54+
match *self {
55+
Zero => *self = One(v),
56+
One(*) => {
57+
let mut tmp = Many(~[]);
58+
util::swap(self, &mut tmp);
59+
match *self {
60+
Many(ref mut vs) => {
61+
match tmp {
62+
One(v1) => {
63+
vs.push(v1);
64+
vs.push(v);
65+
}
66+
_ => unreachable!()
67+
}
68+
}
69+
_ => unreachable!()
70+
}
71+
}
72+
Many(ref mut vs) => vs.push(v)
73+
}
74+
}
75+
76+
pub fn get<'a>(&'a self, idx: uint) -> &'a T {
77+
match *self {
78+
One(ref v) if idx == 0 => v,
79+
Many(ref vs) => &vs[idx],
80+
_ => fail!("Out of bounds access")
81+
}
82+
}
83+
84+
pub fn iter<'a>(&'a self) -> SmallVectorIterator<'a, T> {
85+
SmallVectorIterator {
86+
vec: self,
87+
idx: 0
88+
}
89+
}
90+
91+
pub fn move_iter(self) -> SmallVectorMoveIterator<T> {
92+
match self {
93+
Zero => ZeroIterator,
94+
One(v) => OneIterator(v),
95+
Many(vs) => ManyIterator(vs.move_iter())
96+
}
97+
}
98+
}
99+
100+
pub struct SmallVectorIterator<'vec, T> {
101+
priv vec: &'vec SmallVector<T>,
102+
priv idx: uint
103+
}
104+
105+
impl<'vec, T> Iterator<&'vec T> for SmallVectorIterator<'vec, T> {
106+
fn next(&mut self) -> Option<&'vec T> {
107+
if self.idx == self.vec.len() {
108+
return None;
109+
}
110+
111+
self.idx += 1;
112+
Some(self.vec.get(self.idx - 1))
113+
}
114+
115+
fn size_hint(&self) -> (uint, Option<uint>) {
116+
let rem = self.vec.len() - self.idx;
117+
(rem, Some(rem))
118+
}
119+
}
120+
121+
pub enum SmallVectorMoveIterator<T> {
122+
priv ZeroIterator,
123+
priv OneIterator(T),
124+
priv ManyIterator(MoveIterator<T>),
125+
}
126+
127+
impl<T> Iterator<T> for SmallVectorMoveIterator<T> {
128+
fn next(&mut self) -> Option<T> {
129+
match *self {
130+
ZeroIterator => None,
131+
OneIterator(*) => {
132+
let mut replacement = ZeroIterator;
133+
util::swap(self, &mut replacement);
134+
match replacement {
135+
OneIterator(v) => Some(v),
136+
_ => unreachable!()
137+
}
138+
}
139+
ManyIterator(ref mut inner) => inner.next()
140+
}
141+
}
142+
143+
fn size_hint(&self) -> (uint, Option<uint>) {
144+
match *self {
145+
ZeroIterator => (0, Some(0)),
146+
OneIterator(*) => (1, Some(1)),
147+
ManyIterator(ref inner) => inner.size_hint()
148+
}
149+
}
150+
}
151+
152+
#[cfg(test)]
153+
mod test {
154+
use super::*;
155+
156+
#[test]
157+
fn test_len() {
158+
let v: SmallVector<int> = SmallVector::zero();
159+
assert_eq!(0, v.len());
160+
161+
assert_eq!(1, SmallVector::one(1).len());
162+
assert_eq!(5, SmallVector::many(~[1, 2, 3, 4, 5]).len());
163+
}
164+
165+
#[test]
166+
fn test_push_get() {
167+
let mut v = SmallVector::zero();
168+
v.push(1);
169+
assert_eq!(1, v.len());
170+
assert_eq!(&1, v.get(0));
171+
v.push(2);
172+
assert_eq!(2, v.len());
173+
assert_eq!(&2, v.get(1));
174+
v.push(3);
175+
assert_eq!(3, v.len());
176+
assert_eq!(&3, v.get(2));
177+
}
178+
179+
#[test]
180+
fn test_from_iterator() {
181+
let v: SmallVector<int> = (~[1, 2, 3]).move_iter().collect();
182+
assert_eq!(3, v.len());
183+
assert_eq!(&1, v.get(0));
184+
assert_eq!(&2, v.get(1));
185+
assert_eq!(&3, v.get(2));
186+
}
187+
188+
#[test]
189+
fn test_iter() {
190+
let v = SmallVector::zero();
191+
let v: ~[&int] = v.iter().collect();
192+
assert_eq!(~[], v);
193+
194+
let v = SmallVector::one(1);
195+
assert_eq!(~[&1], v.iter().collect());
196+
197+
let v = SmallVector::many(~[1, 2, 3]);
198+
assert_eq!(~[&1, &2, &3], v.iter().collect());
199+
}
200+
201+
#[test]
202+
fn test_move_iter() {
203+
let v = SmallVector::zero();
204+
let v: ~[int] = v.move_iter().collect();
205+
assert_eq!(~[], v);
206+
207+
let v = SmallVector::one(1);
208+
assert_eq!(~[1], v.move_iter().collect());
209+
210+
let v = SmallVector::many(~[1, 2, 3]);
211+
assert_eq!(~[1, 2, 3], v.move_iter().collect());
212+
}
213+
}

0 commit comments

Comments
 (0)