// Copyright 2012 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. /*! * * Defines a type OptVec that can be used in place of ~[T]. * OptVec avoids the need for allocation for empty vectors. * OptVec implements the iterable interface as well as * other useful things like `push()` and `len()`. */ use core::prelude::*; use core::iter; use core::iter::BaseIter; #[auto_encode] #[auto_decode] pub enum OptVec { Empty, Vec(~[T]) } pub fn with(+t: T) -> OptVec { Vec(~[t]) } pub fn from(+t: ~[T]) -> OptVec { if t.len() == 0 { Empty } else { Vec(t) } } impl OptVec { fn push(&mut self, +t: T) { match *self { Vec(ref mut v) => { v.push(t); return; } Empty => {} } // FIXME(#5074): flow insensitive means we can't move // assignment inside `match` *self = Vec(~[t]); } fn map(&self, op: &fn(&T) -> U) -> OptVec { match *self { Empty => Empty, Vec(ref v) => Vec(v.map(op)) } } fn get(&self, i: uint) -> &'self T { match *self { Empty => fail!(fmt!("Invalid index %u", i)), Vec(ref v) => &v[i] } } fn is_empty(&self) -> bool { self.len() == 0 } fn len(&self) -> uint { match *self { Empty => 0, Vec(ref v) => v.len() } } } pub fn take_vec(+v: OptVec) -> ~[T] { match v { Empty => ~[], Vec(v) => v } } impl OptVec { fn prepend(&self, +t: T) -> OptVec { let mut v0 = ~[t]; match *self { Empty => {} Vec(ref v1) => { v0.push_all(*v1); } } return Vec(v0); } fn push_all>(&mut self, from: &I) { for from.each |e| { self.push(copy *e); } } #[inline(always)] fn mapi_to_vec(&self, op: &fn(uint, &T) -> B) -> ~[B] { let mut index = 0; iter::map_to_vec(self, |a| { let i = index; index += 1; op(i, a) }) } } impl Eq for OptVec { fn eq(&self, other: &OptVec) -> bool { // Note: cannot use #[deriving(Eq)] here because // (Empty, Vec(~[])) ought to be equal. match (self, other) { (&Empty, &Empty) => true, (&Empty, &Vec(ref v)) => v.is_empty(), (&Vec(ref v), &Empty) => v.is_empty(), (&Vec(ref v1), &Vec(ref v2)) => *v1 == *v2 } } fn ne(&self, other: &OptVec) -> bool { !self.eq(other) } } impl BaseIter for OptVec { fn each(&self, blk: &fn(v: &A) -> bool) { match *self { Empty => {} Vec(ref v) => v.each(blk) } } fn size_hint(&self) -> Option { Some(self.len()) } } impl iter::ExtendedIter for OptVec { #[inline(always)] fn eachi(&self, blk: &fn(+v: uint, v: &A) -> bool) { iter::eachi(self, blk) } #[inline(always)] fn all(&self, blk: &fn(&A) -> bool) -> bool { iter::all(self, blk) } #[inline(always)] fn any(&self, blk: &fn(&A) -> bool) -> bool { iter::any(self, blk) } #[inline(always)] fn foldl(&self, +b0: B, blk: &fn(&B, &A) -> B) -> B { iter::foldl(self, b0, blk) } #[inline(always)] fn position(&self, f: &fn(&A) -> bool) -> Option { iter::position(self, f) } #[inline(always)] fn map_to_vec(&self, op: &fn(&A) -> B) -> ~[B] { iter::map_to_vec(self, op) } #[inline(always)] fn flat_map_to_vec>(&self, op: &fn(&A) -> IB) -> ~[B] { iter::flat_map_to_vec(self, op) } } impl iter::EqIter for OptVec { #[inline(always)] fn contains(&self, x: &A) -> bool { iter::contains(self, x) } #[inline(always)] fn count(&self, x: &A) -> uint { iter::count(self, x) } } impl iter::CopyableIter for OptVec { #[inline(always)] fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] { iter::filter_to_vec(self, pred) } #[inline(always)] fn to_vec(&self) -> ~[A] { iter::to_vec(self) } #[inline(always)] fn find(&self, f: &fn(&A) -> bool) -> Option { iter::find(self, f) } } impl iter::CopyableOrderedIter for OptVec { #[inline(always)] fn min(&self) -> A { iter::min(self) } #[inline(always)] fn max(&self) -> A { iter::max(self) } }