1
Fork 0

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::boxed::Box;
use alloc::rc::Rc; use alloc::rc::Rc;
use core::borrow::{Cow, ToOwned};
use core::intrinsics::TypeId; use core::intrinsics::TypeId;
use core::mem; use core::mem;
use core::num::Int; 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)] #[cfg(test)]

View file

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

View file

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

View file

@ -16,6 +16,7 @@ use core::prelude::*;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
use core::borrow::{Cow, IntoCow};
use core::cmp::max; use core::cmp::max;
use core::default::Default; use core::default::Default;
use core::fmt; use core::fmt;
@ -107,6 +108,27 @@ pub struct Vec<T> {
cap: uint, 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> { impl<T> Vec<T> {
/// Constructs a new, empty `Vec`. /// Constructs a new, empty `Vec`.
/// ///

View file

@ -45,8 +45,11 @@
#![unstable = "recently added as part of collections reform"] #![unstable = "recently added as part of collections reform"]
use clone::Clone; use clone::Clone;
use cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use fmt;
use kinds::Sized; use kinds::Sized;
use ops::Deref; use ops::Deref;
use option::Option;
use self::Cow::*; use self::Cow::*;
/// A trait for borrowing data. /// 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 } 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. /// A generalization of Clone to borrowed data.
pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> { pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
/// Create owned data from borrowed data, usually by copying. /// 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 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> { 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, Each node label is derived directly from the int representing the node,
while the edge labels are all empty strings. 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 an owned vector or a borrowed slice as appropriate: we construct the
node vector from scratch, but borrow the edge list (rather than node vector from scratch, but borrow the edge list (rather than
constructing a copy of all the edges from scratch). constructing a copy of all the edges from scratch).
@ -48,7 +48,6 @@ which is cyclic.
```rust ```rust
use graphviz as dot; use graphviz as dot;
use graphviz::maybe_owned_vec::IntoMaybeOwnedVector;
type Nd = int; type Nd = int;
type Ed = (int,int); type Ed = (int,int);
@ -77,12 +76,12 @@ impl<'a> dot::GraphWalk<'a, Nd, Ed> for Edges {
} }
nodes.sort(); nodes.sort();
nodes.dedup(); nodes.dedup();
nodes.into_maybe_owned() nodes.into_cow()
} }
fn edges(&'a self) -> dot::Edges<'a,Ed> { fn edges(&'a self) -> dot::Edges<'a,Ed> {
let &Edges(ref edges) = self; 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 } 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 Since both the set of nodes and the set of edges are always
constructed from scratch via iterators, we use the `collect()` method constructed from scratch via iterators, we use the `collect()` method
from the `Iterator` trait to collect the nodes and edges into freshly from the `Iterator` trait to collect the nodes and edges into freshly
constructed growable `Vec` values (rather use the `into_maybe_owned` constructed growable `Vec` values (rather use the `into_cow`
from the `IntoMaybeOwnedVector` trait as was used in the first example from the `IntoCow` trait as was used in the first example
above). above).
The output from this example renders four nodes that make up the The output from this example renders four nodes that make up the
@ -148,7 +147,6 @@ entity `&sube`).
```rust ```rust
use graphviz as dot; use graphviz as dot;
use std::str;
type Nd = uint; type Nd = uint;
type Ed<'a> = &'a (uint, 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() dot::Id::new(format!("N{}", n)).unwrap()
} }
fn node_label<'a>(&'a self, n: &Nd) -> dot::LabelText<'a> { 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> { 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 ```rust
use graphviz as dot; use graphviz as dot;
use std::str;
type Nd<'a> = (uint, &'a str); type Nd<'a> = (uint, &'a str);
type Ed<'a> = (Nd<'a>, Nd<'a>); 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> { fn node_label<'a>(&'a self, n: &Nd<'a>) -> dot::LabelText<'a> {
let &(i, _) = n; 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> { 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::*; pub use self::LabelText::*;
use std::io; use std::io;
use std::str; use std::str::CowString;
use self::maybe_owned_vec::MaybeOwnedVector; use std::vec::CowVec;
pub mod maybe_owned_vec; pub mod maybe_owned_vec;
@ -290,7 +287,7 @@ pub enum LabelText<'a> {
/// ///
/// Occurrences of backslashes (`\`) are escaped, and thus appear /// Occurrences of backslashes (`\`) are escaped, and thus appear
/// as backslashes in the rendered label. /// as backslashes in the rendered label.
LabelStr(str::MaybeOwned<'a>), LabelStr(CowString<'a>),
/// This kind of label uses the graphviz label escString type: /// This kind of label uses the graphviz label escString type:
/// http://www.graphviz.org/content/attrs#kescString /// 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 /// to break a line (centering the line preceding the `\n`), there
/// are also the escape sequences `\l` which left-justifies the /// are also the escape sequences `\l` which left-justifies the
/// preceding line and `\r` which right-justifies it. /// 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. // There is a tension in the design of the labelling API.
@ -339,7 +336,7 @@ pub enum LabelText<'a> {
/// `Id` is a Graphviz `ID`. /// `Id` is a Graphviz `ID`.
pub struct Id<'a> { pub struct Id<'a> {
name: str::MaybeOwned<'a>, name: CowString<'a>,
} }
impl<'a> Id<'a> { impl<'a> Id<'a> {
@ -357,10 +354,10 @@ impl<'a> Id<'a> {
/// ///
/// Passing an invalid string (containing spaces, brackets, /// Passing an invalid string (containing spaces, brackets,
/// quotes, ...) will return an empty `Err` value. /// quotes, ...) will return an empty `Err` value.
pub fn new<Name:str::IntoMaybeOwned<'a>>(name: Name) -> Result<Id<'a>, ()> { pub fn new<Name: IntoCow<'a, String, str>>(name: Name) -> Result<Id<'a>, ()> {
let name = name.into_maybe_owned(); let name = name.into_cow();
{ {
let mut chars = name.as_slice().chars(); let mut chars = name.chars();
match chars.next() { match chars.next() {
Some(c) if is_letter_or_underscore(c) => { ; }, Some(c) if is_letter_or_underscore(c) => { ; },
_ => return Err(()) _ => return Err(())
@ -383,10 +380,10 @@ impl<'a> Id<'a> {
} }
pub fn as_slice(&'a self) -> &'a str { 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 self.name
} }
} }
@ -421,7 +418,7 @@ pub trait Labeller<'a,N,E> {
/// default is in fact the empty string. /// default is in fact the empty string.
fn edge_label(&'a self, e: &E) -> LabelText<'a> { fn edge_label(&'a self, e: &E) -> LabelText<'a> {
let _ignored = e; 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 /// yields same content as self. The result obeys the law
/// render(`lt`) == render(`EscStr(lt.pre_escaped_content())`) for /// render(`lt`) == render(`EscStr(lt.pre_escaped_content())`) for
/// all `lt: LabelText`. /// all `lt: LabelText`.
fn pre_escaped_content(self) -> str::MaybeOwned<'a> { fn pre_escaped_content(self) -> CowString<'a> {
match self { match self {
EscStr(s) => s, EscStr(s) => s,
LabelStr(s) => if s.as_slice().contains_char('\\') { LabelStr(s) => if s.contains_char('\\') {
str::Owned(s.as_slice().escape_default()) s.escape_default().into_cow()
} else { } else {
s s
}, },
@ -476,12 +473,12 @@ impl<'a> LabelText<'a> {
let suffix = suffix.pre_escaped_content(); let suffix = suffix.pre_escaped_content();
prefix.push_str(r"\n\n"); prefix.push_str(r"\n\n");
prefix.push_str(suffix.as_slice()); prefix.push_str(suffix.as_slice());
EscStr(str::Owned(prefix)) EscStr(prefix.into_cow())
} }
} }
pub type Nodes<'a,N> = MaybeOwnedVector<'a,N>; pub type Nodes<'a,N> = CowVec<'a,N>;
pub type Edges<'a,E> = MaybeOwnedVector<'a,E>; pub type Edges<'a,E> = CowVec<'a,E>;
// (The type parameters in GraphWalk should be associated items, // (The type parameters in GraphWalk should be associated items,
// when/if Rust supports such.) // 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`. /// that is bound by the self lifetime `'a`.
/// ///
/// The `nodes` and `edges` method each return instantiations of /// 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 /// entirely new vectors or to pass back slices into internally owned
/// vectors. /// vectors.
pub trait GraphWalk<'a, N, E> { 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. /// Renders directed graph `g` into the writer `w` in DOT syntax.
/// (Main entry point for the library.) /// (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, g: &'a G,
w: &mut W) -> io::IoResult<()> w: &mut W) -> io::IoResult<()>
{ {
@ -647,12 +644,12 @@ mod tests {
} }
fn node_label(&'a self, n: &Node) -> LabelText<'a> { fn node_label(&'a self, n: &Node) -> LabelText<'a> {
match self.node_labels[*n] { 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()), None => LabelStr(id_name(n).name()),
} }
} }
fn edge_label(&'a self, e: & &'a Edge) -> LabelText<'a> { 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 // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![deprecated = "use std::vec::CowVec"]
pub use self::MaybeOwnedVector::*; pub use self::MaybeOwnedVector::*;
use std::default::Default; use std::default::Default;
@ -46,12 +48,16 @@ pub trait IntoMaybeOwnedVector<'a,T> {
fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T>; fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T>;
} }
#[allow(deprecated)]
impl<'a,T:'a> IntoMaybeOwnedVector<'a,T> for Vec<T> { impl<'a,T:'a> IntoMaybeOwnedVector<'a,T> for Vec<T> {
#[allow(deprecated)]
#[inline] #[inline]
fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) } fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) }
} }
#[allow(deprecated)]
impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T] { impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T] {
#[allow(deprecated)]
#[inline] #[inline]
fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Borrowed(self) } 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() } pub fn len(&self) -> uint { self.as_slice().len() }
#[allow(deprecated)]
pub fn is_empty(&self) -> bool { self.len() == 0 } 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> { impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> {
#[allow(deprecated)]
fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<'a,T> { fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<'a,T> {
// If we are building from scratch, might as well build the // If we are building from scratch, might as well build the
// most flexible variant. // 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> { impl<'a, T: Clone> Clone for MaybeOwnedVector<'a, T> {
#[allow(deprecated)]
fn clone(&self) -> MaybeOwnedVector<'a, T> { fn clone(&self) -> MaybeOwnedVector<'a, T> {
match *self { match *self {
Growable(ref v) => Growable(v.clone()), 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> { impl<'a, T> Default for MaybeOwnedVector<'a, T> {
#[allow(deprecated)]
fn default() -> MaybeOwnedVector<'a, T> { fn default() -> MaybeOwnedVector<'a, T> {
Growable(Vec::new()) Growable(Vec::new())
} }

View file

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

View file

@ -26,7 +26,6 @@ use middle::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit};
use middle::dataflow; use middle::dataflow;
use std::rc::Rc; use std::rc::Rc;
use std::str;
#[deriving(Show)] #[deriving(Show)]
pub enum Variant { 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 suffix = self.dataflow_for(dataflow::Exit, n);
let inner_label = self.inner.node_label(n); let inner_label = self.inner.node_label(n);
inner_label inner_label
.prefix_line(dot::LabelStr(str::Owned(prefix))) .prefix_line(dot::LabelStr(prefix.into_cow()))
.suffix_line(dot::LabelStr(str::Owned(suffix))) .suffix_line(dot::LabelStr(suffix.into_cow()))
} }
fn edge_label(&'a self, e: &Edge<'a>) -> dot::LabelText<'a> { self.inner.edge_label(e) } 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> { fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> {
if i == self.cfg.entry { if i == self.cfg.entry {
dot::LabelStr("entry".into_maybe_owned()) dot::LabelStr("entry".into_cow())
} else if i == self.cfg.exit { } 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 { } else if n.data.id == ast::DUMMY_NODE_ID {
dot::LabelStr("(dummy_node)".into_maybe_owned()) dot::LabelStr("(dummy_node)".into_cow())
} else { } else {
let s = self.ast_map.node_to_string(n.data.id); let s = self.ast_map.node_to_string(n.data.id);
// left-aligns the lines // left-aligns the lines
let s = replace_newline_with_backslash_l(s); 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, label.push_str(format!("exiting scope_{} {}", i,
s.as_slice()).as_slice()); 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>> { fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> {
let mut v = Vec::new(); let mut v = Vec::new();
self.graph.each_node(|i, nd| { v.push((i, nd)); true }); 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>> { fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
self.graph.all_edges().iter().collect() self.graph.all_edges().iter().collect()

View file

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

View file

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

View file

@ -1326,10 +1326,10 @@ mod tests {
assert_eq!(path.filename_display().to_string(), "".to_string()); assert_eq!(path.filename_display().to_string(), "".to_string());
let path = Path::new("foo"); let path = Path::new("foo");
let mo = path.display().as_maybe_owned(); let mo = path.display().as_cow();
assert_eq!(mo.as_slice(), "foo"); assert_eq!(mo.as_slice(), "foo");
let path = Path::new(b"\\"); 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(), ""); 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::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
#[doc(no_inline)] pub use ascii::IntoBytes; #[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 c_str::ToCStr;
#[doc(no_inline)] pub use char::{Char, UnicodeChar}; #[doc(no_inline)] pub use char::{Char, UnicodeChar};
#[doc(no_inline)] pub use clone::Clone; #[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 result::Result::{Ok, Err};
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude}; #[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::{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::{Tuple1, Tuple2, Tuple3, Tuple4};
#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8}; #[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12}; #[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)] #![allow(dead_code)]
use borrow::IntoCow;
use failure; use failure;
use rustrt; use rustrt;
use os; use os;
@ -113,7 +114,6 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
use prelude::*; use prelude::*;
use rt; use rt;
use rustrt::task::Task; use rustrt::task::Task;
use str;
let something_around_the_top_of_the_stack = 1; let something_around_the_top_of_the_stack = 1;
let addr = &something_around_the_top_of_the_stack as *const int; 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 main = Some(main);
let mut task = box Task::new(Some((my_stack_bottom, my_stack_top)), let mut task = box Task::new(Some((my_stack_bottom, my_stack_top)),
Some(rustrt::thread::main_guard_page())); Some(rustrt::thread::main_guard_page()));
task.name = Some(str::Slice("<main>")); task.name = Some("<main>".into_cow());
drop(task.run(|| { drop(task.run(|| {
unsafe { unsafe {
rustrt::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top); 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`."] will likely be renamed from `task` to `thread`."]
use any::Any; use any::Any;
use borrow::IntoCow;
use boxed::Box;
use comm::channel; use comm::channel;
use io::{Writer, stdio}; use io::{Writer, stdio};
use kinds::{Send, marker}; use kinds::{Send, marker};
use option::{None, Some, Option}; use option::{None, Some, Option};
use boxed::Box;
use result::Result; use result::Result;
use rustrt::local::Local; use rustrt::local::Local;
use rustrt::task;
use rustrt::task::Task; use rustrt::task::Task;
use str::{Str, SendStr, IntoMaybeOwned}; use rustrt::task;
use str::{Str, SendStr};
use string::{String, ToString}; use string::{String, ToString};
use sync::Future; use sync::Future;
@ -101,8 +102,8 @@ impl TaskBuilder {
/// Name the task-to-be. Currently the name is used for identification /// Name the task-to-be. Currently the name is used for identification
/// only in panic messages. /// only in panic messages.
#[unstable = "IntoMaybeOwned will probably change."] #[unstable = "IntoMaybeOwned will probably change."]
pub fn named<T: IntoMaybeOwned<'static>>(mut self, name: T) -> TaskBuilder { pub fn named<T: IntoCow<'static, String, str>>(mut self, name: T) -> TaskBuilder {
self.name = Some(name.into_maybe_owned()); self.name = Some(name.into_cow());
self self
} }
@ -264,12 +265,13 @@ pub fn failing() -> bool {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use any::{Any, AnyRefExt}; use any::{Any, AnyRefExt};
use borrow::IntoCow;
use boxed::BoxAny; use boxed::BoxAny;
use result;
use result::{Ok, Err};
use string::String;
use std::io::{ChanReader, ChanWriter};
use prelude::*; use prelude::*;
use result::{Ok, Err};
use result;
use std::io::{ChanReader, ChanWriter};
use string::String;
use super::*; use super::*;
// !!! These tests are dangerous. If something is buggy, they will hang, !!! // !!! These tests are dangerous. If something is buggy, they will hang, !!!
@ -298,7 +300,7 @@ mod test {
#[test] #[test]
fn test_send_named_task() { 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()); assert!(name().unwrap() == "ada lovelace".to_string());
}).map_err(|_| ()).unwrap(); }).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. /// Converts CRLF to LF in the given string, raising an error on bare CR.
fn translate_crlf<'a>(&self, start: BytePos, 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; let mut i = 0u;
while i < s.len() { while i < s.len() {
let str::CharRange { ch, next } = s.char_range_at(i); let str::CharRange { ch, next } = s.char_range_at(i);
if ch == '\r' { if ch == '\r' {
if next < s.len() && s.char_at(next) == '\n' { 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 pos = start + BytePos(i as u32);
let end_pos = start + BytePos(next as u32); let end_pos = start + BytePos(next as u32);
@ -286,7 +286,7 @@ impl<'a> StringReader<'a> {
} }
i = next; i = next;
} }
return s.into_maybe_owned(); return s.into_cow();
fn translate_crlf_(rdr: &StringReader, start: BytePos, fn translate_crlf_(rdr: &StringReader, start: BytePos,
s: &str, errmsg: &str, mut i: uint) -> String { s: &str, errmsg: &str, mut i: uint) -> String {
@ -550,7 +550,7 @@ impl<'a> StringReader<'a> {
let string = if has_cr { let string = if has_cr {
self.translate_crlf(start_bpos, string, self.translate_crlf(start_bpos, string,
"bare CR not allowed in block doc-comment") "bare CR not allowed in block doc-comment")
} else { string.into_maybe_owned() }; } else { string.into_cow() };
token::DocComment(token::intern(string.as_slice())) token::DocComment(token::intern(string.as_slice()))
} else { } else {
token::Comment token::Comment

View file

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

View file

@ -12,7 +12,7 @@
fn main() { fn main() {
let r: Result<int,_> = 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() { .try(proc() {
panic!("test"); panic!("test");
3i 3i

View file

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

View file

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