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