diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index d2bdda83fa998..f01568c90caac 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -2,7 +2,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use core::cmp::Ordering; +use core::cmp::{Ordering, max}; use core::hash::{Hash, Hasher}; use core::ops::{Add, AddAssign, Deref}; @@ -444,6 +444,17 @@ impl<'a> Add> for Cow<'a, str> { } } +#[stable(feature = "cow_str_add_char", since = "1.41.0")] +impl<'a> Add for Cow<'a, str> { + type Output = Cow<'a, str>; + + #[inline] + fn add(mut self, rhs: char) -> Self::Output { + self += rhs; + self + } +} + #[stable(feature = "cow_add", since = "1.14.0")] impl<'a> AddAssign<&'a str> for Cow<'a, str> { fn add_assign(&mut self, rhs: &'a str) { @@ -479,3 +490,18 @@ impl<'a> AddAssign> for Cow<'a, str> { } } } + +#[stable(feature = "cow_str_add_assign_char", since = "1.41.0")] +impl AddAssign for Cow<'_, str> { + fn add_assign(&mut self, rhs: char) { + if let Cow::Borrowed(lhs) = *self { + let base_capacity = lhs.len() + rhs.len_utf8(); + //Attempt amortized memory allocation + let new_optimal_size = max(base_capacity * 2, base_capacity); + let mut s = String::with_capacity(new_optimal_size); + s.push_str(lhs); + *self = Cow::Owned(s); + } + self.to_mut().push(rhs); + } +} diff --git a/src/liballoc/tests/cow_str.rs b/src/liballoc/tests/cow_str.rs index 6f357eda9b83b..c28a8607af71f 100644 --- a/src/liballoc/tests/cow_str.rs +++ b/src/liballoc/tests/cow_str.rs @@ -54,6 +54,20 @@ fn check_cow_add_str() { } } +#[test] +fn check_cow_add_char() { + let test_char = '👋'; + + let borrowed = Cow::Borrowed("Hello, World! "); + + let owned: Cow<'_, str> = Cow::Owned(String::from("Hi, World! ")); + + assert_eq!("Hello, World! 👋", borrowed.clone() + test_char); + + assert_eq!("Hi, World! 👋", owned.clone() + test_char); +} + + #[test] fn check_cow_add_assign_cow() { let mut borrowed1 = Cow::Borrowed("Hello, "); @@ -139,3 +153,18 @@ fn check_cow_clone_from() { c1.clone_from(&c2); assert!(c1.into_owned().capacity() >= 25); } + +#[test] +fn check_cow_add_assign_char() { + let test_char = '👋'; + + let mut borrowed = Cow::Borrowed("Hello, World! "); + + let mut owned: Cow<'_, str> = Cow::Owned(String::from("Hi, World! ")); + + owned += test_char; + borrowed += test_char; + + assert_eq!(format!("Hi, World! {}", test_char), owned); + assert_eq!(format!("Hello, World! {}", test_char), borrowed); +}