diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 700f88dc0f267..6b45c25eb2139 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -14,7 +14,7 @@ use core::cmp::Ordering; use core::hash::{Hash, Hasher}; -use core::ops::Deref; +use core::ops::{Add, AddAssign, Deref}; use fmt; @@ -270,3 +270,49 @@ impl<'a, T: ?Sized + ToOwned> AsRef for Cow<'a, T> { self } } + +#[stable(feature = "cow_add", since = "1.13.0")] +impl<'a> Add<&'a str> for Cow<'a, str> { + type Output = Cow<'a, str>; + + fn add(self, rhs: &'a str) -> Self { + if self == "" { + Cow::Borrowed(rhs) + } else if rhs == "" { + self + } else { + Cow::Owned(self.into_owned() + rhs) + } + } +} + +#[stable(feature = "cow_add", since = "1.13.0")] +impl<'a> Add> for Cow<'a, str> { + type Output = Cow<'a, str>; + + fn add(self, rhs: Cow<'a, str>) -> Self { + if self == "" { + rhs + } else if rhs == "" { + self + } else { + Cow::Owned(self.into_owned() + rhs.borrow()) + } + } +} + +#[stable(feature = "cow_add", since = "1.13.0")] +impl<'a> AddAssign<&'a str> for Cow<'a, str> { + fn add_assign(&mut self, rhs: &'a str) { + if rhs == "" { return; } + self.to_mut().push_str(rhs); + } +} + +#[stable(feature = "cow_add", since = "1.13.0")] +impl<'a> AddAssign> for Cow<'a, str> { + fn add_assign(&mut self, rhs: Cow<'a, str>) { + if rhs == "" { return; } + self.to_mut().push_str(rhs.borrow()); + } +} diff --git a/src/libcollectionstest/cow_str.rs b/src/libcollectionstest/cow_str.rs new file mode 100644 index 0000000000000..82533ba077541 --- /dev/null +++ b/src/libcollectionstest/cow_str.rs @@ -0,0 +1,65 @@ +// Copyright 2012-2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; + +// check that Cow<'a, str> implements addition +#[test] +fn check_cow_add() { + borrowed1 = Cow::Borrowed("Hello, "); + borrowed2 = Cow::Borrowed("World!"); + borrow_empty = Cow::Borrowed(""); + + owned1 = Cow::Owned("Hi, ".into()); + owned2 = Cow::Owned("Rustaceans!".into()); + owned_empty = Cow::Owned("".into()); + + assert_eq!("Hello, World!", borrowed1 + borrowed2); + assert_eq!("Hello, Rustaceans!", borrowed1 + owned2); + + assert_eq!("Hello, World!", owned1 + borrowed2); + assert_eq!("Hello, Rustaceans!", owned1 + owned2); + + if let Cow::Owned(_) = borrowed1 + borrow_empty { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = borrow_empty + borrowed1 { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = borrowed1 + owned_empty { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = owned_empty + borrowed1 { + panic!("Adding empty strings to a borrow should note allocate"); + } +} + +fn check_cow_add_assign() { + borrowed1 = Cow::Borrowed("Hello, "); + borrowed2 = Cow::Borrowed("World!"); + borrow_empty = Cow::Borrowed(""); + + owned1 = Cow::Owned("Hi, ".into()); + owned2 = Cow::Owned("Rustaceans!".into()); + owned_empty = Cow::Owned("".into()); + + let borrowed1clone = borrowed1.clone(); + borrowed1clone += borrow_empty; + assert_eq!((&borrowed1clone).as_ptr(), (&borrowed1).as_ptr()); + + borrowed1clone += owned_empty; + assert_eq!((&borrowed1clone).as_ptr(), (&borrowed1).as_ptr()); + + owned1 += borrowed2; + borrowed1 += owned2; + + assert_eq!("Hello, World!", owned1); + assert_eq!("Hello, Rustaceans!", borrowed1); +}