| #include <endian.h> | 
 |  | 
 | #include <stdplus/raw.hpp> | 
 |  | 
 | #include <array> | 
 | #include <span> | 
 | #include <stdexcept> | 
 | #include <string_view> | 
 | #include <vector> | 
 |  | 
 | #include <gmock/gmock.h> | 
 | #include <gtest/gtest.h> | 
 |  | 
 | namespace stdplus | 
 | { | 
 | namespace raw | 
 | { | 
 | namespace | 
 | { | 
 |  | 
 | TEST(Equal, Equal) | 
 | { | 
 |     int a = 4; | 
 |     unsigned b = 4; | 
 |     EXPECT_TRUE(equal(a, b)); | 
 |     b = 5; | 
 |     EXPECT_FALSE(equal(a, b)); | 
 | } | 
 |  | 
 | TEST(CopyFrom, Empty) | 
 | { | 
 |     const std::string_view cs; | 
 |     EXPECT_THROW(copyFrom<int>(cs), exception::Incomplete); | 
 |     std::string_view s; | 
 |     EXPECT_THROW(copyFrom<int>(s), exception::Incomplete); | 
 |     EXPECT_THROW(copyFromStrict<char>(s), exception::Incomplete); | 
 | } | 
 |  | 
 | TEST(CopyFrom, Basic) | 
 | { | 
 |     int a = 4; | 
 |     const std::string_view s(reinterpret_cast<char*>(&a), sizeof(a)); | 
 |     EXPECT_EQ(a, copyFrom<int>(s)); | 
 |     EXPECT_EQ(a, copyFromStrict<int>(s)); | 
 | } | 
 |  | 
 | TEST(CopyFrom, Partial) | 
 | { | 
 |     const std::vector<char> s = {'a', 'b', 'c'}; | 
 |     EXPECT_EQ('a', copyFrom<char>(s)); | 
 |     EXPECT_THROW(copyFromStrict<char>(s), exception::Incomplete); | 
 |     const char s2[] = "def"; | 
 |     EXPECT_EQ('d', copyFrom<char>(s2)); | 
 | } | 
 |  | 
 | struct Int | 
 | { | 
 |     uint8_t data[sizeof(int)]; | 
 |  | 
 |     inline bool operator==(const Int& other) const | 
 |     { | 
 |         return memcmp(data, other.data, sizeof(data)) == 0; | 
 |     } | 
 | }; | 
 |  | 
 | TEST(RefFrom, Empty) | 
 | { | 
 |     const std::string_view cs; | 
 |     EXPECT_THROW(refFrom<Int>(cs), exception::Incomplete); | 
 |     std::string_view s; | 
 |     EXPECT_THROW(refFrom<Int>(s), exception::Incomplete); | 
 |     EXPECT_THROW(refFromStrict<Int>(s), exception::Incomplete); | 
 | } | 
 |  | 
 | TEST(RefFrom, Basic) | 
 | { | 
 |     Int a = {4, 0, 0, 4}; | 
 |     const std::string_view s(reinterpret_cast<char*>(&a), sizeof(a)); | 
 |     EXPECT_EQ(a, refFrom<Int>(s)); | 
 |     EXPECT_EQ(a, refFromStrict<Int>(s)); | 
 | } | 
 |  | 
 | TEST(RefFrom, Partial) | 
 | { | 
 |     const std::vector<char> s = {'a', 'b', 'c'}; | 
 |     EXPECT_EQ('a', refFrom<char>(s)); | 
 |     EXPECT_THROW(refFromStrict<char>(s), exception::Incomplete); | 
 |     const char s2[] = "def"; | 
 |     EXPECT_EQ('d', refFrom<char>(s2)); | 
 | } | 
 |  | 
 | TEST(Extract, TooSmall) | 
 | { | 
 |     std::string str = "aaaa"; | 
 |     str.resize(1); | 
 |     std::string_view s(str); | 
 |     EXPECT_THROW(extract<int>(s), exception::Incomplete); | 
 |     EXPECT_EQ("a", s); | 
 | } | 
 |  | 
 | TEST(Extract, Basic) | 
 | { | 
 |     int a = 4; | 
 |     std::string_view s(reinterpret_cast<char*>(&a), sizeof(a)); | 
 |     EXPECT_EQ(a, extract<int>(s)); | 
 |     EXPECT_TRUE(s.empty()); | 
 | } | 
 |  | 
 | TEST(Extract, Partial) | 
 | { | 
 |     std::string_view s("abc"); | 
 |     EXPECT_EQ('a', extract<char>(s)); | 
 |     EXPECT_EQ("bc", s); | 
 | } | 
 |  | 
 | TEST(ExtractRef, TooSmall) | 
 | { | 
 |     // Trick the compiler with a bigger buffer so it doesn't complain | 
 |     std::array<char, sizeof(Int)> buf{}; | 
 |     buf[0] = 'a'; | 
 |     std::string_view s(buf.data(), 1); | 
 |     EXPECT_THROW(extractRef<Int>(s), exception::Incomplete); | 
 |     EXPECT_EQ("a", s); | 
 | } | 
 |  | 
 | TEST(ExtractRef, Basic) | 
 | { | 
 |     Int a = {4, 0, 0, 4}; | 
 |     std::string_view s(reinterpret_cast<char*>(&a), sizeof(a)); | 
 |     EXPECT_EQ(a, extractRef<Int>(s)); | 
 |     EXPECT_TRUE(s.empty()); | 
 | } | 
 |  | 
 | TEST(ExtractRef, Partial) | 
 | { | 
 |     std::string_view s("abc"); | 
 |     EXPECT_EQ('a', extractRef<char>(s)); | 
 |     EXPECT_EQ("bc", s); | 
 | } | 
 |  | 
 | TEST(AsView, Byte) | 
 | { | 
 |     int32_t a = 4; | 
 |     auto s = asView<uint8_t>(a); | 
 |     EXPECT_EQ(a, copyFrom<int>(s)); | 
 | } | 
 |  | 
 | TEST(AsView, Int) | 
 | { | 
 |     int32_t a = 4; | 
 |     auto s = asView<char16_t>(a); | 
 |     EXPECT_EQ(a, copyFrom<int>(s)); | 
 | } | 
 |  | 
 | using testing::ElementsAre; | 
 | using testing::ElementsAreArray; | 
 |  | 
 | TEST(AsView, Array) | 
 | { | 
 |     std::vector<uint32_t> arr = {htole32(1), htole32(2)}; | 
 |     auto s = asView<char16_t>(arr); | 
 |     EXPECT_THAT(s, ElementsAre(htole16(1), htole16(0), htole16(2), htole16(0))); | 
 | } | 
 |  | 
 | TEST(AsView, StringView) | 
 | { | 
 |     std::string_view sv = "ab"; | 
 |     auto s = asView<uint8_t>(sv); | 
 |     EXPECT_THAT(s, ElementsAreArray(sv)); | 
 | } | 
 |  | 
 | TEST(SpanExtract, TooSmall) | 
 | { | 
 |     const std::vector<char> v = {'c'}; | 
 |     std::span<const char> s = v; | 
 |     EXPECT_THROW(extract<int>(s), exception::Incomplete); | 
 |     EXPECT_THAT(s, ElementsAreArray(v)); | 
 | } | 
 |  | 
 | TEST(SpanExtract, Basic) | 
 | { | 
 |     const std::vector<int> v = {4}; | 
 |     std::span<const int> s = v; | 
 |     EXPECT_EQ(v[0], extract<int>(s)); | 
 |     EXPECT_TRUE(s.empty()); | 
 | } | 
 |  | 
 | TEST(SpanExtract, Larger) | 
 | { | 
 |     const std::vector<int> v{3, 4, 5}; | 
 |     std::span<const int> s = v; | 
 |     EXPECT_EQ(v[0], extract<int>(s)); | 
 |     EXPECT_THAT(s, ElementsAre(v[1], v[2])); | 
 | } | 
 |  | 
 | TEST(SpanExtractRef, TooSmall) | 
 | { | 
 |     const std::vector<char> v = {'c'}; | 
 |     std::span<const char> s = v; | 
 |     EXPECT_THROW(extractRef<Int>(s), exception::Incomplete); | 
 |     EXPECT_THAT(s, ElementsAreArray(v)); | 
 | } | 
 |  | 
 | TEST(SpanExtractRef, Basic) | 
 | { | 
 |     const std::vector<Int> v = {{4, 0, 0, 4}}; | 
 |     std::span<const Int> s = v; | 
 |     EXPECT_EQ(v[0], extractRef<Int>(s)); | 
 |     EXPECT_TRUE(s.empty()); | 
 | } | 
 |  | 
 | TEST(SpanExtractRef, Larger) | 
 | { | 
 |     const std::vector<Int> v{{3}, {4}, {5}}; | 
 |     std::span<const Int> s = v; | 
 |     EXPECT_EQ(v[0], extractRef<Int>(s)); | 
 |     EXPECT_THAT(s, ElementsAre(v[1], v[2])); | 
 | } | 
 |  | 
 | TEST(AsSpan, ConstInt) | 
 | { | 
 |     const uint64_t data = htole64(0xffff0000); | 
 |     auto s = asSpan<uint32_t>(data); | 
 |     EXPECT_THAT(s, ElementsAre(htole32(0xffff0000), htole32(0x00000000))); | 
 | } | 
 |  | 
 | TEST(AsSpan, ConstArray) | 
 | { | 
 |     const std::vector<uint32_t> arr = {htole32(1), htole32(2)}; | 
 |     auto s = asSpan<uint16_t>(arr); | 
 |     EXPECT_THAT(s, ElementsAre(htole16(1), htole16(0), htole16(2), htole16(0))); | 
 | } | 
 |  | 
 | TEST(AsSpan, Int) | 
 | { | 
 |     struct | 
 |     { | 
 |         uint64_t a; | 
 |         uint64_t* data() | 
 |         { | 
 |             return &a; | 
 |         } | 
 |     } data = {htole64(0xffff0000)}; | 
 |     auto s = asSpan<uint16_t>(data); | 
 |     EXPECT_THAT(s, ElementsAre(htole16(0x0000), htole16(0xffff), | 
 |                                htole16(0x0000), htole16(0x0000))); | 
 |     s[2] = 0xfefe; | 
 |     EXPECT_THAT(s, ElementsAre(htole16(0x0000), htole16(0xffff), | 
 |                                htole16(0xfefe), htole16(0x0000))); | 
 | } | 
 |  | 
 | TEST(AsSpan, Array) | 
 | { | 
 |     std::vector<uint32_t> arr = {htole32(1), htole32(2)}; | 
 |     auto s = asSpan<uint16_t>(arr); | 
 |     EXPECT_THAT(s, ElementsAre(htole16(1), htole16(0), htole16(2), htole16(0))); | 
 | } | 
 |  | 
 | TEST(AsSpan, Span) | 
 | { | 
 |     std::array<char, 2> arr = {'a', 'b'}; | 
 |     auto sp1 = std::span<const char>(arr); | 
 |     auto s1 = asSpan<uint8_t>(sp1); | 
 |     EXPECT_THAT(s1, ElementsAreArray(arr)); | 
 |     auto sp2 = std::span<char>(arr); | 
 |     auto s2 = asSpan<uint8_t>(sp2); | 
 |     EXPECT_THAT(s2, ElementsAreArray(arr)); | 
 | } | 
 |  | 
 | } // namespace | 
 | } // namespace raw | 
 | } // namespace stdplus |