rust/src/libsyntax/util/small_vector.rs

202 lines
5.0 KiB
Rust
Raw Normal View History

// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2013-11-24 23:18:21 -06:00
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::mem;
use std::vec;
2013-11-24 23:18:21 -06:00
/// A vector type optimized for cases where the size is almost always 0 or 1
pub enum SmallVector<T> {
priv Zero,
priv One(T),
priv Many(~[T]),
}
impl<T> Container for SmallVector<T> {
fn len(&self) -> uint {
match *self {
Zero => 0,
2013-11-28 14:22:53 -06:00
One(..) => 1,
2013-11-24 23:18:21 -06:00
Many(ref vals) => vals.len()
}
}
}
impl<T> FromIterator<T> for SmallVector<T> {
fn from_iterator<I: Iterator<T>>(iter: &mut I) -> SmallVector<T> {
let mut v = Zero;
for val in *iter {
v.push(val);
}
v
}
}
impl<T> SmallVector<T> {
pub fn zero() -> SmallVector<T> {
Zero
}
pub fn one(v: T) -> SmallVector<T> {
One(v)
}
pub fn many(vs: ~[T]) -> SmallVector<T> {
Many(vs)
}
pub fn push(&mut self, v: T) {
match *self {
Zero => *self = One(v),
2013-11-28 14:22:53 -06:00
One(..) => {
let one = mem::replace(self, Zero);
2013-11-25 22:02:15 -06:00
match one {
One(v1) => mem::replace(self, Many(~[v1, v])),
2013-11-24 23:18:21 -06:00
_ => unreachable!()
2013-11-25 22:02:15 -06:00
};
2013-11-24 23:18:21 -06:00
}
Many(ref mut vs) => vs.push(v)
}
}
pub fn push_all(&mut self, other: SmallVector<T>) {
for v in other.move_iter() {
self.push(v);
}
}
2013-12-08 01:55:28 -06:00
pub fn get<'a>(&'a self, idx: uint) -> &'a T {
2013-11-24 23:18:21 -06:00
match *self {
One(ref v) if idx == 0 => v,
Many(ref vs) => &vs[idx],
_ => fail!("out of bounds access")
2013-11-24 23:18:21 -06:00
}
}
2013-11-25 22:02:15 -06:00
pub fn expect_one(self, err: &'static str) -> T {
match self {
One(v) => v,
Many(v) => {
if v.len() == 1 {
v.move_iter().next().unwrap()
} else {
fail!(err)
}
}
2013-11-25 22:02:15 -06:00
_ => fail!(err)
2013-11-24 23:18:21 -06:00
}
}
pub fn move_iter(self) -> MoveItems<T> {
2013-11-24 23:18:21 -06:00
match self {
Zero => ZeroIterator,
One(v) => OneIterator(v),
Many(vs) => ManyIterator(vs.move_iter())
}
}
}
pub enum MoveItems<T> {
2013-11-24 23:18:21 -06:00
priv ZeroIterator,
priv OneIterator(T),
priv ManyIterator(vec::MoveItems<T>),
2013-11-24 23:18:21 -06:00
}
impl<T> Iterator<T> for MoveItems<T> {
2013-11-24 23:18:21 -06:00
fn next(&mut self) -> Option<T> {
match *self {
ZeroIterator => None,
2013-11-28 14:22:53 -06:00
OneIterator(..) => {
2013-11-24 23:18:21 -06:00
let mut replacement = ZeroIterator;
mem::swap(self, &mut replacement);
2013-11-24 23:18:21 -06:00
match replacement {
OneIterator(v) => Some(v),
_ => unreachable!()
}
}
ManyIterator(ref mut inner) => inner.next()
}
}
fn size_hint(&self) -> (uint, Option<uint>) {
match *self {
ZeroIterator => (0, Some(0)),
2013-11-28 14:22:53 -06:00
OneIterator(..) => (1, Some(1)),
2013-11-24 23:18:21 -06:00
ManyIterator(ref inner) => inner.size_hint()
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_len() {
let v: SmallVector<int> = SmallVector::zero();
assert_eq!(0, v.len());
assert_eq!(1, SmallVector::one(1).len());
assert_eq!(5, SmallVector::many(~[1, 2, 3, 4, 5]).len());
}
#[test]
fn test_push_get() {
let mut v = SmallVector::zero();
v.push(1);
assert_eq!(1, v.len());
assert_eq!(&1, v.get(0));
v.push(2);
assert_eq!(2, v.len());
assert_eq!(&2, v.get(1));
v.push(3);
assert_eq!(3, v.len());
assert_eq!(&3, v.get(2));
}
#[test]
fn test_from_iterator() {
let v: SmallVector<int> = (~[1, 2, 3]).move_iter().collect();
assert_eq!(3, v.len());
assert_eq!(&1, v.get(0));
assert_eq!(&2, v.get(1));
assert_eq!(&3, v.get(2));
}
#[test]
2013-11-25 22:02:15 -06:00
fn test_move_iter() {
2013-11-24 23:18:21 -06:00
let v = SmallVector::zero();
2013-11-25 22:02:15 -06:00
let v: ~[int] = v.move_iter().collect();
2013-11-24 23:18:21 -06:00
assert_eq!(~[], v);
let v = SmallVector::one(1);
2013-11-25 22:02:15 -06:00
assert_eq!(~[1], v.move_iter().collect());
2013-11-24 23:18:21 -06:00
let v = SmallVector::many(~[1, 2, 3]);
2013-11-25 22:02:15 -06:00
assert_eq!(~[1, 2, 3], v.move_iter().collect());
2013-11-24 23:18:21 -06:00
}
#[test]
2013-11-25 22:02:15 -06:00
#[should_fail]
fn test_expect_one_zero() {
let _: int = SmallVector::zero().expect_one("");
}
2013-11-24 23:18:21 -06:00
2013-11-25 22:02:15 -06:00
#[test]
#[should_fail]
fn test_expect_one_many() {
SmallVector::many(~[1, 2]).expect_one("");
}
2013-11-24 23:18:21 -06:00
2013-11-25 22:02:15 -06:00
#[test]
fn test_expect_one_one() {
assert_eq!(1, SmallVector::one(1).expect_one(""));
assert_eq!(1, SmallVector::many(~[1]).expect_one(""));
2013-11-24 23:18:21 -06:00
}
}