(index<- )        ./libgraphviz/maybe_owned_vec.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2014 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  
  11  use std::fmt;
  12  use std::iter::FromIterator;
  13  use std::slice;
  14  
  15  // Note 1: It is not clear whether the flexibility of providing both
  16  // the `Growable` and `FixedLen` variants is sufficiently useful.
  17  // Consider restricting to just a two variant enum.
  18  
  19  // Note 2: Once Dynamically Sized Types (DST) lands, it might be
  20  // reasonable to replace this with something like `enum MaybeOwned<'a,
  21  // Sized? U>{ Owned(Box<U>), Borrowed(&'a U) }`; and then `U` could be
  22  // instantiated with `[T]` or `str`, etc.  Of course, that would imply
  23  // removing the `Growable` variant, which relates to note 1 above.
  24  // Alternatively, we might add `MaybeOwned` for the general case but
  25  // keep some form of `MaybeOwnedVector` to avoid unnecessary copying
  26  // of the contents of `Vec<T>`, since we anticipate that to be a
  27  // frequent way to dynamically construct a vector.
  28  
  29  /// MaybeOwnedVector<'a,T> abstracts over `Vec<T>`, `~[T]`, `&'a [T]`.
  30  ///
  31  /// Some clients will have a pre-allocated vector ready to hand off in
  32  /// a slice; others will want to create the set on the fly and hand
  33  /// off ownership, via either `Growable` or `FixedLen` depending on
  34  /// which kind of vector they have constucted.  (The `FixedLen`
  35  /// variant is provided for interoperability with `std::slice` methods
  36  /// that return `~[T]`.)
  37  pub enum MaybeOwnedVector<'a,T> {
  38      Growable(Vec<T>),
  39      FixedLen(~[T]),
  40      Borrowed(&'a [T]),
  41  }
  42  
  43  /// Trait for moving into a `MaybeOwnedVector`
  44  pub trait IntoMaybeOwnedVector<'a,T> {
  45      /// Moves self into a `MaybeOwnedVector`
  46      fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T>;
  47  }
  48  
  49  impl<'a,T> IntoMaybeOwnedVector<'a,T> for Vec<T> {
  50      #[inline]
  51      fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) }
  52  }
  53  
  54  impl<'a,T> IntoMaybeOwnedVector<'a,T> for ~[T{
  55      #[inline]
  56      fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { FixedLen(self) }
  57  }
  58  
  59  impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T{
  60      #[inline]
  61      fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Borrowed(self) }
  62  }
  63  
  64  impl<'a,T> MaybeOwnedVector<'a,T> {
  65      pub fn iter(&'a self) -> slice::Items<'a,T> {
  66          match self {
  67              &Growable(ref v) => v.iter(),
  68              &FixedLen(ref v) => v.iter(),
  69              &Borrowed(ref v) => v.iter(),
  70          }
  71      }
  72  }
  73  
  74  // The `Vector` trait is provided in the prelude and is implemented on
  75  // both `&'a [T]` and `Vec<T>`, so it makes sense to try to support it
  76  // seamlessly.  The other vector related traits from the prelude do
  77  // not appear to be implemented on both `&'a [T]` and `Vec<T>`.  (It
  78  // is possible that this is an oversight in some cases.)
  79  //
  80  // In any case, with `Vector` in place, the client can just use
  81  // `as_slice` if they prefer that over `match`.
  82  
  83  impl<'b,T> slice::Vector<T> for MaybeOwnedVector<'b,T> {
  84      fn as_slice<'a>(&'a self) -> &'a [T] {
  85          match self {
  86              &Growable(ref v) => v.as_slice(),
  87              &FixedLen(ref v) => v.as_slice(),
  88              &Borrowed(ref v) => v.as_slice(),
  89          }
  90      }
  91  }
  92  
  93  impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> {
  94      fn from_iter<I:Iterator<T>>(iteratorI) -> MaybeOwnedVector<T> {
  95          // If we are building from scratch, might as well build the
  96          // most flexible variant.
  97          Growable(FromIterator::from_iter(iterator))
  98      }
  99  }
 100  
 101  impl<'a,T:fmt::Show> fmt::Show for MaybeOwnedVector<'a,T> {
 102      fn fmt(&self, f&mut fmt::Formatter) -> fmt::Result {
 103          self.as_slice().fmt(f)
 104      }
 105  }
 106  
 107  impl<'a,T:Clone> CloneableVector<T> for MaybeOwnedVector<'a,T> {
 108      /// Returns a copy of `self`.
 109      fn to_owned(&self) -> ~[T] {
 110          self.as_slice().to_owned()
 111      }
 112  
 113      /// Convert `self` into an owned slice, not making a copy if possible.
 114      fn into_owned(self) -> ~[T] {
 115          match self {
 116              Growable(v) => v.as_slice().to_owned(),
 117              FixedLen(v) => v,
 118              Borrowed(v) => v.to_owned(),
 119          }
 120      }
 121  }
 122  
 123  impl<'a,T:Clone> MaybeOwnedVector<'a,T> {
 124      /// Convert `self` into a growable `Vec`, not making a copy if possible.
 125      pub fn into_vec(self) -> Vec<T> {
 126          match self {
 127              Growable(v) => v,
 128              FixedLen(v) => Vec::from_slice(v.as_slice()),
 129              Borrowed(v) => Vec::from_slice(v),
 130          }
 131      }
 132  }