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