Copy //third_party/quic string libraries to //third_party/quiche

  * quic_str_cat_lib      -> quiche_str_cat_lib
  * quic_string_piece_lib -> quiche_string_piece_lib
  * quic_text_utils       -> quiche_text_utils

To keep CLs small, a series of followup CLs will modify consumers of
these libraries to use the quiche variant. A final followup CL will
remove the originals from //third_party/quic.

The motivation is to expose base64 functions to our HTTPSSVC parsing
library, which will eventually land in //third_party and be shared
with Chromium via //third_party/quiche.

PiperOrigin-RevId: 284975905
Change-Id: I78d0b65f7a3afb5613d8f9de1c98b4e3bfd9ed8e
diff --git a/common/platform/api/quiche_str_cat.h b/common/platform/api/quiche_str_cat.h
new file mode 100644
index 0000000..36d054f
--- /dev/null
+++ b/common/platform/api/quiche_str_cat.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_STR_CAT_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_STR_CAT_H_
+
+#include <string>
+#include <utility>
+
+#include "net/quiche/common/platform/impl/quiche_str_cat_impl.h"
+
+namespace quiche {
+
+// Merges given strings or numbers with no delimiter.
+template <typename... Args>
+inline std::string QuicheStrCat(const Args&... args) {
+  return quiche::QuicheStrCatImpl(std::forward<const Args&>(args)...);
+}
+
+template <typename... Args>
+inline std::string QuicheStringPrintf(const Args&... args) {
+  return QuicheStringPrintfImpl(std::forward<const Args&>(args)...);
+}
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_STR_CAT_H_
diff --git a/common/platform/api/quiche_str_cat_test.cc b/common/platform/api/quiche_str_cat_test.cc
new file mode 100644
index 0000000..7085b8a
--- /dev/null
+++ b/common/platform/api/quiche_str_cat_test.cc
@@ -0,0 +1,169 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+
+#include <string>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
+
+namespace quiche {
+namespace test {
+namespace {
+
+class QuicheStrCatTest : public QuicheTest {};
+
+TEST_F(QuicheStrCatTest, Ints) {
+  const int16_t s = -1;
+  const uint16_t us = 2;
+  const int i = -3;
+  const uint32_t ui = 4;
+  const int64_t l = -5;
+  const uint64_t ul = 6;
+  const ptrdiff_t ptrdiff = -7;
+  const size_t size = 8;
+  const intptr_t intptr = -9;
+  const uintptr_t uintptr = 10;
+  std::string answer;
+  answer = QuicheStrCat(s, us);
+  EXPECT_EQ(answer, "-12");
+  answer = QuicheStrCat(i, ui);
+  EXPECT_EQ(answer, "-34");
+  answer = QuicheStrCat(l, ul);
+  EXPECT_EQ(answer, "-56");
+  answer = QuicheStrCat(ptrdiff, size);
+  EXPECT_EQ(answer, "-78");
+  answer = QuicheStrCat(size, intptr);
+  EXPECT_EQ(answer, "8-9");
+  answer = QuicheStrCat(uintptr, 0);
+  EXPECT_EQ(answer, "100");
+}
+
+TEST_F(QuicheStrCatTest, Basics) {
+  std::string result;
+
+  std::string strs[] = {"Hello", "Cruel", "World"};
+
+  QuicheStringPiece pieces[] = {"Hello", "Cruel", "World"};
+
+  const char* c_strs[] = {"Hello", "Cruel", "World"};
+
+  int32_t i32s[] = {'H', 'C', 'W'};
+  uint64_t ui64s[] = {12345678910LL, 10987654321LL};
+
+  result = QuicheStrCat(false, true, 2, 3);
+  EXPECT_EQ(result, "0123");
+
+  result = QuicheStrCat(-1);
+  EXPECT_EQ(result, "-1");
+
+  result = QuicheStrCat(0.5);
+  EXPECT_EQ(result, "0.5");
+
+  result = QuicheStrCat(strs[1], pieces[2]);
+  EXPECT_EQ(result, "CruelWorld");
+
+  result = QuicheStrCat(strs[0], ", ", pieces[2]);
+  EXPECT_EQ(result, "Hello, World");
+
+  result = QuicheStrCat(strs[0], ", ", strs[1], " ", strs[2], "!");
+  EXPECT_EQ(result, "Hello, Cruel World!");
+
+  result = QuicheStrCat(pieces[0], ", ", pieces[1], " ", pieces[2]);
+  EXPECT_EQ(result, "Hello, Cruel World");
+
+  result = QuicheStrCat(c_strs[0], ", ", c_strs[1], " ", c_strs[2]);
+  EXPECT_EQ(result, "Hello, Cruel World");
+
+  result = QuicheStrCat("ASCII ", i32s[0], ", ", i32s[1], " ", i32s[2], "!");
+  EXPECT_EQ(result, "ASCII 72, 67 87!");
+
+  result = QuicheStrCat(ui64s[0], ", ", ui64s[1], "!");
+  EXPECT_EQ(result, "12345678910, 10987654321!");
+
+  std::string one = "1";
+  result = QuicheStrCat("And a ", one.size(), " and a ",
+                        &result[2] - &result[0], " and a ", one, " 2 3 4", "!");
+  EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!");
+
+  result =
+      QuicheStrCat("To output a char by ASCII/numeric value, use +: ", '!' + 0);
+  EXPECT_EQ(result, "To output a char by ASCII/numeric value, use +: 33");
+
+  float f = 10000.5;
+  result = QuicheStrCat("Ten K and a half is ", f);
+  EXPECT_EQ(result, "Ten K and a half is 10000.5");
+
+  double d = 99999.9;
+  result = QuicheStrCat("This double number is ", d);
+  EXPECT_EQ(result, "This double number is 99999.9");
+
+  result = QuicheStrCat(1, 22, 333, 4444, 55555, 666666, 7777777, 88888888,
+                        999999999);
+  EXPECT_EQ(result, "122333444455555666666777777788888888999999999");
+}
+
+TEST_F(QuicheStrCatTest, MaxArgs) {
+  std::string result;
+  // Test 10 up to 26 arguments, the current maximum
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a");
+  EXPECT_EQ(result, "123456789a");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b");
+  EXPECT_EQ(result, "123456789ab");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c");
+  EXPECT_EQ(result, "123456789abc");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d");
+  EXPECT_EQ(result, "123456789abcd");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e");
+  EXPECT_EQ(result, "123456789abcde");
+  result =
+      QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f");
+  EXPECT_EQ(result, "123456789abcdef");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g");
+  EXPECT_EQ(result, "123456789abcdefg");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g", "h");
+  EXPECT_EQ(result, "123456789abcdefgh");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g", "h", "i");
+  EXPECT_EQ(result, "123456789abcdefghi");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g", "h", "i", "j");
+  EXPECT_EQ(result, "123456789abcdefghij");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g", "h", "i", "j", "k");
+  EXPECT_EQ(result, "123456789abcdefghijk");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g", "h", "i", "j", "k", "l");
+  EXPECT_EQ(result, "123456789abcdefghijkl");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g", "h", "i", "j", "k", "l", "m");
+  EXPECT_EQ(result, "123456789abcdefghijklm");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g", "h", "i", "j", "k", "l", "m", "n");
+  EXPECT_EQ(result, "123456789abcdefghijklmn");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g", "h", "i", "j", "k", "l", "m", "n", "o");
+  EXPECT_EQ(result, "123456789abcdefghijklmno");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g", "h", "i", "j", "k", "l", "m", "n", "o", "p");
+  EXPECT_EQ(result, "123456789abcdefghijklmnop");
+  result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+                        "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q");
+  EXPECT_EQ(result, "123456789abcdefghijklmnopq");
+  // No limit thanks to C++11's variadic templates
+  result = QuicheStrCat(
+      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "a", "b", "c", "d", "e", "f", "g", "h",
+      "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
+      "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
+      "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
+  EXPECT_EQ(result,
+            "12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace quiche
diff --git a/common/platform/api/quiche_string_piece.h b/common/platform/api/quiche_string_piece.h
new file mode 100644
index 0000000..9def942
--- /dev/null
+++ b/common/platform/api/quiche_string_piece.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_
+
+#include "net/quiche/common/platform/impl/quiche_string_piece_impl.h"
+
+namespace quiche {
+
+using QuicheStringPiece = quiche::QuicheStringPieceImpl;
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_
diff --git a/common/platform/api/quiche_text_utils.h b/common/platform/api/quiche_text_utils.h
new file mode 100644
index 0000000..c58c676
--- /dev/null
+++ b/common/platform/api/quiche_text_utils.h
@@ -0,0 +1,133 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_
+
+#include <string>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_export.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/quiche/common/platform/impl/quiche_text_utils_impl.h"
+
+namespace quiche {
+
+// Various utilities for manipulating text.
+class QUICHE_EXPORT QuicheTextUtils {
+ public:
+  // Returns true if |data| starts with |prefix|, case sensitively.
+  static bool StartsWith(quiche::QuicheStringPiece data,
+                         quiche::QuicheStringPiece prefix) {
+    return quiche::QuicheTextUtilsImpl::StartsWith(data, prefix);
+  }
+
+  // Returns true if |data| ends with |suffix|, case insensitively.
+  static bool EndsWithIgnoreCase(quiche::QuicheStringPiece data,
+                                 quiche::QuicheStringPiece suffix) {
+    return quiche::QuicheTextUtilsImpl::EndsWithIgnoreCase(data, suffix);
+  }
+
+  // Returns a new string in which |data| has been converted to lower case.
+  static std::string ToLower(quiche::QuicheStringPiece data) {
+    return quiche::QuicheTextUtilsImpl::ToLower(data);
+  }
+
+  // Removes leading and trailing whitespace from |data|.
+  static void RemoveLeadingAndTrailingWhitespace(
+      quiche::QuicheStringPiece* data) {
+    quiche::QuicheTextUtilsImpl::RemoveLeadingAndTrailingWhitespace(data);
+  }
+
+  // Returns true if |in| represents a valid uint64, and stores that value in
+  // |out|.
+  static bool StringToUint64(quiche::QuicheStringPiece in, uint64_t* out) {
+    return quiche::QuicheTextUtilsImpl::StringToUint64(in, out);
+  }
+
+  // Returns true if |in| represents a valid int, and stores that value in
+  // |out|.
+  static bool StringToInt(quiche::QuicheStringPiece in, int* out) {
+    return quiche::QuicheTextUtilsImpl::StringToInt(in, out);
+  }
+
+  // Returns true if |in| represents a valid uint32, and stores that value in
+  // |out|.
+  static bool StringToUint32(quiche::QuicheStringPiece in, uint32_t* out) {
+    return quiche::QuicheTextUtilsImpl::StringToUint32(in, out);
+  }
+
+  // Returns true if |in| represents a valid size_t, and stores that value in
+  // |out|.
+  static bool StringToSizeT(quiche::QuicheStringPiece in, size_t* out) {
+    return quiche::QuicheTextUtilsImpl::StringToSizeT(in, out);
+  }
+
+  // Returns a new string representing |in|.
+  static std::string Uint64ToString(uint64_t in) {
+    return quiche::QuicheTextUtilsImpl::Uint64ToString(in);
+  }
+
+  // This converts |length| bytes of binary to a 2*|length|-character
+  // hexadecimal representation.
+  // Return value: 2*|length| characters of ASCII string.
+  static std::string HexEncode(const char* data, size_t length) {
+    return HexEncode(quiche::QuicheStringPiece(data, length));
+  }
+
+  // This converts |data.length()| bytes of binary to a
+  // 2*|data.length()|-character hexadecimal representation.
+  // Return value: 2*|data.length()| characters of ASCII string.
+  static std::string HexEncode(quiche::QuicheStringPiece data) {
+    return quiche::QuicheTextUtilsImpl::HexEncode(data);
+  }
+
+  // This converts a uint32 into an 8-character hexidecimal
+  // representation.  Return value: 8 characters of ASCII string.
+  static std::string Hex(uint32_t v) {
+    return quiche::QuicheTextUtilsImpl::Hex(v);
+  }
+
+  // Converts |data| from a hexadecimal ASCII string to a binary string
+  // that is |data.length()/2| bytes long.
+  static std::string HexDecode(quiche::QuicheStringPiece data) {
+    return quiche::QuicheTextUtilsImpl::HexDecode(data);
+  }
+
+  // Base64 encodes with no padding |data_len| bytes of |data| into |output|.
+  static void Base64Encode(const uint8_t* data,
+                           size_t data_len,
+                           std::string* output) {
+    return quiche::QuicheTextUtilsImpl::Base64Encode(data, data_len, output);
+  }
+
+  // Returns a string containing hex and ASCII representations of |binary|,
+  // side-by-side in the style of hexdump. Non-printable characters will be
+  // printed as '.' in the ASCII output.
+  // For example, given the input "Hello, QUIC!\01\02\03\04", returns:
+  // "0x0000:  4865 6c6c 6f2c 2051 5549 4321 0102 0304  Hello,.QUIC!...."
+  static std::string HexDump(quiche::QuicheStringPiece binary_data) {
+    return quiche::QuicheTextUtilsImpl::HexDump(binary_data);
+  }
+
+  // Returns true if |data| contains any uppercase characters.
+  static bool ContainsUpperCase(quiche::QuicheStringPiece data) {
+    return quiche::QuicheTextUtilsImpl::ContainsUpperCase(data);
+  }
+
+  // Returns true if |data| contains only decimal digits.
+  static bool IsAllDigits(quiche::QuicheStringPiece data) {
+    return quiche::QuicheTextUtilsImpl::IsAllDigits(data);
+  }
+
+  // Splits |data| into a vector of pieces delimited by |delim|.
+  static std::vector<quiche::QuicheStringPiece> Split(
+      quiche::QuicheStringPiece data,
+      char delim) {
+    return quiche::QuicheTextUtilsImpl::Split(data, delim);
+  }
+};
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_
diff --git a/common/platform/api/quiche_text_utils_test.cc b/common/platform/api/quiche_text_utils_test.cc
new file mode 100644
index 0000000..1ca75d2
--- /dev/null
+++ b/common/platform/api/quiche_text_utils_test.cc
@@ -0,0 +1,231 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+
+#include <string>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
+
+namespace quiche {
+namespace test {
+
+class QuicheTextUtilsTest : public QuicheTest {};
+
+TEST_F(QuicheTextUtilsTest, StartsWith) {
+  EXPECT_TRUE(quiche::QuicheTextUtils::StartsWith("hello world", "hello"));
+  EXPECT_TRUE(
+      quiche::QuicheTextUtils::StartsWith("hello world", "hello world"));
+  EXPECT_TRUE(quiche::QuicheTextUtils::StartsWith("hello world", ""));
+  EXPECT_FALSE(quiche::QuicheTextUtils::StartsWith("hello world", "Hello"));
+  EXPECT_FALSE(quiche::QuicheTextUtils::StartsWith("hello world", "world"));
+  EXPECT_FALSE(quiche::QuicheTextUtils::StartsWith("hello world", "bar"));
+}
+
+TEST_F(QuicheTextUtilsTest, EndsWithIgnoreCase) {
+  EXPECT_TRUE(
+      quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", "world"));
+  EXPECT_TRUE(quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world",
+                                                          "hello world"));
+  EXPECT_TRUE(quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", ""));
+  EXPECT_TRUE(
+      quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", "WORLD"));
+  EXPECT_FALSE(
+      quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", "hello"));
+}
+
+TEST_F(QuicheTextUtilsTest, ToLower) {
+  EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("LOWER"));
+  EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("lower"));
+  EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("lOwEr"));
+  EXPECT_EQ("123", quiche::QuicheTextUtils::ToLower("123"));
+  EXPECT_EQ("", quiche::QuicheTextUtils::ToLower(""));
+}
+
+TEST_F(QuicheTextUtilsTest, RemoveLeadingAndTrailingWhitespace) {
+  std::string input;
+
+  for (auto* input : {"text", " text", "  text", "text ", "text  ", " text ",
+                      "  text  ", "\r\n\ttext", "text\n\r\t"}) {
+    quiche::QuicheStringPiece piece(input);
+    quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&piece);
+    EXPECT_EQ("text", piece);
+  }
+}
+
+TEST_F(QuicheTextUtilsTest, StringToNumbers) {
+  const std::string kMaxInt32Plus1 = "2147483648";
+  const std::string kMinInt32Minus1 = "-2147483649";
+  const std::string kMaxUint32Plus1 = "4294967296";
+
+  {
+    // StringToUint64
+    uint64_t uint64_val = 0;
+    EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint64("123", &uint64_val));
+    EXPECT_EQ(123u, uint64_val);
+    EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint64("1234", &uint64_val));
+    EXPECT_EQ(1234u, uint64_val);
+    EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint64("", &uint64_val));
+    EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint64("-123", &uint64_val));
+    EXPECT_FALSE(
+        quiche::QuicheTextUtils::StringToUint64("-123.0", &uint64_val));
+    EXPECT_TRUE(
+        quiche::QuicheTextUtils::StringToUint64(kMaxUint32Plus1, &uint64_val));
+    EXPECT_EQ(4294967296u, uint64_val);
+  }
+
+  {
+    // StringToint
+    int int_val = 0;
+    EXPECT_TRUE(quiche::QuicheTextUtils::StringToInt("123", &int_val));
+    EXPECT_EQ(123, int_val);
+    EXPECT_TRUE(quiche::QuicheTextUtils::StringToInt("1234", &int_val));
+    EXPECT_EQ(1234, int_val);
+    EXPECT_FALSE(quiche::QuicheTextUtils::StringToInt("", &int_val));
+    EXPECT_TRUE(quiche::QuicheTextUtils::StringToInt("-123", &int_val));
+    EXPECT_EQ(-123, int_val);
+    EXPECT_FALSE(quiche::QuicheTextUtils::StringToInt("-123.0", &int_val));
+    if (sizeof(int) > 4) {
+      EXPECT_TRUE(
+          quiche::QuicheTextUtils::StringToInt(kMinInt32Minus1, &int_val));
+      EXPECT_EQ(-2147483649ll, int_val);
+      EXPECT_TRUE(
+          quiche::QuicheTextUtils::StringToInt(kMaxInt32Plus1, &int_val));
+      EXPECT_EQ(2147483648ll, int_val);
+    } else {
+      EXPECT_FALSE(
+          quiche::QuicheTextUtils::StringToInt(kMinInt32Minus1, &int_val));
+      EXPECT_FALSE(
+          quiche::QuicheTextUtils::StringToInt(kMaxInt32Plus1, &int_val));
+    }
+  }
+
+  {
+    // StringToUint32
+    uint32_t uint32_val = 0;
+    EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint32("123", &uint32_val));
+    EXPECT_EQ(123u, uint32_val);
+    EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint32("1234", &uint32_val));
+    EXPECT_EQ(1234u, uint32_val);
+    EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint32("", &uint32_val));
+    EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint32("-123", &uint32_val));
+    EXPECT_FALSE(
+        quiche::QuicheTextUtils::StringToUint32("-123.0", &uint32_val));
+    EXPECT_FALSE(
+        quiche::QuicheTextUtils::StringToUint32(kMaxUint32Plus1, &uint32_val));
+  }
+
+  {
+    // StringToSizeT
+    size_t size_t_val = 0;
+    EXPECT_TRUE(quiche::QuicheTextUtils::StringToSizeT("123", &size_t_val));
+    EXPECT_EQ(123u, size_t_val);
+    EXPECT_TRUE(quiche::QuicheTextUtils::StringToSizeT("1234", &size_t_val));
+    EXPECT_EQ(1234u, size_t_val);
+    EXPECT_FALSE(quiche::QuicheTextUtils::StringToSizeT("", &size_t_val));
+    EXPECT_FALSE(quiche::QuicheTextUtils::StringToSizeT("-123", &size_t_val));
+    EXPECT_FALSE(quiche::QuicheTextUtils::StringToSizeT("-123.0", &size_t_val));
+    if (sizeof(size_t) > 4) {
+      EXPECT_TRUE(
+          quiche::QuicheTextUtils::StringToSizeT(kMaxUint32Plus1, &size_t_val));
+      EXPECT_EQ(4294967296ull, size_t_val);
+    } else {
+      EXPECT_FALSE(
+          quiche::QuicheTextUtils::StringToSizeT(kMaxUint32Plus1, &size_t_val));
+    }
+  }
+}
+
+TEST_F(QuicheTextUtilsTest, Uint64ToString) {
+  EXPECT_EQ("123", quiche::QuicheTextUtils::Uint64ToString(123));
+  EXPECT_EQ("1234", quiche::QuicheTextUtils::Uint64ToString(1234));
+}
+
+TEST_F(QuicheTextUtilsTest, HexEncode) {
+  EXPECT_EQ("48656c6c6f", quiche::QuicheTextUtils::HexEncode("Hello", 5));
+  EXPECT_EQ("48656c6c6f", quiche::QuicheTextUtils::HexEncode("Hello World", 5));
+  EXPECT_EQ("48656c6c6f", quiche::QuicheTextUtils::HexEncode("Hello"));
+  EXPECT_EQ("0102779cfa",
+            quiche::QuicheTextUtils::HexEncode("\x01\x02\x77\x9c\xfa"));
+}
+
+TEST_F(QuicheTextUtilsTest, HexDecode) {
+  EXPECT_EQ("Hello", quiche::QuicheTextUtils::HexDecode("48656c6c6f"));
+  EXPECT_EQ("", quiche::QuicheTextUtils::HexDecode(""));
+  EXPECT_EQ("\x01\x02\x77\x9c\xfa",
+            quiche::QuicheTextUtils::HexDecode("0102779cfa"));
+}
+
+TEST_F(QuicheTextUtilsTest, HexDump) {
+  // Verify output of the HexDump method is as expected.
+  char packet[] = {
+      0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x51, 0x55, 0x49, 0x43, 0x21,
+      0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+      0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x6c,
+      0x6f, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x74,
+      0x6f, 0x20, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+      0x70, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x6f, 0x66,
+      0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x01, 0x02, 0x03, 0x00,
+  };
+  EXPECT_EQ(
+      quiche::QuicheTextUtils::HexDump(packet),
+      "0x0000:  4865 6c6c 6f2c 2051 5549 4321 2054 6869  Hello,.QUIC!.Thi\n"
+      "0x0010:  7320 7374 7269 6e67 2073 686f 756c 6420  s.string.should.\n"
+      "0x0020:  6265 206c 6f6e 6720 656e 6f75 6768 2074  be.long.enough.t\n"
+      "0x0030:  6f20 7370 616e 206d 756c 7469 706c 6520  o.span.multiple.\n"
+      "0x0040:  6c69 6e65 7320 6f66 206f 7574 7075 742e  lines.of.output.\n"
+      "0x0050:  0102 03                                  ...\n");
+  // Verify that 0x21 and 0x7e are printable, 0x20 and 0x7f are not.
+  EXPECT_EQ("0x0000:  2021 7e7f                                .!~.\n",
+            quiche::QuicheTextUtils::HexDump(
+                quiche::QuicheTextUtils::HexDecode("20217e7f")));
+  // Verify that values above numeric_limits<unsigned char>::max() are formatted
+  // properly on platforms where char is unsigned.
+  EXPECT_EQ("0x0000:  90aa ff                                  ...\n",
+            quiche::QuicheTextUtils::HexDump(
+                quiche::QuicheTextUtils::HexDecode("90aaff")));
+}
+
+TEST_F(QuicheTextUtilsTest, Base64Encode) {
+  std::string output;
+  std::string input = "Hello";
+  quiche::QuicheTextUtils::Base64Encode(
+      reinterpret_cast<const uint8_t*>(input.data()), input.length(), &output);
+  EXPECT_EQ("SGVsbG8", output);
+
+  input =
+      "Hello, QUIC! This string should be long enough to span"
+      "multiple lines of output\n";
+  quiche::QuicheTextUtils::Base64Encode(
+      reinterpret_cast<const uint8_t*>(input.data()), input.length(), &output);
+  EXPECT_EQ(
+      "SGVsbG8sIFFVSUMhIFRoaXMgc3RyaW5nIHNob3VsZCBiZSBsb25n"
+      "IGVub3VnaCB0byBzcGFubXVsdGlwbGUgbGluZXMgb2Ygb3V0cHV0Cg",
+      output);
+}
+
+TEST_F(QuicheTextUtilsTest, ContainsUpperCase) {
+  EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase("abc"));
+  EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase(""));
+  EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase("123"));
+  EXPECT_TRUE(quiche::QuicheTextUtils::ContainsUpperCase("ABC"));
+  EXPECT_TRUE(quiche::QuicheTextUtils::ContainsUpperCase("aBc"));
+}
+
+TEST_F(QuicheTextUtilsTest, Split) {
+  EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a", "b", "c"}),
+            quiche::QuicheTextUtils::Split("a,b,c", ','));
+  EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a", "b", "c"}),
+            quiche::QuicheTextUtils::Split("a:b:c", ':'));
+  EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a:b:c"}),
+            quiche::QuicheTextUtils::Split("a:b:c", ','));
+  // Leading and trailing whitespace is preserved.
+  EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a", "b", "c"}),
+            quiche::QuicheTextUtils::Split("a,b,c", ','));
+  EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({" a", "b ", " c "}),
+            quiche::QuicheTextUtils::Split(" a:b : c ", ':'));
+}
+
+}  // namespace test
+}  // namespace quiche