From 73c4c1b27c9028c5404c39c58ab8afa303251e6b Mon Sep 17 00:00:00 2001 From: Malay Satapathy Date: Fri, 16 Oct 2026 00:22:02 +0530 Subject: [PATCH] Fix #207: FR: Add CopyBytesFrom for array types --- runtime/cpp/emboss_array_view.h | 23 +++++++++++++ runtime/cpp/test/emboss_array_view_test.cc | 38 ++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/runtime/cpp/emboss_array_view.h b/runtime/cpp/emboss_array_view.h index fa8ccd38..4960d118 100644 --- a/runtime/cpp/emboss_array_view.h +++ b/runtime/cpp/emboss_array_view.h @@ -258,6 +258,29 @@ class GenericArrayView final { WriteArrayToTextStream(this, stream, options); } + template + typename ::std::enable_if< + ((void)N, kAddressableUnitSize * kElementSize == 8), void>::type + CopyBytesFrom(const Container &source) const { + EMBOSS_CHECK(IsComplete()); + EMBOSS_CHECK(static_cast<::std::size_t>(source.size()) == ElementCount()); + auto it = source.begin(); + for (::std::size_t i = 0; i < ElementCount(); ++i, ++it) { + (*this)[i].Write(static_cast(*it)); + } + } + + template + typename ::std::enable_if< + ((void)M, kAddressableUnitSize * kElementSize == 8), void>::type + CopyBytesFrom(const T (&source)[N]) const { + EMBOSS_CHECK(IsComplete()); + EMBOSS_CHECK(N == ElementCount()); + for (::std::size_t i = 0; i < ElementCount(); ++i) { + (*this)[i].Write(static_cast(source[i])); + } + } + static constexpr bool IsAggregate() { return true; } BufferType BackingStorage() const { return buffer_; } diff --git a/runtime/cpp/test/emboss_array_view_test.cc b/runtime/cpp/test/emboss_array_view_test.cc index 1f632e89..10e98b9f 100644 --- a/runtime/cpp/test/emboss_array_view_test.cc +++ b/runtime/cpp/test/emboss_array_view_test.cc @@ -16,6 +16,7 @@ #include #include +#include #include "absl/strings/str_format.h" #include "gtest/gtest.h" @@ -89,6 +90,43 @@ TEST(ArrayView, Methods) { EXPECT_FALSE((ArrayView, ReadWriteContiguousBuffer, 1>{ ReadWriteContiguousBuffer{ nullptr}}.Ok())); + + // Test CopyBytesFrom + ::std::array<::std::uint8_t, 4> new_bytes = {0xaa, 0xbb, 0xcc, 0xdd}; + auto dest_array = ArrayView, ReadWriteContiguousBuffer, 1>{ + ReadWriteContiguousBuffer{bytes, 4}}; + dest_array.CopyBytesFrom(new_bytes); + EXPECT_EQ(0xaa, bytes[0]); + EXPECT_EQ(0xbb, bytes[1]); + EXPECT_EQ(0xcc, bytes[2]); + EXPECT_EQ(0xdd, bytes[3]); + + // Test CopyBytesFrom with signed elements to ensure values >= 128 do not abort + bytes[0] = 0; + bytes[1] = 0; + bytes[2] = 0; + bytes[3] = 0; + auto dest_signed_array = + ArrayView, ReadWriteContiguousBuffer, 1>{ + ReadWriteContiguousBuffer{bytes, 4}}; + dest_signed_array.CopyBytesFrom(new_bytes); + EXPECT_EQ(0xaa, bytes[0]); + EXPECT_EQ(0xbb, bytes[1]); + EXPECT_EQ(0xcc, bytes[2]); + EXPECT_EQ(0xdd, bytes[3]); + + // Test CopyBytesFrom with a raw C-style array + const ::std::uint8_t raw_bytes[4] = {0x11, 0x22, 0x33, 0x44}; + dest_array.CopyBytesFrom(raw_bytes); + EXPECT_EQ(0x11, bytes[0]); + EXPECT_EQ(0x22, bytes[1]); + EXPECT_EQ(0x33, bytes[2]); + EXPECT_EQ(0x44, bytes[3]); + +#if EMBOSS_CHECK_ABORTS + ::std::array<::std::uint8_t, 3> wrong_size_bytes = {0xaa, 0xbb, 0xcc}; + EXPECT_DEATH(dest_array.CopyBytesFrom(wrong_size_bytes), ""); +#endif // EMBOSS_CHECK_ABORTS } TEST(ArrayView, Ok) {