Fix + test copying of fixed-sized ArrayView rvalues

Previously, only lvalues were tested, and only lvalues worked.

Bug: webrtc:11389
Change-Id: I524e9d63e0840c3ba274dbe2062d78f72d79019d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/169347
Commit-Queue: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30644}
diff --git a/api/array_view.h b/api/array_view.h
index f7130dc..a66369a 100644
--- a/api/array_view.h
+++ b/api/array_view.h
@@ -213,6 +213,14 @@
       : ArrayView(u.data(), u.size()) {
     static_assert(U::size() == Size, "Sizes must match exactly");
   }
+  template <
+      typename U,
+      typename std::enable_if<Size != impl::kArrayViewVarSize &&
+                              HasDataAndSize<U, T>::value>::type* = nullptr>
+  ArrayView(const U& u)  // NOLINT(runtime/explicit)
+      : ArrayView(u.data(), u.size()) {
+    static_assert(U::size() == Size, "Sizes must match exactly");
+  }
 
   // (Only if size is variable.) Construct an ArrayView from any type U that
   // has a size() method whose return value converts implicitly to size_t, and
diff --git a/api/array_view_unittest.cc b/api/array_view_unittest.cc
index 0639404..8aa8588 100644
--- a/api/array_view_unittest.cc
+++ b/api/array_view_unittest.cc
@@ -116,7 +116,7 @@
   // ArrayView<char> v = std::move(z);  // Error, because can't drop const.
 }
 
-TEST(ArrayViewTest, TestCopyConstructorFixed) {
+TEST(ArrayViewTest, TestCopyConstructorFixedLvalue) {
   char arr[] = "Arrr!";
   ArrayView<char, 6> x = arr;
   static_assert(x.size() == 6, "");
@@ -147,6 +147,37 @@
   // ArrayView<char> vv = z;  // Compile error, because can't drop const.
 }
 
+TEST(ArrayViewTest, TestCopyConstructorFixedRvalue) {
+  char arr[] = "Arrr!";
+  ArrayView<char, 6> x = arr;
+  static_assert(x.size() == 6, "");
+  EXPECT_EQ(arr, x.data());
+
+  // Copy fixed -> fixed.
+  ArrayView<char, 6> y = std::move(x);  // Copy non-const -> non-const.
+  static_assert(y.size() == 6, "");
+  EXPECT_EQ(arr, y.data());
+  ArrayView<const char, 6> z = std::move(x);  // Copy non-const -> const.
+  static_assert(z.size() == 6, "");
+  EXPECT_EQ(arr, z.data());
+  ArrayView<const char, 6> w = std::move(z);  // Copy const -> const.
+  static_assert(w.size() == 6, "");
+  EXPECT_EQ(arr, w.data());
+  // ArrayView<char, 6> v = std::move(z);  // Error, because can't drop const.
+
+  // Copy fixed -> variable.
+  ArrayView<char> yv = std::move(x);  // Copy non-const -> non-const.
+  EXPECT_EQ(6u, yv.size());
+  EXPECT_EQ(arr, yv.data());
+  ArrayView<const char> zv = std::move(x);  // Copy non-const -> const.
+  EXPECT_EQ(6u, zv.size());
+  EXPECT_EQ(arr, zv.data());
+  ArrayView<const char> wv = std::move(z);  // Copy const -> const.
+  EXPECT_EQ(6u, wv.size());
+  EXPECT_EQ(arr, wv.data());
+  // ArrayView<char> vv = std::move(z);  // Error, because can't drop const.
+}
+
 TEST(ArrayViewTest, TestCopyAssignmentVariableLvalue) {
   char arr[] = "Arrr!";
   ArrayView<char> x(arr);
@@ -189,7 +220,7 @@
   // v = std::move(z);  // Compile error, because can't drop const.
 }
 
-TEST(ArrayViewTest, TestCopyAssignmentFixed) {
+TEST(ArrayViewTest, TestCopyAssignmentFixedLvalue) {
   char arr[] = "Arrr!";
   char init[] = "Init!";
   ArrayView<char, 6> x(arr);
@@ -225,6 +256,42 @@
   // v = z;  // Compile error, because can't drop const.
 }
 
+TEST(ArrayViewTest, TestCopyAssignmentFixedRvalue) {
+  char arr[] = "Arrr!";
+  char init[] = "Init!";
+  ArrayView<char, 6> x(arr);
+  EXPECT_EQ(arr, x.data());
+
+  // Copy fixed -> fixed.
+  ArrayView<char, 6> y(init);
+  y = std::move(x);  // Copy non-const -> non-const.
+  EXPECT_EQ(arr, y.data());
+  ArrayView<const char, 6> z(init);
+  z = std::move(x);  // Copy non-const -> const.
+  EXPECT_EQ(arr, z.data());
+  ArrayView<const char, 6> w(init);
+  w = std::move(z);  // Copy const -> const.
+  EXPECT_EQ(arr, w.data());
+  // ArrayView<char, 6> v(init);
+  // v = std::move(z);  // Compile error, because can't drop const.
+
+  // Copy fixed -> variable.
+  ArrayView<char> yv;
+  yv = std::move(x);  // Copy non-const -> non-const.
+  EXPECT_EQ(6u, yv.size());
+  EXPECT_EQ(arr, yv.data());
+  ArrayView<const char> zv;
+  zv = std::move(x);  // Copy non-const -> const.
+  EXPECT_EQ(6u, zv.size());
+  EXPECT_EQ(arr, zv.data());
+  ArrayView<const char> wv;
+  wv = std::move(z);  // Copy const -> const.
+  EXPECT_EQ(6u, wv.size());
+  EXPECT_EQ(arr, wv.data());
+  // ArrayView<char> v;
+  // v = std::move(z);  // Compile error, because can't drop const.
+}
+
 TEST(ArrayViewTest, TestStdArray) {
   EXPECT_EQ(4u, Call<const int>(std::array<int, 4>{1, 2, 3, 4}));
   CallFixed<const int, 3>(std::array<int, 3>{2, 3, 4});