rust/src/libsyntax/util/small_vector.rs
Alex Crichton ff49733274 std: Stabilize library APIs for 1.5
This commit stabilizes and deprecates library APIs whose FCP has closed in the
last cycle, specifically:

Stabilized APIs:

* `fs::canonicalize`
* `Path::{metadata, symlink_metadata, canonicalize, read_link, read_dir, exists,
   is_file, is_dir}` - all moved to inherent methods from the `PathExt` trait.
* `Formatter::fill`
* `Formatter::width`
* `Formatter::precision`
* `Formatter::sign_plus`
* `Formatter::sign_minus`
* `Formatter::alternate`
* `Formatter::sign_aware_zero_pad`
* `string::ParseError`
* `Utf8Error::valid_up_to`
* `Iterator::{cmp, partial_cmp, eq, ne, lt, le, gt, ge}`
* `<[T]>::split_{first,last}{,_mut}`
* `Condvar::wait_timeout` - note that `wait_timeout_ms` is not yet deprecated
  but will be once 1.5 is released.
* `str::{R,}MatchIndices`
* `str::{r,}match_indices`
* `char::from_u32_unchecked`
* `VecDeque::insert`
* `VecDeque::shrink_to_fit`
* `VecDeque::as_slices`
* `VecDeque::as_mut_slices`
* `VecDeque::swap_remove_front` - (renamed from `swap_front_remove`)
* `VecDeque::swap_remove_back` - (renamed from `swap_back_remove`)
* `Vec::resize`
* `str::slice_mut_unchecked`
* `FileTypeExt`
* `FileTypeExt::{is_block_device, is_char_device, is_fifo, is_socket}`
* `BinaryHeap::from` - `from_vec` deprecated in favor of this
* `BinaryHeap::into_vec` - plus a `Into` impl
* `BinaryHeap::into_sorted_vec`

Deprecated APIs

* `slice::ref_slice`
* `slice::mut_ref_slice`
* `iter::{range_inclusive, RangeInclusive}`
* `std::dynamic_lib`

Closes #27706
Closes #27725
cc #27726 (align not stabilized yet)
Closes #27734
Closes #27737
Closes #27742
Closes #27743
Closes #27772
Closes #27774
Closes #27777
Closes #27781
cc #27788 (a few remaining methods though)
Closes #27790
Closes #27793
Closes #27796
Closes #27810
cc #28147 (not all parts stabilized)
2015-10-25 09:36:32 -07:00

271 lines
6.8 KiB
Rust

// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// 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 self::SmallVectorRepr::*;
use self::IntoIterRepr::*;
use std::iter::{IntoIterator, FromIterator};
use std::mem;
use std::slice;
use std::vec;
use fold::MoveMap;
/// A vector type optimized for cases where the size is almost always 0 or 1
pub struct SmallVector<T> {
repr: SmallVectorRepr<T>,
}
enum SmallVectorRepr<T> {
Zero,
One(T),
Many(Vec<T>),
}
impl<T> FromIterator<T> for SmallVector<T> {
fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> SmallVector<T> {
let mut v = SmallVector::zero();
v.extend(iter);
v
}
}
impl<T> Extend<T> for SmallVector<T> {
fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
for val in iter {
self.push(val);
}
}
}
impl<T> SmallVector<T> {
pub fn zero() -> SmallVector<T> {
SmallVector { repr: Zero }
}
pub fn one(v: T) -> SmallVector<T> {
SmallVector { repr: One(v) }
}
pub fn many(vs: Vec<T>) -> SmallVector<T> {
SmallVector { repr: Many(vs) }
}
pub fn as_slice<'a>(&'a self) -> &'a [T] {
match self.repr {
Zero => {
let result: &[T] = &[];
result
}
One(ref v) => {
unsafe { slice::from_raw_parts(v, 1) }
}
Many(ref vs) => vs
}
}
pub fn pop(&mut self) -> Option<T> {
match self.repr {
Zero => None,
One(..) => {
let one = mem::replace(&mut self.repr, Zero);
match one {
One(v1) => Some(v1),
_ => unreachable!()
}
}
Many(ref mut vs) => vs.pop(),
}
}
pub fn push(&mut self, v: T) {
match self.repr {
Zero => self.repr = One(v),
One(..) => {
let one = mem::replace(&mut self.repr, Zero);
match one {
One(v1) => mem::replace(&mut self.repr, Many(vec!(v1, v))),
_ => unreachable!()
};
}
Many(ref mut vs) => vs.push(v)
}
}
pub fn push_all(&mut self, other: SmallVector<T>) {
for v in other.into_iter() {
self.push(v);
}
}
pub fn get<'a>(&'a self, idx: usize) -> &'a T {
match self.repr {
One(ref v) if idx == 0 => v,
Many(ref vs) => &vs[idx],
_ => panic!("out of bounds access")
}
}
pub fn expect_one(self, err: &'static str) -> T {
match self.repr {
One(v) => v,
Many(v) => {
if v.len() == 1 {
v.into_iter().next().unwrap()
} else {
panic!(err)
}
}
_ => panic!(err)
}
}
/// Deprecated: use `into_iter`.
#[unstable(feature = "rustc_private", issue = "0")]
#[deprecated(since = "1.0.0", reason = "use into_iter")]
pub fn move_iter(self) -> IntoIter<T> {
self.into_iter()
}
pub fn into_iter(self) -> IntoIter<T> {
let repr = match self.repr {
Zero => ZeroIterator,
One(v) => OneIterator(v),
Many(vs) => ManyIterator(vs.into_iter())
};
IntoIter { repr: repr }
}
pub fn len(&self) -> usize {
match self.repr {
Zero => 0,
One(..) => 1,
Many(ref vals) => vals.len()
}
}
pub fn is_empty(&self) -> bool { self.len() == 0 }
}
pub struct IntoIter<T> {
repr: IntoIterRepr<T>,
}
enum IntoIterRepr<T> {
ZeroIterator,
OneIterator(T),
ManyIterator(vec::IntoIter<T>),
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
match self.repr {
ZeroIterator => None,
OneIterator(..) => {
let mut replacement = ZeroIterator;
mem::swap(&mut self.repr, &mut replacement);
match replacement {
OneIterator(v) => Some(v),
_ => unreachable!()
}
}
ManyIterator(ref mut inner) => inner.next()
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self.repr {
ZeroIterator => (0, Some(0)),
OneIterator(..) => (1, Some(1)),
ManyIterator(ref inner) => inner.size_hint()
}
}
}
impl<T> MoveMap<T> for SmallVector<T> {
fn move_map<F>(self, mut f: F) -> SmallVector<T> where F: FnMut(T) -> T {
let repr = match self.repr {
Zero => Zero,
One(v) => One(f(v)),
Many(vs) => Many(vs.move_map(f))
};
SmallVector { repr: repr }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_len() {
let v: SmallVector<isize> = SmallVector::zero();
assert_eq!(0, v.len());
assert_eq!(1, SmallVector::one(1).len());
assert_eq!(5, SmallVector::many(vec![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_iter() {
let v: SmallVector<isize> = (vec![1, 2, 3]).into_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]
fn test_move_iter() {
let v = SmallVector::zero();
let v: Vec<isize> = v.into_iter().collect();
assert_eq!(v, Vec::new());
let v = SmallVector::one(1);
assert_eq!(v.into_iter().collect::<Vec<_>>(), [1]);
let v = SmallVector::many(vec![1, 2, 3]);
assert_eq!(v.into_iter().collect::<Vec<_>>(), [1, 2, 3]);
}
#[test]
#[should_panic]
fn test_expect_one_zero() {
let _: isize = SmallVector::zero().expect_one("");
}
#[test]
#[should_panic]
fn test_expect_one_many() {
SmallVector::many(vec!(1, 2)).expect_one("");
}
#[test]
fn test_expect_one_one() {
assert_eq!(1, SmallVector::one(1).expect_one(""));
assert_eq!(1, SmallVector::many(vec!(1)).expect_one(""));
}
}