Deprecate MaybeOwned[Vector] in favor of Cow

This commit is contained in:
Jorge Aparicio 2014-11-21 17:10:42 -05:00
parent 48ca6d1840
commit 3293ab14e2
21 changed files with 323 additions and 169 deletions

View File

@ -67,6 +67,7 @@ use core::prelude::*;
use alloc::boxed::Box;
use alloc::rc::Rc;
use core::borrow::{Cow, ToOwned};
use core::intrinsics::TypeId;
use core::mem;
use core::num::Int;
@ -284,6 +285,13 @@ impl<S: Writer, T: Hash<S>, U: Hash<S>> Hash<S> for Result<T, U> {
}
}
impl<'a, T, Sized? B, S> Hash<S> for Cow<'a, T, B> where B: Hash<S> + ToOwned<T> {
#[inline]
fn hash(&self, state: &mut S) {
Hash::hash(&**self, state)
}
}
//////////////////////////////////////////////////////////////////////////////
#[cfg(test)]

View File

@ -54,7 +54,7 @@
pub use self::MaybeOwned::*;
use self::RecompositionState::*;
use self::DecompositionType::*;
use core::borrow::{BorrowFrom, ToOwned};
use core::borrow::{BorrowFrom, Cow, ToOwned};
use core::default::Default;
use core::fmt;
use core::cmp;
@ -67,7 +67,7 @@ use core::prelude::{range};
use hash;
use ring_buf::RingBuf;
use string::{String, ToString};
use string::String;
use unicode;
use vec::Vec;
@ -425,6 +425,7 @@ Section: MaybeOwned
/// A string type that can hold either a `String` or a `&str`.
/// This can be useful as an optimization when an allocation is sometimes
/// needed but not always.
#[deprecated = "use std::str::CowString"]
pub enum MaybeOwned<'a> {
/// A borrowed string.
Slice(&'a str),
@ -432,15 +433,16 @@ pub enum MaybeOwned<'a> {
Owned(String)
}
/// A specialization of `MaybeOwned` to be sendable.
pub type SendStr = MaybeOwned<'static>;
/// A specialization of `CowString` to be sendable.
pub type SendStr = CowString<'static>;
#[deprecated = "use std::str::CowString"]
impl<'a> MaybeOwned<'a> {
/// Returns `true` if this `MaybeOwned` wraps an owned string.
///
/// # Example
///
/// ```rust
/// ``` ignore
/// let string = String::from_str("orange");
/// let maybe_owned_string = string.into_maybe_owned();
/// assert_eq!(true, maybe_owned_string.is_owned());
@ -457,7 +459,7 @@ impl<'a> MaybeOwned<'a> {
///
/// # Example
///
/// ```rust
/// ``` ignore
/// let string = "orange";
/// let maybe_owned_string = string.as_slice().into_maybe_owned();
/// assert_eq!(true, maybe_owned_string.is_slice());
@ -475,46 +477,56 @@ impl<'a> MaybeOwned<'a> {
pub fn len(&self) -> uint { self.as_slice().len() }
/// Returns true if the string contains no bytes
#[allow(deprecated)]
#[inline]
pub fn is_empty(&self) -> bool { self.len() == 0 }
}
#[deprecated = "use std::borrow::IntoCow"]
/// Trait for moving into a `MaybeOwned`.
pub trait IntoMaybeOwned<'a> {
/// Moves `self` into a `MaybeOwned`.
fn into_maybe_owned(self) -> MaybeOwned<'a>;
}
#[deprecated = "use std::borrow::IntoCow"]
#[allow(deprecated)]
impl<'a> IntoMaybeOwned<'a> for String {
/// # Example
///
/// ```rust
/// ``` ignore
/// let owned_string = String::from_str("orange");
/// let maybe_owned_string = owned_string.into_maybe_owned();
/// assert_eq!(true, maybe_owned_string.is_owned());
/// ```
#[allow(deprecated)]
#[inline]
fn into_maybe_owned(self) -> MaybeOwned<'a> {
Owned(self)
}
}
#[deprecated = "use std::borrow::IntoCow"]
#[allow(deprecated)]
impl<'a> IntoMaybeOwned<'a> for &'a str {
/// # Example
///
/// ```rust
/// ``` ignore
/// let string = "orange";
/// let maybe_owned_str = string.as_slice().into_maybe_owned();
/// assert_eq!(false, maybe_owned_str.is_owned());
/// ```
#[allow(deprecated)]
#[inline]
fn into_maybe_owned(self) -> MaybeOwned<'a> { Slice(self) }
}
#[allow(deprecated)]
#[deprecated = "use std::borrow::IntoCow"]
impl<'a> IntoMaybeOwned<'a> for MaybeOwned<'a> {
/// # Example
///
/// ```rust
/// ``` ignore
/// let str = "orange";
/// let maybe_owned_str = str.as_slice().into_maybe_owned();
/// let maybe_maybe_owned_str = maybe_owned_str.into_maybe_owned();
@ -524,6 +536,7 @@ impl<'a> IntoMaybeOwned<'a> for MaybeOwned<'a> {
fn into_maybe_owned(self) -> MaybeOwned<'a> { self }
}
#[deprecated = "use std::str::CowString"]
impl<'a> PartialEq for MaybeOwned<'a> {
#[inline]
fn eq(&self, other: &MaybeOwned) -> bool {
@ -531,8 +544,10 @@ impl<'a> PartialEq for MaybeOwned<'a> {
}
}
#[deprecated = "use std::str::CowString"]
impl<'a> Eq for MaybeOwned<'a> {}
#[deprecated = "use std::str::CowString"]
impl<'a> PartialOrd for MaybeOwned<'a> {
#[inline]
fn partial_cmp(&self, other: &MaybeOwned) -> Option<Ordering> {
@ -540,6 +555,7 @@ impl<'a> PartialOrd for MaybeOwned<'a> {
}
}
#[deprecated = "use std::str::CowString"]
impl<'a> Ord for MaybeOwned<'a> {
#[inline]
fn cmp(&self, other: &MaybeOwned) -> Ordering {
@ -547,6 +563,7 @@ impl<'a> Ord for MaybeOwned<'a> {
}
}
#[deprecated = "use std::str::CowString"]
impl<'a, S: Str> Equiv<S> for MaybeOwned<'a> {
#[inline]
fn equiv(&self, other: &S) -> bool {
@ -554,7 +571,9 @@ impl<'a, S: Str> Equiv<S> for MaybeOwned<'a> {
}
}
#[deprecated = "use std::str::CowString"]
impl<'a> Str for MaybeOwned<'a> {
#[allow(deprecated)]
#[inline]
fn as_slice<'b>(&'b self) -> &'b str {
match *self {
@ -564,7 +583,9 @@ impl<'a> Str for MaybeOwned<'a> {
}
}
#[deprecated = "use std::str::CowString"]
impl<'a> StrAllocating for MaybeOwned<'a> {
#[allow(deprecated)]
#[inline]
fn into_string(self) -> String {
match self {
@ -574,7 +595,9 @@ impl<'a> StrAllocating for MaybeOwned<'a> {
}
}
#[deprecated = "use std::str::CowString"]
impl<'a> Clone for MaybeOwned<'a> {
#[allow(deprecated)]
#[inline]
fn clone(&self) -> MaybeOwned<'a> {
match *self {
@ -584,11 +607,14 @@ impl<'a> Clone for MaybeOwned<'a> {
}
}
#[deprecated = "use std::str::CowString"]
impl<'a> Default for MaybeOwned<'a> {
#[allow(deprecated)]
#[inline]
fn default() -> MaybeOwned<'a> { Slice("") }
}
#[deprecated = "use std::str::CowString"]
impl<'a, H: hash::Writer> hash::Hash<H> for MaybeOwned<'a> {
#[inline]
fn hash(&self, hasher: &mut H) {
@ -596,6 +622,7 @@ impl<'a, H: hash::Writer> hash::Hash<H> for MaybeOwned<'a> {
}
}
#[deprecated = "use std::str::CowString"]
impl<'a> fmt::Show for MaybeOwned<'a> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -613,7 +640,7 @@ impl BorrowFrom<String> for str {
#[unstable = "trait is unstable"]
impl ToOwned<String> for str {
fn to_owned(&self) -> String { self.to_string() }
fn to_owned(&self) -> String { self.into_string() }
}
/// Unsafe string operations.
@ -622,6 +649,13 @@ pub mod raw {
pub use core::str::raw::{slice_unchecked};
}
/*
Section: CowString
*/
/// A clone-on-write string
pub type CowString<'a> = Cow<'a, String, str>;
/*
Section: Trait implementations
*/

View File

@ -14,6 +14,7 @@
use core::prelude::*;
use core::borrow::{Cow, IntoCow};
use core::default::Default;
use core::fmt;
use core::mem;
@ -25,8 +26,7 @@ use core::raw::Slice as RawSlice;
use hash;
use slice::CloneSliceAllocPrelude;
use str;
use str::{CharRange, FromStr, StrAllocating, MaybeOwned, Owned};
use str::Slice as MaybeOwnedSlice; // So many `Slice`s...
use str::{CharRange, CowString, FromStr, StrAllocating, Owned};
use vec::{DerefVec, Vec, as_vec};
/// A growable string stored as a UTF-8 encoded buffer.
@ -121,9 +121,9 @@ impl String {
/// assert_eq!(output.as_slice(), "Hello \uFFFDWorld");
/// ```
#[unstable = "return type may change"]
pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> MaybeOwned<'a> {
pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> CowString<'a> {
if str::is_utf8(v) {
return MaybeOwnedSlice(unsafe { mem::transmute(v) })
return Cow::Borrowed(unsafe { mem::transmute(v) })
}
static TAG_CONT_U8: u8 = 128u8;
@ -234,7 +234,7 @@ impl String {
res.as_mut_vec().push_all(v[subseqidx..total])
};
}
Owned(res.into_string())
Cow::Owned(res.into_string())
}
/// Decode a UTF-16 encoded vector `v` into a `String`, returning `None`
@ -868,6 +868,18 @@ impl<T: fmt::Show> ToString for T {
}
}
impl IntoCow<'static, String, str> for String {
fn into_cow(self) -> CowString<'static> {
Cow::Owned(self)
}
}
impl<'a> IntoCow<'a, String, str> for &'a str {
fn into_cow(self) -> CowString<'a> {
Cow::Borrowed(self)
}
}
/// Unsafe operations
#[deprecated]
pub mod raw {
@ -921,11 +933,11 @@ mod tests {
use std::prelude::*;
use test::Bencher;
use slice::CloneSliceAllocPrelude;
use str::{Str, StrPrelude};
use str;
use str::{Str, StrPrelude, Owned};
use super::{as_string, String, ToString};
use vec::Vec;
use slice::CloneSliceAllocPrelude;
#[test]
fn test_as_string() {
@ -955,39 +967,39 @@ mod tests {
#[test]
fn test_from_utf8_lossy() {
let xs = b"hello";
assert_eq!(String::from_utf8_lossy(xs), str::Slice("hello"));
assert_eq!(String::from_utf8_lossy(xs), "hello".into_cow());
let xs = "ศไทย中华Việt Nam".as_bytes();
assert_eq!(String::from_utf8_lossy(xs), str::Slice("ศไทย中华Việt Nam"));
assert_eq!(String::from_utf8_lossy(xs), "ศไทย中华Việt Nam".into_cow());
let xs = b"Hello\xC2 There\xFF Goodbye";
assert_eq!(String::from_utf8_lossy(xs),
Owned(String::from_str("Hello\uFFFD There\uFFFD Goodbye")));
String::from_str("Hello\uFFFD There\uFFFD Goodbye").into_cow());
let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
assert_eq!(String::from_utf8_lossy(xs),
Owned(String::from_str("Hello\uFFFD\uFFFD There\uFFFD Goodbye")));
String::from_str("Hello\uFFFD\uFFFD There\uFFFD Goodbye").into_cow());
let xs = b"\xF5foo\xF5\x80bar";
assert_eq!(String::from_utf8_lossy(xs),
Owned(String::from_str("\uFFFDfoo\uFFFD\uFFFDbar")));
String::from_str("\uFFFDfoo\uFFFD\uFFFDbar").into_cow());
let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
assert_eq!(String::from_utf8_lossy(xs),
Owned(String::from_str("\uFFFDfoo\uFFFDbar\uFFFDbaz")));
String::from_str("\uFFFDfoo\uFFFDbar\uFFFDbaz").into_cow());
let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
assert_eq!(String::from_utf8_lossy(xs),
Owned(String::from_str("\uFFFDfoo\uFFFDbar\uFFFD\uFFFDbaz")));
String::from_str("\uFFFDfoo\uFFFDbar\uFFFD\uFFFDbaz").into_cow());
let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
assert_eq!(String::from_utf8_lossy(xs), Owned(String::from_str("\uFFFD\uFFFD\uFFFD\uFFFD\
foo\U00010000bar")));
assert_eq!(String::from_utf8_lossy(xs), String::from_str("\uFFFD\uFFFD\uFFFD\uFFFD\
foo\U00010000bar").into_cow());
// surrogates
let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
assert_eq!(String::from_utf8_lossy(xs), Owned(String::from_str("\uFFFD\uFFFD\uFFFDfoo\
\uFFFD\uFFFD\uFFFDbar")));
assert_eq!(String::from_utf8_lossy(xs), String::from_str("\uFFFD\uFFFD\uFFFDfoo\
\uFFFD\uFFFD\uFFFDbar").into_cow());
}
#[test]

View File

@ -16,6 +16,7 @@ use core::prelude::*;
use alloc::boxed::Box;
use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
use core::borrow::{Cow, IntoCow};
use core::cmp::max;
use core::default::Default;
use core::fmt;
@ -107,6 +108,27 @@ pub struct Vec<T> {
cap: uint,
}
/// A clone-on-write vector
pub type CowVec<'a, T> = Cow<'a, Vec<T>, [T]>;
impl<'a, T> FromIterator<T> for CowVec<'a, T> where T: Clone {
fn from_iter<I: Iterator<T>>(it: I) -> CowVec<'a, T> {
Cow::Owned(FromIterator::from_iter(it))
}
}
impl<'a, T: 'a> IntoCow<'a, Vec<T>, [T]> for Vec<T> where T: Clone {
fn into_cow(self) -> CowVec<'a, T> {
Cow::Owned(self)
}
}
impl<'a, T> IntoCow<'a, Vec<T>, [T]> for &'a [T] where T: Clone {
fn into_cow(self) -> CowVec<'a, T> {
Cow::Borrowed(self)
}
}
impl<T> Vec<T> {
/// Constructs a new, empty `Vec`.
///

View File

@ -45,8 +45,11 @@
#![unstable = "recently added as part of collections reform"]
use clone::Clone;
use cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use fmt;
use kinds::Sized;
use ops::Deref;
use option::Option;
use self::Cow::*;
/// A trait for borrowing data.
@ -81,6 +84,24 @@ impl<'a, Sized? T> BorrowFromMut<&'a mut T> for T {
fn borrow_from_mut<'b>(owned: &'b mut &'a mut T) -> &'b mut T { &mut **owned }
}
impl<'a, T, Sized? B> BorrowFrom<Cow<'a, T, B>> for B where B: ToOwned<T> {
fn borrow_from<'b>(owned: &'b Cow<'a, T, B>) -> &'b B {
&**owned
}
}
/// Trait for moving into a `Cow`
pub trait IntoCow<'a, T, Sized? B> {
/// Moves `self` into `Cow`
fn into_cow(self) -> Cow<'a, T, B>;
}
impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned<T> {
fn into_cow(self) -> Cow<'a, T, B> {
self
}
}
/// A generalization of Clone to borrowed data.
pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
/// Create owned data from borrowed data, usually by copying.
@ -139,6 +160,22 @@ impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned<T> {
Owned(owned) => owned
}
}
/// Returns true if this `Cow` wraps a borrowed value
pub fn is_borrowed(&self) -> bool {
match *self {
Borrowed(_) => true,
_ => false,
}
}
/// Returns true if this `Cow` wraps an owned value
pub fn is_owned(&self) -> bool {
match *self {
Owned(_) => true,
_ => false,
}
}
}
impl<'a, T, Sized? B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T> {
@ -149,3 +186,35 @@ impl<'a, T, Sized? B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T> {
}
}
}
impl<'a, T, Sized? B> Eq for Cow<'a, T, B> where B: Eq + ToOwned<T> {}
impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
#[inline]
fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<'a, T, Sized? B> PartialEq for Cow<'a, T, B> where B: PartialEq + ToOwned<T> {
#[inline]
fn eq(&self, other: &Cow<'a, T, B>) -> bool {
PartialEq::eq(&**self, &**other)
}
}
impl<'a, T, Sized? B> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned<T> {
#[inline]
fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
impl<'a, T, Sized? B> fmt::Show for Cow<'a, T, B> where B: fmt::Show + ToOwned<T>, T: fmt::Show {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Borrowed(ref b) => fmt::Show::fmt(b, f),
Owned(ref o) => fmt::Show::fmt(o, f),
}
}
}

View File

@ -37,7 +37,7 @@ pairs of ints, representing the edges (the node set is implicit).
Each node label is derived directly from the int representing the node,
while the edge labels are all empty strings.
This example also illustrates how to use `MaybeOwnedVector` to return
This example also illustrates how to use `CowVec` to return
an owned vector or a borrowed slice as appropriate: we construct the
node vector from scratch, but borrow the edge list (rather than
constructing a copy of all the edges from scratch).
@ -48,7 +48,6 @@ which is cyclic.
```rust
use graphviz as dot;
use graphviz::maybe_owned_vec::IntoMaybeOwnedVector;
type Nd = int;
type Ed = (int,int);
@ -77,12 +76,12 @@ impl<'a> dot::GraphWalk<'a, Nd, Ed> for Edges {
}
nodes.sort();
nodes.dedup();
nodes.into_maybe_owned()
nodes.into_cow()
}
fn edges(&'a self) -> dot::Edges<'a,Ed> {
let &Edges(ref edges) = self;
edges.as_slice().into_maybe_owned()
edges.as_slice().into_cow()
}
fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s }
@ -137,8 +136,8 @@ edges stored in `self`.
Since both the set of nodes and the set of edges are always
constructed from scratch via iterators, we use the `collect()` method
from the `Iterator` trait to collect the nodes and edges into freshly
constructed growable `Vec` values (rather use the `into_maybe_owned`
from the `IntoMaybeOwnedVector` trait as was used in the first example
constructed growable `Vec` values (rather use the `into_cow`
from the `IntoCow` trait as was used in the first example
above).
The output from this example renders four nodes that make up the
@ -148,7 +147,6 @@ entity `&sube`).
```rust
use graphviz as dot;
use std::str;
type Nd = uint;
type Ed<'a> = &'a (uint, uint);
@ -168,10 +166,10 @@ impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph {
dot::Id::new(format!("N{}", n)).unwrap()
}
fn node_label<'a>(&'a self, n: &Nd) -> dot::LabelText<'a> {
dot::LabelStr(str::Slice(self.nodes[*n].as_slice()))
dot::LabelStr(self.nodes[*n].as_slice().into_cow())
}
fn edge_label<'a>(&'a self, _: &Ed) -> dot::LabelText<'a> {
dot::LabelStr(str::Slice("&sube;"))
dot::LabelStr("&sube;".into_cow())
}
}
@ -204,7 +202,6 @@ Hasse-diagram for the subsets of the set `{x, y}`.
```rust
use graphviz as dot;
use std::str;
type Nd<'a> = (uint, &'a str);
type Ed<'a> = (Nd<'a>, Nd<'a>);
@ -225,10 +222,10 @@ impl<'a> dot::Labeller<'a, Nd<'a>, Ed<'a>> for Graph {
}
fn node_label<'a>(&'a self, n: &Nd<'a>) -> dot::LabelText<'a> {
let &(i, _) = n;
dot::LabelStr(str::Slice(self.nodes[i].as_slice()))
dot::LabelStr(self.nodes[i].as_slice().into_cow())
}
fn edge_label<'a>(&'a self, _: &Ed<'a>) -> dot::LabelText<'a> {
dot::LabelStr(str::Slice("&sube;"))
dot::LabelStr("&sube;".into_cow())
}
}
@ -279,8 +276,8 @@ pub fn main() {
pub use self::LabelText::*;
use std::io;
use std::str;
use self::maybe_owned_vec::MaybeOwnedVector;
use std::str::CowString;
use std::vec::CowVec;
pub mod maybe_owned_vec;
@ -290,7 +287,7 @@ pub enum LabelText<'a> {
///
/// Occurrences of backslashes (`\`) are escaped, and thus appear
/// as backslashes in the rendered label.
LabelStr(str::MaybeOwned<'a>),
LabelStr(CowString<'a>),
/// This kind of label uses the graphviz label escString type:
/// http://www.graphviz.org/content/attrs#kescString
@ -302,7 +299,7 @@ pub enum LabelText<'a> {
/// to break a line (centering the line preceding the `\n`), there
/// are also the escape sequences `\l` which left-justifies the
/// preceding line and `\r` which right-justifies it.
EscStr(str::MaybeOwned<'a>),
EscStr(CowString<'a>),
}
// There is a tension in the design of the labelling API.
@ -339,7 +336,7 @@ pub enum LabelText<'a> {
/// `Id` is a Graphviz `ID`.
pub struct Id<'a> {
name: str::MaybeOwned<'a>,
name: CowString<'a>,
}
impl<'a> Id<'a> {
@ -357,10 +354,10 @@ impl<'a> Id<'a> {
///
/// Passing an invalid string (containing spaces, brackets,
/// quotes, ...) will return an empty `Err` value.
pub fn new<Name:str::IntoMaybeOwned<'a>>(name: Name) -> Result<Id<'a>, ()> {
let name = name.into_maybe_owned();
pub fn new<Name: IntoCow<'a, String, str>>(name: Name) -> Result<Id<'a>, ()> {
let name = name.into_cow();
{
let mut chars = name.as_slice().chars();
let mut chars = name.chars();
match chars.next() {
Some(c) if is_letter_or_underscore(c) => { ; },
_ => return Err(())
@ -383,10 +380,10 @@ impl<'a> Id<'a> {
}
pub fn as_slice(&'a self) -> &'a str {
self.name.as_slice()
&*self.name
}
pub fn name(self) -> str::MaybeOwned<'a> {
pub fn name(self) -> CowString<'a> {
self.name
}
}
@ -421,7 +418,7 @@ pub trait Labeller<'a,N,E> {
/// default is in fact the empty string.
fn edge_label(&'a self, e: &E) -> LabelText<'a> {
let _ignored = e;
LabelStr(str::Slice(""))
LabelStr("".into_cow())
}
}
@ -454,11 +451,11 @@ impl<'a> LabelText<'a> {
/// yields same content as self. The result obeys the law
/// render(`lt`) == render(`EscStr(lt.pre_escaped_content())`) for
/// all `lt: LabelText`.
fn pre_escaped_content(self) -> str::MaybeOwned<'a> {
fn pre_escaped_content(self) -> CowString<'a> {
match self {
EscStr(s) => s,
LabelStr(s) => if s.as_slice().contains_char('\\') {
str::Owned(s.as_slice().escape_default())
LabelStr(s) => if s.contains_char('\\') {
s.escape_default().into_cow()
} else {
s
},
@ -476,12 +473,12 @@ impl<'a> LabelText<'a> {
let suffix = suffix.pre_escaped_content();
prefix.push_str(r"\n\n");
prefix.push_str(suffix.as_slice());
EscStr(str::Owned(prefix))
EscStr(prefix.into_cow())
}
}
pub type Nodes<'a,N> = MaybeOwnedVector<'a,N>;
pub type Edges<'a,E> = MaybeOwnedVector<'a,E>;
pub type Nodes<'a,N> = CowVec<'a,N>;
pub type Edges<'a,E> = CowVec<'a,E>;
// (The type parameters in GraphWalk should be associated items,
// when/if Rust supports such.)
@ -496,7 +493,7 @@ pub type Edges<'a,E> = MaybeOwnedVector<'a,E>;
/// that is bound by the self lifetime `'a`.
///
/// The `nodes` and `edges` method each return instantiations of
/// `MaybeOwnedVector` to leave implementers the freedom to create
/// `CowVec` to leave implementers the freedom to create
/// entirely new vectors or to pass back slices into internally owned
/// vectors.
pub trait GraphWalk<'a, N, E> {
@ -512,7 +509,7 @@ pub trait GraphWalk<'a, N, E> {
/// Renders directed graph `g` into the writer `w` in DOT syntax.
/// (Main entry point for the library.)
pub fn render<'a, N:'a, E:'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>(
pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>(
g: &'a G,
w: &mut W) -> io::IoResult<()>
{
@ -647,12 +644,12 @@ mod tests {
}
fn node_label(&'a self, n: &Node) -> LabelText<'a> {
match self.node_labels[*n] {
Some(ref l) => LabelStr(str::Slice(l.as_slice())),
Some(ref l) => LabelStr(l.into_cow()),
None => LabelStr(id_name(n).name()),
}
}
fn edge_label(&'a self, e: & &'a Edge) -> LabelText<'a> {
LabelStr(str::Slice(e.label.as_slice()))
LabelStr(e.label.into_cow())
}
}

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![deprecated = "use std::vec::CowVec"]
pub use self::MaybeOwnedVector::*;
use std::default::Default;
@ -46,12 +48,16 @@ pub trait IntoMaybeOwnedVector<'a,T> {
fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T>;
}
#[allow(deprecated)]
impl<'a,T:'a> IntoMaybeOwnedVector<'a,T> for Vec<T> {
#[allow(deprecated)]
#[inline]
fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) }
}
#[allow(deprecated)]
impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T] {
#[allow(deprecated)]
#[inline]
fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Borrowed(self) }
}
@ -66,6 +72,7 @@ impl<'a,T> MaybeOwnedVector<'a,T> {
pub fn len(&self) -> uint { self.as_slice().len() }
#[allow(deprecated)]
pub fn is_empty(&self) -> bool { self.len() == 0 }
}
@ -114,6 +121,7 @@ impl<'b,T> AsSlice<T> for MaybeOwnedVector<'b,T> {
}
impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> {
#[allow(deprecated)]
fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<'a,T> {
// If we are building from scratch, might as well build the
// most flexible variant.
@ -143,6 +151,7 @@ impl<'a,T:Clone> CloneSliceAllocPrelude<T> for MaybeOwnedVector<'a,T> {
}
impl<'a, T: Clone> Clone for MaybeOwnedVector<'a, T> {
#[allow(deprecated)]
fn clone(&self) -> MaybeOwnedVector<'a, T> {
match *self {
Growable(ref v) => Growable(v.clone()),
@ -152,6 +161,7 @@ impl<'a, T: Clone> Clone for MaybeOwnedVector<'a, T> {
}
impl<'a, T> Default for MaybeOwnedVector<'a, T> {
#[allow(deprecated)]
fn default() -> MaybeOwnedVector<'a, T> {
Growable(Vec::new())
}

View File

@ -13,7 +13,7 @@ pub use self::Regex::*;
use std::collections::HashMap;
use std::fmt;
use std::str::{MaybeOwned, Owned, Slice};
use std::str::CowString;
use compile::Program;
use parse;
@ -565,25 +565,25 @@ pub trait Replacer {
///
/// The `'a` lifetime refers to the lifetime of a borrowed string when
/// a new owned string isn't needed (e.g., for `NoExpand`).
fn reg_replace<'a>(&'a mut self, caps: &Captures) -> MaybeOwned<'a>;
fn reg_replace<'a>(&'a mut self, caps: &Captures) -> CowString<'a>;
}
impl<'t> Replacer for NoExpand<'t> {
fn reg_replace<'a>(&'a mut self, _: &Captures) -> MaybeOwned<'a> {
fn reg_replace<'a>(&'a mut self, _: &Captures) -> CowString<'a> {
let NoExpand(s) = *self;
Slice(s)
s.into_cow()
}
}
impl<'t> Replacer for &'t str {
fn reg_replace<'a>(&'a mut self, caps: &Captures) -> MaybeOwned<'a> {
Owned(caps.expand(*self))
fn reg_replace<'a>(&'a mut self, caps: &Captures) -> CowString<'a> {
caps.expand(*self).into_cow()
}
}
impl<'t> Replacer for |&Captures|: 't -> String {
fn reg_replace<'a>(&'a mut self, caps: &Captures) -> MaybeOwned<'a> {
Owned((*self)(caps))
fn reg_replace<'a>(&'a mut self, caps: &Captures) -> CowString<'a> {
(*self)(caps).into_cow()
}
}

View File

@ -26,7 +26,6 @@ use middle::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit};
use middle::dataflow;
use std::rc::Rc;
use std::str;
#[deriving(Show)]
pub enum Variant {
@ -137,8 +136,8 @@ impl<'a, 'tcx> dot::Labeller<'a, Node<'a>, Edge<'a>> for DataflowLabeller<'a, 't
let suffix = self.dataflow_for(dataflow::Exit, n);
let inner_label = self.inner.node_label(n);
inner_label
.prefix_line(dot::LabelStr(str::Owned(prefix)))
.suffix_line(dot::LabelStr(str::Owned(suffix)))
.prefix_line(dot::LabelStr(prefix.into_cow()))
.suffix_line(dot::LabelStr(suffix.into_cow()))
}
fn edge_label(&'a self, e: &Edge<'a>) -> dot::LabelText<'a> { self.inner.edge_label(e) }
}

View File

@ -58,16 +58,16 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> {
if i == self.cfg.entry {
dot::LabelStr("entry".into_maybe_owned())
dot::LabelStr("entry".into_cow())
} else if i == self.cfg.exit {
dot::LabelStr("exit".into_maybe_owned())
dot::LabelStr("exit".into_cow())
} else if n.data.id == ast::DUMMY_NODE_ID {
dot::LabelStr("(dummy_node)".into_maybe_owned())
dot::LabelStr("(dummy_node)".into_cow())
} else {
let s = self.ast_map.node_to_string(n.data.id);
// left-aligns the lines
let s = replace_newline_with_backslash_l(s);
dot::EscStr(s.into_maybe_owned())
dot::EscStr(s.into_cow())
}
}
@ -86,7 +86,7 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
label.push_str(format!("exiting scope_{} {}", i,
s.as_slice()).as_slice());
}
dot::EscStr(label.into_maybe_owned())
dot::EscStr(label.into_cow())
}
}
@ -94,7 +94,7 @@ impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG {
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> {
let mut v = Vec::new();
self.graph.each_node(|i, nd| { v.push((i, nd)); true });
dot::maybe_owned_vec::Growable(v)
v.into_cow()
}
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
self.graph.all_edges().iter().collect()

View File

@ -74,7 +74,7 @@ use fmt;
use iter::Iterator;
use option::{Option, None, Some};
use str;
use str::{MaybeOwned, Str, StrPrelude};
use str::{CowString, MaybeOwned, Str, StrPrelude};
use string::String;
use slice::{AsSlice, CloneSliceAllocPrelude};
use slice::{PartialEqSlicePrelude, SlicePrelude};
@ -830,7 +830,7 @@ pub struct Display<'a, P:'a> {
impl<'a, P: GenericPath> fmt::Show for Display<'a, P> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.as_maybe_owned().as_slice().fmt(f)
self.as_cow().fmt(f)
}
}
@ -840,7 +840,7 @@ impl<'a, P: GenericPath> Display<'a, P> {
/// If the path is not UTF-8, invalid sequences will be replaced with the
/// Unicode replacement char. This involves allocation.
#[inline]
pub fn as_maybe_owned(&self) -> MaybeOwned<'a> {
pub fn as_cow(&self) -> CowString<'a> {
String::from_utf8_lossy(if self.filename {
match self.path.filename() {
None => {

View File

@ -551,14 +551,14 @@ mod tests {
($path:expr, $exp:expr) => (
{
let path = Path::new($path);
let mo = path.display().as_maybe_owned();
let mo = path.display().as_cow();
assert!(mo.as_slice() == $exp);
}
);
($path:expr, $exp:expr, filename) => (
{
let path = Path::new($path);
let mo = path.filename_display().as_maybe_owned();
let mo = path.filename_display().as_cow();
assert!(mo.as_slice() == $exp);
}
)

View File

@ -1326,10 +1326,10 @@ mod tests {
assert_eq!(path.filename_display().to_string(), "".to_string());
let path = Path::new("foo");
let mo = path.display().as_maybe_owned();
let mo = path.display().as_cow();
assert_eq!(mo.as_slice(), "foo");
let path = Path::new(b"\\");
let mo = path.filename_display().as_maybe_owned();
let mo = path.filename_display().as_cow();
assert_eq!(mo.as_slice(), "");
}

View File

@ -58,6 +58,7 @@
#[doc(no_inline)] pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
#[doc(no_inline)] pub use ascii::IntoBytes;
#[doc(no_inline)] pub use borrow::IntoCow;
#[doc(no_inline)] pub use c_str::ToCStr;
#[doc(no_inline)] pub use char::{Char, UnicodeChar};
#[doc(no_inline)] pub use clone::Clone;
@ -78,7 +79,7 @@
#[doc(no_inline)] pub use result::Result::{Ok, Err};
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude};
#[doc(no_inline)] pub use str::{Str, StrVector, StrPrelude};
#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrPrelude};
#[doc(no_inline)] pub use str::{StrAllocating, UnicodeStrPrelude};
#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};

View File

@ -56,6 +56,7 @@ Several modules in `core` are clients of `rt`:
#![allow(dead_code)]
use borrow::IntoCow;
use failure;
use rustrt;
use os;
@ -113,7 +114,6 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
use prelude::*;
use rt;
use rustrt::task::Task;
use str;
let something_around_the_top_of_the_stack = 1;
let addr = &something_around_the_top_of_the_stack as *const int;
@ -147,7 +147,7 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
let mut main = Some(main);
let mut task = box Task::new(Some((my_stack_bottom, my_stack_top)),
Some(rustrt::thread::main_guard_page()));
task.name = Some(str::Slice("<main>"));
task.name = Some("<main>".into_cow());
drop(task.run(|| {
unsafe {
rustrt::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);

View File

@ -44,16 +44,17 @@
will likely be renamed from `task` to `thread`."]
use any::Any;
use borrow::IntoCow;
use boxed::Box;
use comm::channel;
use io::{Writer, stdio};
use kinds::{Send, marker};
use option::{None, Some, Option};
use boxed::Box;
use result::Result;
use rustrt::local::Local;
use rustrt::task;
use rustrt::task::Task;
use str::{Str, SendStr, IntoMaybeOwned};
use rustrt::task;
use str::{Str, SendStr};
use string::{String, ToString};
use sync::Future;
@ -101,8 +102,8 @@ impl TaskBuilder {
/// Name the task-to-be. Currently the name is used for identification
/// only in panic messages.
#[unstable = "IntoMaybeOwned will probably change."]
pub fn named<T: IntoMaybeOwned<'static>>(mut self, name: T) -> TaskBuilder {
self.name = Some(name.into_maybe_owned());
pub fn named<T: IntoCow<'static, String, str>>(mut self, name: T) -> TaskBuilder {
self.name = Some(name.into_cow());
self
}
@ -264,12 +265,13 @@ pub fn failing() -> bool {
#[cfg(test)]
mod test {
use any::{Any, AnyRefExt};
use borrow::IntoCow;
use boxed::BoxAny;
use result;
use result::{Ok, Err};
use string::String;
use std::io::{ChanReader, ChanWriter};
use prelude::*;
use result::{Ok, Err};
use result;
use std::io::{ChanReader, ChanWriter};
use string::String;
use super::*;
// !!! These tests are dangerous. If something is buggy, they will hang, !!!
@ -298,7 +300,7 @@ mod test {
#[test]
fn test_send_named_task() {
TaskBuilder::new().named("ada lovelace".into_maybe_owned()).try(proc() {
TaskBuilder::new().named("ada lovelace".into_cow()).try(proc() {
assert!(name().unwrap() == "ada lovelace".to_string());
}).map_err(|_| ()).unwrap();
}

View File

@ -272,13 +272,13 @@ impl<'a> StringReader<'a> {
/// Converts CRLF to LF in the given string, raising an error on bare CR.
fn translate_crlf<'a>(&self, start: BytePos,
s: &'a str, errmsg: &'a str) -> str::MaybeOwned<'a> {
s: &'a str, errmsg: &'a str) -> str::CowString<'a> {
let mut i = 0u;
while i < s.len() {
let str::CharRange { ch, next } = s.char_range_at(i);
if ch == '\r' {
if next < s.len() && s.char_at(next) == '\n' {
return translate_crlf_(self, start, s, errmsg, i).into_maybe_owned();
return translate_crlf_(self, start, s, errmsg, i).into_cow();
}
let pos = start + BytePos(i as u32);
let end_pos = start + BytePos(next as u32);
@ -286,7 +286,7 @@ impl<'a> StringReader<'a> {
}
i = next;
}
return s.into_maybe_owned();
return s.into_cow();
fn translate_crlf_(rdr: &StringReader, start: BytePos,
s: &str, errmsg: &str, mut i: uint) -> String {
@ -550,7 +550,7 @@ impl<'a> StringReader<'a> {
let string = if has_cr {
self.translate_crlf(start_bpos, string,
"bare CR not allowed in block doc-comment")
} else { string.into_maybe_owned() };
} else { string.into_cow() };
token::DocComment(token::intern(string.as_slice()))
} else {
token::Comment

View File

@ -4966,10 +4966,10 @@ impl<'a> Parser<'a> {
let mut err = String::from_str("circular modules: ");
let len = included_mod_stack.len();
for p in included_mod_stack.slice(i, len).iter() {
err.push_str(p.display().as_maybe_owned().as_slice());
err.push_str(p.display().as_cow().as_slice());
err.push_str(" -> ");
}
err.push_str(path.display().as_maybe_owned().as_slice());
err.push_str(path.display().as_cow().as_slice());
self.span_fatal(id_sp, err.as_slice());
}
None => ()

View File

@ -12,7 +12,7 @@
fn main() {
let r: Result<int,_> =
::std::task::TaskBuilder::new().named("send name".into_maybe_owned())
::std::task::TaskBuilder::new().named("send name".into_cow())
.try(proc() {
panic!("test");
3i

View File

@ -10,51 +10,51 @@
extern crate collections;
use std::str::{SendStr, Owned, Slice};
use std::collections::HashMap;
use std::option::Some;
use std::str::SendStr;
pub fn main() {
let mut map: HashMap<SendStr, uint> = HashMap::new();
assert!(map.insert(Slice("foo"), 42).is_none());
assert!(map.insert(Owned("foo".to_string()), 42).is_some());
assert!(map.insert(Slice("foo"), 42).is_some());
assert!(map.insert(Owned("foo".to_string()), 42).is_some());
assert!(map.insert("foo".into_cow(), 42).is_none());
assert!(map.insert("foo".to_string().into_cow(), 42).is_some());
assert!(map.insert("foo".into_cow(), 42).is_some());
assert!(map.insert("foo".to_string().into_cow(), 42).is_some());
assert!(map.insert(Slice("foo"), 43).is_some());
assert!(map.insert(Owned("foo".to_string()), 44).is_some());
assert!(map.insert(Slice("foo"), 45).is_some());
assert!(map.insert(Owned("foo".to_string()), 46).is_some());
assert!(map.insert("foo".into_cow(), 43).is_some());
assert!(map.insert("foo".to_string().into_cow(), 44).is_some());
assert!(map.insert("foo".into_cow(), 45).is_some());
assert!(map.insert("foo".to_string().into_cow(), 46).is_some());
let v = 46;
assert_eq!(map.get(&Owned("foo".to_string())), Some(&v));
assert_eq!(map.get(&Slice("foo")), Some(&v));
assert_eq!(map.get(&"foo".to_string().into_cow()), Some(&v));
assert_eq!(map.get(&"foo".into_cow()), Some(&v));
let (a, b, c, d) = (50, 51, 52, 53);
assert!(map.insert(Slice("abc"), a).is_none());
assert!(map.insert(Owned("bcd".to_string()), b).is_none());
assert!(map.insert(Slice("cde"), c).is_none());
assert!(map.insert(Owned("def".to_string()), d).is_none());
assert!(map.insert("abc".into_cow(), a).is_none());
assert!(map.insert("bcd".to_string().into_cow(), b).is_none());
assert!(map.insert("cde".into_cow(), c).is_none());
assert!(map.insert("def".to_string().into_cow(), d).is_none());
assert!(map.insert(Slice("abc"), a).is_some());
assert!(map.insert(Owned("bcd".to_string()), b).is_some());
assert!(map.insert(Slice("cde"), c).is_some());
assert!(map.insert(Owned("def".to_string()), d).is_some());
assert!(map.insert("abc".into_cow(), a).is_some());
assert!(map.insert("bcd".to_string().into_cow(), b).is_some());
assert!(map.insert("cde".into_cow(), c).is_some());
assert!(map.insert("def".to_string().into_cow(), d).is_some());
assert!(map.insert(Owned("abc".to_string()), a).is_some());
assert!(map.insert(Slice("bcd"), b).is_some());
assert!(map.insert(Owned("cde".to_string()), c).is_some());
assert!(map.insert(Slice("def"), d).is_some());
assert!(map.insert("abc".to_string().into_cow(), a).is_some());
assert!(map.insert("bcd".into_cow(), b).is_some());
assert!(map.insert("cde".to_string().into_cow(), c).is_some());
assert!(map.insert("def".into_cow(), d).is_some());
assert_eq!(map.find_equiv("abc"), Some(&a));
assert_eq!(map.find_equiv("bcd"), Some(&b));
assert_eq!(map.find_equiv("cde"), Some(&c));
assert_eq!(map.find_equiv("def"), Some(&d));
assert_eq!(map.get("abc"), Some(&a));
assert_eq!(map.get("bcd"), Some(&b));
assert_eq!(map.get("cde"), Some(&c));
assert_eq!(map.get("def"), Some(&d));
assert_eq!(map.find_equiv(&Slice("abc")), Some(&a));
assert_eq!(map.find_equiv(&Slice("bcd")), Some(&b));
assert_eq!(map.find_equiv(&Slice("cde")), Some(&c));
assert_eq!(map.find_equiv(&Slice("def")), Some(&d));
assert_eq!(map.get(&"abc".into_cow()), Some(&a));
assert_eq!(map.get(&"bcd".into_cow()), Some(&b));
assert_eq!(map.get(&"cde".into_cow()), Some(&c));
assert_eq!(map.get(&"def".into_cow()), Some(&d));
}

View File

@ -10,56 +10,56 @@
extern crate collections;
use std::str::{SendStr, Owned, Slice};
use std::string::ToString;
use self::collections::TreeMap;
use std::option::Some;
use std::str::SendStr;
use std::string::ToString;
pub fn main() {
let mut map: TreeMap<SendStr, uint> = TreeMap::new();
assert!(map.insert(Slice("foo"), 42).is_none());
assert!(map.insert(Owned("foo".to_string()), 42).is_some());
assert!(map.insert(Slice("foo"), 42).is_some());
assert!(map.insert(Owned("foo".to_string()), 42).is_some());
assert!(map.insert("foo".into_cow(), 42).is_none());
assert!(map.insert("foo".to_string().into_cow(), 42).is_some());
assert!(map.insert("foo".into_cow(), 42).is_some());
assert!(map.insert("foo".to_string().into_cow(), 42).is_some());
assert!(map.insert(Slice("foo"), 43).is_some());
assert!(map.insert(Owned("foo".to_string()), 44).is_some());
assert!(map.insert(Slice("foo"), 45).is_some());
assert!(map.insert(Owned("foo".to_string()), 46).is_some());
assert!(map.insert("foo".into_cow(), 43).is_some());
assert!(map.insert("foo".to_string().into_cow(), 44).is_some());
assert!(map.insert("foo".into_cow(), 45).is_some());
assert!(map.insert("foo".to_string().into_cow(), 46).is_some());
let v = 46;
assert_eq!(map.get(&Owned("foo".to_string())), Some(&v));
assert_eq!(map.get(&Slice("foo")), Some(&v));
assert_eq!(map.get(&"foo".to_string().into_cow()), Some(&v));
assert_eq!(map.get(&"foo".into_cow()), Some(&v));
let (a, b, c, d) = (50, 51, 52, 53);
assert!(map.insert(Slice("abc"), a).is_none());
assert!(map.insert(Owned("bcd".to_string()), b).is_none());
assert!(map.insert(Slice("cde"), c).is_none());
assert!(map.insert(Owned("def".to_string()), d).is_none());
assert!(map.insert("abc".into_cow(), a).is_none());
assert!(map.insert("bcd".to_string().into_cow(), b).is_none());
assert!(map.insert("cde".into_cow(), c).is_none());
assert!(map.insert("def".to_string().into_cow(), d).is_none());
assert!(map.insert(Slice("abc"), a).is_some());
assert!(map.insert(Owned("bcd".to_string()), b).is_some());
assert!(map.insert(Slice("cde"), c).is_some());
assert!(map.insert(Owned("def".to_string()), d).is_some());
assert!(map.insert("abc".into_cow(), a).is_some());
assert!(map.insert("bcd".to_string().into_cow(), b).is_some());
assert!(map.insert("cde".into_cow(), c).is_some());
assert!(map.insert("def".to_string().into_cow(), d).is_some());
assert!(map.insert(Owned("abc".to_string()), a).is_some());
assert!(map.insert(Slice("bcd"), b).is_some());
assert!(map.insert(Owned("cde".to_string()), c).is_some());
assert!(map.insert(Slice("def"), d).is_some());
assert!(map.insert("abc".to_string().into_cow(), a).is_some());
assert!(map.insert("bcd".into_cow(), b).is_some());
assert!(map.insert("cde".to_string().into_cow(), c).is_some());
assert!(map.insert("def".into_cow(), d).is_some());
assert_eq!(map.get(&Slice("abc")), Some(&a));
assert_eq!(map.get(&Slice("bcd")), Some(&b));
assert_eq!(map.get(&Slice("cde")), Some(&c));
assert_eq!(map.get(&Slice("def")), Some(&d));
assert_eq!(map.get(&"abc".into_cow()), Some(&a));
assert_eq!(map.get(&"bcd".into_cow()), Some(&b));
assert_eq!(map.get(&"cde".into_cow()), Some(&c));
assert_eq!(map.get(&"def".into_cow()), Some(&d));
assert_eq!(map.get(&Owned("abc".to_string())), Some(&a));
assert_eq!(map.get(&Owned("bcd".to_string())), Some(&b));
assert_eq!(map.get(&Owned("cde".to_string())), Some(&c));
assert_eq!(map.get(&Owned("def".to_string())), Some(&d));
assert_eq!(map.get(&"abc".to_string().into_cow()), Some(&a));
assert_eq!(map.get(&"bcd".to_string().into_cow()), Some(&b));
assert_eq!(map.get(&"cde".to_string().into_cow()), Some(&c));
assert_eq!(map.get(&"def".to_string().into_cow()), Some(&d));
assert!(map.remove(&Slice("foo")).is_some());
assert!(map.remove(&"foo".into_cow()).is_some());
assert_eq!(map.into_iter().map(|(k, v)| format!("{}{}", k, v))
.collect::<Vec<String>>()
.concat(),