Allow CopyOnWriteBuffer to accept vector-like types.

Bug: none
Change-Id: I03ee91be151e10d6b0385b462158ecd0bd9ad4ed
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/232129
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35039}
diff --git a/rtc_base/copy_on_write_buffer.h b/rtc_base/copy_on_write_buffer.h
index 526cbe5..6837f06 100644
--- a/rtc_base/copy_on_write_buffer.h
+++ b/rtc_base/copy_on_write_buffer.h
@@ -24,6 +24,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/ref_counted_object.h"
 #include "rtc_base/system/rtc_export.h"
+#include "rtc_base/type_traits.h"
 
 namespace rtc {
 
@@ -70,6 +71,17 @@
   CopyOnWriteBuffer(const T (&array)[N])  // NOLINT: runtime/explicit
       : CopyOnWriteBuffer(array, N) {}
 
+  // Construct a buffer from a vector like type.
+  template <typename VecT,
+            typename ElemT = typename std::remove_pointer_t<
+                decltype(std::declval<VecT>().data())>,
+            typename std::enable_if_t<
+                !std::is_same<VecT, CopyOnWriteBuffer>::value &&
+                HasDataAndSize<VecT, ElemT>::value &&
+                internal::BufferCompat<uint8_t, ElemT>::value>* = nullptr>
+  explicit CopyOnWriteBuffer(const VecT& v)
+      : CopyOnWriteBuffer(v.data(), v.size()) {}
+
   ~CopyOnWriteBuffer();
 
   // Get a pointer to the data. Just .data() will give you a (const) uint8_t*,
@@ -221,8 +233,14 @@
     AppendData(array, N);
   }
 
-  void AppendData(const CopyOnWriteBuffer& buf) {
-    AppendData(buf.data(), buf.size());
+  template <typename VecT,
+            typename ElemT = typename std::remove_pointer_t<
+                decltype(std::declval<VecT>().data())>,
+            typename std::enable_if_t<
+                HasDataAndSize<VecT, ElemT>::value &&
+                internal::BufferCompat<uint8_t, ElemT>::value>* = nullptr>
+  void AppendData(const VecT& v) {
+    AppendData(v.data(), v.size());
   }
 
   // Sets the size of the buffer. If the new size is smaller than the old, the
diff --git a/rtc_base/copy_on_write_buffer_unittest.cc b/rtc_base/copy_on_write_buffer_unittest.cc
index d397868..ad2c4e0 100644
--- a/rtc_base/copy_on_write_buffer_unittest.cc
+++ b/rtc_base/copy_on_write_buffer_unittest.cc
@@ -353,4 +353,24 @@
   EXPECT_EQ(buf.cdata() + 3, slice.cdata());
 }
 
+TEST(CopyOnWriteBufferTest, AcceptsVectorLikeTypes) {
+  std::vector<uint8_t> a = {1, 2};
+  std::vector<int8_t> b = {3, 4};
+  rtc::ArrayView<uint8_t> c(a);
+  rtc::ArrayView<const int8_t> d(b);
+
+  CopyOnWriteBuffer a_buf(a);
+  CopyOnWriteBuffer b_buf(b);
+  CopyOnWriteBuffer c_buf(c);
+  CopyOnWriteBuffer d_buf(d);
+
+  CopyOnWriteBuffer all;
+  all.AppendData(a);
+  all.AppendData(b);
+  all.AppendData(c);
+  all.AppendData(d);
+
+  EXPECT_EQ(all.size(), 8U);
+}
+
 }  // namespace rtc