2014-02-14 00:57:43 -06:00
|
|
|
// 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.
|
2014-02-28 14:54:01 -06:00
|
|
|
|
2014-01-31 14:35:36 -06:00
|
|
|
use std::mem;
|
2014-04-21 18:21:52 -05:00
|
|
|
use std::slice;
|
2014-03-20 02:35:51 -05:00
|
|
|
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
|
2014-04-15 20:05:38 -05:00
|
|
|
pub struct SmallVector<T> {
|
|
|
|
repr: SmallVectorRepr<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum SmallVectorRepr<T> {
|
|
|
|
Zero,
|
|
|
|
One(T),
|
|
|
|
Many(Vec<T> ),
|
2013-11-24 23:18:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Container for SmallVector<T> {
|
|
|
|
fn len(&self) -> uint {
|
2014-04-15 20:05:38 -05:00
|
|
|
match self.repr {
|
2013-11-24 23:18:21 -06:00
|
|
|
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> {
|
2014-03-30 23:45:55 -05:00
|
|
|
fn from_iter<I: Iterator<T>>(iter: I) -> SmallVector<T> {
|
2014-04-15 20:05:38 -05:00
|
|
|
let mut v = SmallVector::zero();
|
2014-03-20 08:12:56 -05:00
|
|
|
v.extend(iter);
|
2013-11-24 23:18:21 -06:00
|
|
|
v
|
|
|
|
}
|
2014-03-03 12:12:40 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Extendable<T> for SmallVector<T> {
|
2014-03-20 08:12:56 -05:00
|
|
|
fn extend<I: Iterator<T>>(&mut self, mut iter: I) {
|
|
|
|
for val in iter {
|
2014-03-03 12:12:40 -06:00
|
|
|
self.push(val);
|
|
|
|
}
|
|
|
|
}
|
2013-11-24 23:18:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> SmallVector<T> {
|
|
|
|
pub fn zero() -> SmallVector<T> {
|
2014-04-15 20:05:38 -05:00
|
|
|
SmallVector { repr: Zero }
|
2013-11-24 23:18:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn one(v: T) -> SmallVector<T> {
|
2014-04-15 20:05:38 -05:00
|
|
|
SmallVector { repr: One(v) }
|
2013-11-24 23:18:21 -06:00
|
|
|
}
|
|
|
|
|
2014-04-15 20:05:38 -05:00
|
|
|
pub fn many(vs: Vec<T>) -> SmallVector<T> {
|
|
|
|
SmallVector { repr: Many(vs) }
|
2013-11-24 23:18:21 -06:00
|
|
|
}
|
|
|
|
|
2014-04-21 18:21:52 -05:00
|
|
|
pub fn as_slice<'a>(&'a self) -> &'a [T] {
|
|
|
|
match self.repr {
|
|
|
|
Zero => &[],
|
|
|
|
One(ref v) => slice::ref_slice(v),
|
|
|
|
Many(ref vs) => vs.as_slice()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-24 23:18:21 -06:00
|
|
|
pub fn push(&mut self, v: T) {
|
2014-04-15 20:05:38 -05:00
|
|
|
match self.repr {
|
|
|
|
Zero => self.repr = One(v),
|
2013-11-28 14:22:53 -06:00
|
|
|
One(..) => {
|
2014-04-15 20:05:38 -05:00
|
|
|
let one = mem::replace(&mut self.repr, Zero);
|
2013-11-25 22:02:15 -06:00
|
|
|
match one {
|
2014-04-15 20:05:38 -05:00
|
|
|
One(v1) => mem::replace(&mut self.repr, Many(vec!(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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-14 00:57:43 -06:00
|
|
|
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 {
|
2014-04-15 20:05:38 -05:00
|
|
|
match self.repr {
|
2013-11-24 23:18:21 -06:00
|
|
|
One(ref v) if idx == 0 => v,
|
2014-02-28 14:54:01 -06:00
|
|
|
Many(ref vs) => vs.get(idx),
|
2014-02-06 03:38:08 -06:00
|
|
|
_ => 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 {
|
2014-04-15 20:05:38 -05:00
|
|
|
match self.repr {
|
2013-11-25 22:02:15 -06:00
|
|
|
One(v) => v,
|
2014-02-13 11:46:46 -06:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
pub fn move_iter(self) -> MoveItems<T> {
|
2014-04-15 20:05:38 -05:00
|
|
|
let repr = match self.repr {
|
2013-11-24 23:18:21 -06:00
|
|
|
Zero => ZeroIterator,
|
|
|
|
One(v) => OneIterator(v),
|
|
|
|
Many(vs) => ManyIterator(vs.move_iter())
|
2014-04-15 20:05:38 -05:00
|
|
|
};
|
|
|
|
MoveItems { repr: repr }
|
2013-11-24 23:18:21 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-15 20:05:38 -05:00
|
|
|
pub struct MoveItems<T> {
|
|
|
|
repr: MoveItemsRepr<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum MoveItemsRepr<T> {
|
|
|
|
ZeroIterator,
|
|
|
|
OneIterator(T),
|
|
|
|
ManyIterator(vec::MoveItems<T>),
|
2013-11-24 23:18:21 -06:00
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<T> Iterator<T> for MoveItems<T> {
|
2013-11-24 23:18:21 -06:00
|
|
|
fn next(&mut self) -> Option<T> {
|
2014-04-15 20:05:38 -05:00
|
|
|
match self.repr {
|
2013-11-24 23:18:21 -06:00
|
|
|
ZeroIterator => None,
|
2013-11-28 14:22:53 -06:00
|
|
|
OneIterator(..) => {
|
2013-11-24 23:18:21 -06:00
|
|
|
let mut replacement = ZeroIterator;
|
2014-04-15 20:05:38 -05:00
|
|
|
mem::swap(&mut self.repr, &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>) {
|
2014-04-15 20:05:38 -05:00
|
|
|
match self.repr {
|
2013-11-24 23:18:21 -06:00
|
|
|
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());
|
2014-02-28 15:09:09 -06:00
|
|
|
assert_eq!(5, SmallVector::many(vec!(1, 2, 3, 4, 5)).len());
|
2013-11-24 23:18:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[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]
|
2014-03-30 23:45:55 -05:00
|
|
|
fn test_from_iter() {
|
2014-02-28 15:09:09 -06:00
|
|
|
let v: SmallVector<int> = (vec!(1, 2, 3)).move_iter().collect();
|
2013-11-24 23:18:21 -06:00
|
|
|
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();
|
2014-02-28 15:09:09 -06:00
|
|
|
let v: Vec<int> = v.move_iter().collect();
|
|
|
|
assert_eq!(Vec::new(), v);
|
2013-11-24 23:18:21 -06:00
|
|
|
|
|
|
|
let v = SmallVector::one(1);
|
2014-02-28 15:09:09 -06:00
|
|
|
assert_eq!(vec!(1), v.move_iter().collect());
|
2013-11-24 23:18:21 -06:00
|
|
|
|
2014-02-28 15:09:09 -06:00
|
|
|
let v = SmallVector::many(vec!(1, 2, 3));
|
|
|
|
assert_eq!(vec!(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() {
|
2014-02-28 15:09:09 -06:00
|
|
|
SmallVector::many(vec!(1, 2)).expect_one("");
|
2013-11-25 22:02:15 -06:00
|
|
|
}
|
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(""));
|
2014-02-28 15:09:09 -06:00
|
|
|
assert_eq!(1, SmallVector::many(vec!(1)).expect_one(""));
|
2013-11-24 23:18:21 -06:00
|
|
|
}
|
|
|
|
}
|