diff --git a/api/array_view.h b/api/array_view.h index bf91484a24..f7130dcc37 100644 --- a/api/array_view.h +++ b/api/array_view.h @@ -285,6 +285,23 @@ inline ArrayView MakeArrayView(T* data, size_t size) { return ArrayView(data, size); } +// Only for primitive types that have the same size and aligment. +// Allow reinterpret cast of the array view to another primitive type of the +// same size. +// Template arguments order is (U, T, Size) to allow deduction of the template +// arguments in client calls: reinterpret_array_view(array_view). +template +inline ArrayView reinterpret_array_view(ArrayView view) { + static_assert(sizeof(U) == sizeof(T) && alignof(U) == alignof(T), + "ArrayView reinterpret_cast is only supported for casting " + "between views that represent the same chunk of memory."); + static_assert( + std::is_fundamental::value && std::is_fundamental::value, + "ArrayView reinterpret_cast is only supported for casting between " + "fundamental types."); + return ArrayView(reinterpret_cast(view.data()), view.size()); +} + } // namespace rtc #endif // API_ARRAY_VIEW_H_ diff --git a/api/array_view_unittest.cc b/api/array_view_unittest.cc index 62b51c0811..18d0e6cf9e 100644 --- a/api/array_view_unittest.cc +++ b/api/array_view_unittest.cc @@ -450,4 +450,23 @@ TEST(ArrayViewTest, TestSubViewFixed) { EXPECT_THAT(av.subview(1, 3), ElementsAre(2, 3)); } +TEST(ArrayViewTest, TestReinterpretCastFixedSize) { + uint8_t bytes[] = {1, 2, 3}; + ArrayView uint8_av(bytes); + ArrayView int8_av = reinterpret_array_view(uint8_av); + EXPECT_EQ(int8_av.size(), uint8_av.size()); + EXPECT_EQ(int8_av[0], 1); + EXPECT_EQ(int8_av[1], 2); + EXPECT_EQ(int8_av[2], 3); +} + +TEST(ArrayViewTest, TestReinterpretCastVariableSize) { + std::vector v = {1, 2, 3}; + ArrayView int8_av(v); + ArrayView uint8_av = reinterpret_array_view(int8_av); + EXPECT_EQ(int8_av.size(), uint8_av.size()); + EXPECT_EQ(uint8_av[0], 1); + EXPECT_EQ(uint8_av[1], 2); + EXPECT_EQ(uint8_av[2], 3); +} } // namespace rtc