Skip to content

Deprecate MaybeOwned[Vector] in favor of Cow #19252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 26, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/libcollections/hash/mod.rs
Original file line number Diff line number Diff line change
@@ -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)]
54 changes: 44 additions & 10 deletions src/libcollections/str.rs
Original file line number Diff line number Diff line change
@@ -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,22 +425,24 @@ 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),
/// An owned string.
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,37 +536,44 @@ 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 {
self.as_slice() == other.as_slice()
}
}

#[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> {
Some(self.cmp(other))
}
}

#[deprecated = "use std::str::CowString"]
impl<'a> Ord for MaybeOwned<'a> {
#[inline]
fn cmp(&self, other: &MaybeOwned) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}

#[deprecated = "use std::str::CowString"]
impl<'a, S: Str> Equiv<S> for MaybeOwned<'a> {
#[inline]
fn equiv(&self, other: &S) -> bool {
self.as_slice() == other.as_slice()
}
}

#[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,18 +607,22 @@ 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) {
self.as_slice().hash(hasher)
}
}

#[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
*/
48 changes: 30 additions & 18 deletions src/libcollections/string.rs
Original file line number Diff line number Diff line change
@@ -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]
Loading