Ship our own implementation of QuicheEndian instead of using the platform one. PiperOrigin-RevId: 332495000 Change-Id: I157a4a4379f2240ccd1538c41d87b209751a487d
diff --git a/common/platform/api/quiche_endian.h b/common/platform/api/quiche_endian.h index f8a9ee6..69bdc5b 100644 --- a/common/platform/api/quiche_endian.h +++ b/common/platform/api/quiche_endian.h
@@ -5,8 +5,11 @@ #ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_ENDIAN_H_ #define QUICHE_COMMON_PLATFORM_API_QUICHE_ENDIAN_H_ +#include <algorithm> +#include <cstdint> +#include <type_traits> + #include "net/third_party/quiche/src/common/platform/api/quiche_export.h" -#include "net/quiche/common/platform/impl/quiche_endian_impl.h" namespace quiche { @@ -20,33 +23,38 @@ // platform). class QUICHE_EXPORT_PRIVATE QuicheEndian { public: - // Convert |x| from host order (can be either little or big endian depending - // on the platform) to network order (big endian). - static uint16_t HostToNet16(uint16_t x) { - return QuicheEndianImpl::HostToNet16(x); - } - static uint32_t HostToNet32(uint32_t x) { - return QuicheEndianImpl::HostToNet32(x); - } - static uint64_t HostToNet64(uint64_t x) { - return QuicheEndianImpl::HostToNet64(x); - } + // Convert |x| from host order (little endian) to network order (big endian). +#if defined(__clang__) || \ + (defined(__GNUC__) && \ + ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ >= 5)) + static uint16_t HostToNet16(uint16_t x) { return __builtin_bswap16(x); } + static uint32_t HostToNet32(uint32_t x) { return __builtin_bswap32(x); } + static uint64_t HostToNet64(uint64_t x) { return __builtin_bswap64(x); } +#else + static uint16_t HostToNet16(uint16_t x) { return PortableByteSwap(x); } + static uint32_t HostToNet32(uint32_t x) { return PortableByteSwap(x); } + static uint64_t HostToNet64(uint64_t x) { return PortableByteSwap(x); } +#endif - // Convert |x| from network order (big endian) to host order (can be either - // little or big endian depending on the platform). - static uint16_t NetToHost16(uint16_t x) { - return QuicheEndianImpl::NetToHost16(x); - } - static uint32_t NetToHost32(uint32_t x) { - return QuicheEndianImpl::NetToHost32(x); - } - static uint64_t NetToHost64(uint64_t x) { - return QuicheEndianImpl::NetToHost64(x); - } + // Convert |x| from network order (big endian) to host order (little endian). + static uint16_t NetToHost16(uint16_t x) { return HostToNet16(x); } + static uint32_t NetToHost32(uint32_t x) { return HostToNet32(x); } + static uint64_t NetToHost64(uint64_t x) { return HostToNet64(x); } // Returns true if current host order is little endian. - static bool HostIsLittleEndian() { - return QuicheEndianImpl::HostIsLittleEndian(); + static bool HostIsLittleEndian() { return true; } + + // Left public for tests. + template <typename T> + static T PortableByteSwap(T input) { + static_assert(std::is_unsigned<T>::value, "T has to be uintNN_t"); + union { + T number; + char bytes[sizeof(T)]; + } value; + value.number = input; + std::reverse(std::begin(value.bytes), std::end(value.bytes)); + return value.number; } };
diff --git a/common/platform/api/quiche_endian_test.cc b/common/platform/api/quiche_endian_test.cc index 98e16fe..2f21938 100644 --- a/common/platform/api/quiche_endian_test.cc +++ b/common/platform/api/quiche_endian_test.cc
@@ -18,40 +18,33 @@ class QuicheEndianTest : public QuicheTest {}; +// Test portable version. Since we normally compile with either GCC or Clang, +// it will very rarely used otherwise. +TEST_F(QuicheEndianTest, Portable) { + EXPECT_EQ(k16BitSwappedTestData, + QuicheEndian::PortableByteSwap(k16BitTestData)); + EXPECT_EQ(k32BitSwappedTestData, + QuicheEndian::PortableByteSwap(k32BitTestData)); + EXPECT_EQ(k64BitSwappedTestData, + QuicheEndian::PortableByteSwap(k64BitTestData)); +} + TEST_F(QuicheEndianTest, HostToNet) { - if (quiche::QuicheEndian::HostIsLittleEndian()) { - EXPECT_EQ(k16BitSwappedTestData, - quiche::QuicheEndian::HostToNet16(k16BitTestData)); - EXPECT_EQ(k32BitSwappedTestData, - quiche::QuicheEndian::HostToNet32(k32BitTestData)); - EXPECT_EQ(k64BitSwappedTestData, - quiche::QuicheEndian::HostToNet64(k64BitTestData)); - } else { - EXPECT_EQ(k16BitTestData, - quiche::QuicheEndian::HostToNet16(k16BitTestData)); - EXPECT_EQ(k32BitTestData, - quiche::QuicheEndian::HostToNet32(k32BitTestData)); - EXPECT_EQ(k64BitTestData, - quiche::QuicheEndian::HostToNet64(k64BitTestData)); - } + EXPECT_EQ(k16BitSwappedTestData, + quiche::QuicheEndian::HostToNet16(k16BitTestData)); + EXPECT_EQ(k32BitSwappedTestData, + quiche::QuicheEndian::HostToNet32(k32BitTestData)); + EXPECT_EQ(k64BitSwappedTestData, + quiche::QuicheEndian::HostToNet64(k64BitTestData)); } TEST_F(QuicheEndianTest, NetToHost) { - if (quiche::QuicheEndian::HostIsLittleEndian()) { - EXPECT_EQ(k16BitTestData, - quiche::QuicheEndian::NetToHost16(k16BitSwappedTestData)); - EXPECT_EQ(k32BitTestData, - quiche::QuicheEndian::NetToHost32(k32BitSwappedTestData)); - EXPECT_EQ(k64BitTestData, - quiche::QuicheEndian::NetToHost64(k64BitSwappedTestData)); - } else { - EXPECT_EQ(k16BitSwappedTestData, - quiche::QuicheEndian::NetToHost16(k16BitSwappedTestData)); - EXPECT_EQ(k32BitSwappedTestData, - quiche::QuicheEndian::NetToHost32(k32BitSwappedTestData)); - EXPECT_EQ(k64BitSwappedTestData, - quiche::QuicheEndian::NetToHost64(k64BitSwappedTestData)); - } + EXPECT_EQ(k16BitTestData, + quiche::QuicheEndian::NetToHost16(k16BitSwappedTestData)); + EXPECT_EQ(k32BitTestData, + quiche::QuicheEndian::NetToHost32(k32BitSwappedTestData)); + EXPECT_EQ(k64BitTestData, + quiche::QuicheEndian::NetToHost64(k64BitSwappedTestData)); } } // namespace