Repository: ParkMyCar/compact_str
Pull request #64 (2022-03-01 15:15:13)

feature: impl Extend<Cow<'_, str>> for CompactStr
This PR implements `Extend<Cow<'_, str>>` for `CompactStr`


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c1b98fe7..92f632b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,9 @@
 # Upcoming
+* impl `Extend<Cow<'_, str>>` for `CompactStr`
+    * Implemented in [`#64 feature: impl Extend<Cow<'_, str>> for CompactStr`](https://github.com/ParkMyCar/compact_str/pull/64)
+* impl `From<Cow<'_, str>>` for `CompactStr`
+    * Implemented in [`#62 impl From<Cow<'_, str>> for CompactStr`](https://github.com/ParkMyCar/compact_str/pull/62)
+
 
 # 0.3.0
 ### February 27, 2021
diff --git a/compact_str/src/lib.rs b/compact_str/src/lib.rs
index 29f7c75c..9e464977 100644
--- a/compact_str/src/lib.rs
+++ b/compact_str/src/lib.rs
@@ -532,6 +532,12 @@ impl PartialEq<CompactStr> for &str {
     }
 }
 
+impl<'a> PartialEq<CompactStr> for Cow<'a, str> {
+    fn eq(&self, other: &CompactStr) -> bool {
+        *self == other.as_str()
+    }
+}
+
 impl Ord for CompactStr {
     fn cmp(&self, other: &Self) -> Ordering {
         self.as_str().cmp(other.as_str())
@@ -652,6 +658,12 @@ impl Extend<Box<str>> for CompactStr {
     }
 }
 
+impl<'a> Extend<Cow<'a, str>> for CompactStr {
+    fn extend<T: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: T) {
+        iter.into_iter().for_each(move |s| self.push_str(&s));
+    }
+}
+
 impl Extend<String> for CompactStr {
     fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
         self.repr.extend(iter)
diff --git a/compact_str/src/repr/mod.rs b/compact_str/src/repr/mod.rs
index 55df14b2..c76de896 100644
--- a/compact_str/src/repr/mod.rs
+++ b/compact_str/src/repr/mod.rs
@@ -1,3 +1,4 @@
+use std::borrow::Cow;
 use std::iter::Extend;
 use std::mem::ManuallyDrop;
 use std::str::Utf8Error;
@@ -327,6 +328,12 @@ impl Extend<Box<str>> for Repr {
     }
 }
 
+impl<'a> Extend<Cow<'a, str>> for Repr {
+    fn extend<T: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: T) {
+        iter.into_iter().for_each(move |s| self.push_str(&s));
+    }
+}
+
 impl Extend<String> for Repr {
     fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
         iter.into_iter().for_each(move |s| self.push_str(&s));


Test patch:
diff --git a/compact_str/src/tests.rs b/compact_str/src/tests.rs
index c372767b..1ae7caa0 100644
--- a/compact_str/src/tests.rs
+++ b/compact_str/src/tests.rs
@@ -97,6 +97,22 @@ proptest! {
         }
     }
 
+    #[test]
+    #[cfg_attr(miri, ignore)]
+    fn test_from_lossy_cow_roundtrips(bytes in proptest::collection::vec(any::<u8>(), 0..80)) {
+        let cow = String::from_utf8_lossy(&bytes[..]);
+        let compact = CompactStr::from(cow.clone());
+        prop_assert_eq!(cow, compact);
+    }
+
+    #[test]
+    #[cfg_attr(miri, ignore)]
+    fn test_from_lossy_cow_allocated_properly(bytes in proptest::collection::vec(any::<u8>(), 0..80)) {
+        let cow = String::from_utf8_lossy(&bytes[..]);
+        let compact = CompactStr::from(cow);
+        assert_allocated_properly(&compact);
+    }
+
     #[test]
     #[cfg_attr(miri, ignore)]
     fn test_reserve_and_write_bytes(word in rand_unicode()) {