Relocate QUICHE files into quiche/ directory within the quiche repo, and change the relative include paths accordingly.

PiperOrigin-RevId: 440164720
Change-Id: I64d8a975d08888a3a86f6c51908e63d5cd45fa35
diff --git a/quiche/common/platform/api/quiche_bug_tracker.h b/quiche/common/platform/api/quiche_bug_tracker.h
new file mode 100644
index 0000000..27ac0d2
--- /dev/null
+++ b/quiche/common/platform/api/quiche_bug_tracker.h
@@ -0,0 +1,15 @@
+// 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_BUG_TRACKER_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_BUG_TRACKER_H_
+
+#include "quiche_platform_impl/quiche_bug_tracker_impl.h"
+
+#define QUICHE_BUG QUICHE_BUG_IMPL
+#define QUICHE_BUG_IF QUICHE_BUG_IF_IMPL
+#define QUICHE_PEER_BUG QUICHE_PEER_BUG_IMPL
+#define QUICHE_PEER_BUG_IF QUICHE_PEER_BUG_IF_IMPL
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_BUG_TRACKER_H_
diff --git a/quiche/common/platform/api/quiche_client_stats.h b/quiche/common/platform/api/quiche_client_stats.h
new file mode 100644
index 0000000..5b1b08c
--- /dev/null
+++ b/quiche/common/platform/api/quiche_client_stats.h
@@ -0,0 +1,88 @@
+// Copyright 2018 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_CLIENT_STATS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_CLIENT_STATS_H_
+
+#include <string>
+
+#include "quiche_platform_impl/quiche_client_stats_impl.h"
+
+namespace quiche {
+
+//------------------------------------------------------------------------------
+// Enumeration histograms.
+//
+// Sample usage:
+//   // In Chrome, these values are persisted to logs. Entries should not be
+//   // renumbered and numeric values should never be reused.
+//   enum class MyEnum {
+//     FIRST_VALUE = 0,
+//     SECOND_VALUE = 1,
+//     ...
+//     FINAL_VALUE = N,
+//     COUNT
+//   };
+//   QUICHE_CLIENT_HISTOGRAM_ENUM("My.Enumeration", MyEnum::SOME_VALUE,
+//   MyEnum::COUNT, "Number of time $foo equals to some enum value");
+//
+// Note: The value in |sample| must be strictly less than |enum_size|.
+
+#define QUICHE_CLIENT_HISTOGRAM_ENUM(name, sample, enum_size, docstring) \
+  QUICHE_CLIENT_HISTOGRAM_ENUM_IMPL(name, sample, enum_size, docstring)
+
+//------------------------------------------------------------------------------
+// Histogram for boolean values.
+
+// Sample usage:
+//   QUICHE_CLIENT_HISTOGRAM_BOOL("My.Boolean", bool,
+//   "Number of times $foo is true or false");
+#define QUICHE_CLIENT_HISTOGRAM_BOOL(name, sample, docstring) \
+  QUICHE_CLIENT_HISTOGRAM_BOOL_IMPL(name, sample, docstring)
+
+//------------------------------------------------------------------------------
+// Timing histograms. These are used for collecting timing data (generally
+// latencies).
+
+// These macros create exponentially sized histograms (lengths of the bucket
+// ranges exponentially increase as the sample range increases). The units for
+// sample and max are unspecified, but they must be the same for one histogram.
+
+// Sample usage:
+//   QUICHE_CLIENT_HISTOGRAM_TIMES("Very.Long.Timing.Histogram", time_delta,
+//       QuicTime::Delta::FromSeconds(1), QuicTime::Delta::FromSecond(3600 *
+//       24), 100, "Time spent in doing operation.");
+#define QUICHE_CLIENT_HISTOGRAM_TIMES(name, sample, min, max, bucket_count, \
+                                      docstring)                            \
+  QUICHE_CLIENT_HISTOGRAM_TIMES_IMPL(name, sample, min, max, bucket_count,  \
+                                     docstring)
+
+//------------------------------------------------------------------------------
+// Count histograms. These are used for collecting numeric data.
+
+// These macros default to exponential histograms - i.e. the lengths of the
+// bucket ranges exponentially increase as the sample range increases.
+
+// All of these macros must be called with |name| as a runtime constant.
+
+// Any data outside the range here will be put in underflow and overflow
+// buckets. Min values should be >=1 as emitted 0s will still go into the
+// underflow bucket.
+
+// Sample usage:
+//   UMA_CLIENT_HISTOGRAM_CUSTOM_COUNTS("My.Histogram", 1, 100000000, 100,
+//      "Counters of hitting certain code.");
+
+#define QUICHE_CLIENT_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count, \
+                                       docstring)                            \
+  QUICHE_CLIENT_HISTOGRAM_COUNTS_IMPL(name, sample, min, max, bucket_count,  \
+                                      docstring)
+
+inline void QuicheClientSparseHistogram(const std::string& name, int sample) {
+  QuicheClientSparseHistogramImpl(name, sample);
+}
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_CLIENT_STATS_H_
diff --git a/quiche/common/platform/api/quiche_command_line_flags.h b/quiche/common/platform/api/quiche_command_line_flags.h
new file mode 100644
index 0000000..783dea6
--- /dev/null
+++ b/quiche/common/platform/api/quiche_command_line_flags.h
@@ -0,0 +1,38 @@
+// 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_COMMAND_LINE_FLAGS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_COMMAND_LINE_FLAGS_H_
+
+#include <string>
+#include <vector>
+
+#include "quiche_platform_impl/quiche_command_line_flags_impl.h"
+
+// Define a command-line flag that can be automatically set via
+// QuicheParseCommandLineFlags().
+#define DEFINE_QUICHE_COMMAND_LINE_FLAG(type, name, default_value, help) \
+  DEFINE_QUICHE_COMMAND_LINE_FLAG_IMPL(type, name, default_value, help)
+
+namespace quiche {
+
+// Parses command-line flags, setting flag variables defined using
+// DEFINE_QUICHE_COMMAND_LINE_FLAG if they appear in the command line, and
+// returning a list of any non-flag arguments specified in the command line. If
+// the command line specifies '-h' or '--help', prints a usage message with flag
+// descriptions to stdout and exits with status 0. If a flag has an unparsable
+// value, writes an error message to stderr and exits with status 1.
+inline std::vector<std::string> QuicheParseCommandLineFlags(
+    const char* usage, int argc, const char* const* argv) {
+  return QuicheParseCommandLineFlagsImpl(usage, argc, argv);
+}
+
+// Prints a usage message with flag descriptions to stdout.
+inline void QuichePrintCommandLineFlagHelp(const char* usage) {
+  QuichePrintCommandLineFlagHelpImpl(usage);
+}
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_COMMAND_LINE_FLAGS_H_
diff --git a/quiche/common/platform/api/quiche_containers.h b/quiche/common/platform/api/quiche_containers.h
new file mode 100644
index 0000000..b3b929a
--- /dev/null
+++ b/quiche/common/platform/api/quiche_containers.h
@@ -0,0 +1,22 @@
+// 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_CONTAINERS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_CONTAINERS_H_
+
+#include "quiche_platform_impl/quiche_containers_impl.h"
+
+namespace quiche {
+
+// An ordered container optimized for small sets.
+// An implementation with O(n) mutations might be chosen
+// in case it has better memory usage and/or faster access.
+//
+// DOES NOT GUARANTEE POINTER OR ITERATOR STABILITY!
+template <typename Key, typename Compare = std::less<Key>>
+using QuicheSmallOrderedSet = QuicheSmallOrderedSetImpl<Key, Compare>;
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_CONTAINERS_H_
diff --git a/quiche/common/platform/api/quiche_default_proof_providers.h b/quiche/common/platform/api/quiche_default_proof_providers.h
new file mode 100644
index 0000000..9d5522e
--- /dev/null
+++ b/quiche/common/platform/api/quiche_default_proof_providers.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2019 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_DEFAULT_PROOF_PROVIDERS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_DEFAULT_PROOF_PROVIDERS_H_
+
+#include <memory>
+
+#include "quiche_platform_impl/quiche_default_proof_providers_impl.h"
+#include "quiche/quic/core/crypto/proof_source.h"
+#include "quiche/quic/core/crypto/proof_verifier.h"
+
+namespace quiche {
+
+// Provides a default proof verifier that can verify a cert chain for |host|.
+// The verifier has to do a good faith attempt at verifying the certificate
+// against a reasonable root store, and not just always return success.
+inline std::unique_ptr<quic::ProofVerifier> CreateDefaultProofVerifier(
+    const std::string& host) {
+  return CreateDefaultProofVerifierImpl(host);
+}
+
+// Provides a default proof source for CLI-based tools.  The actual certificates
+// used in the proof source should be confifgurable via command-line flags.
+inline std::unique_ptr<quic::ProofSource> CreateDefaultProofSource() {
+  return CreateDefaultProofSourceImpl();
+}
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_DEFAULT_PROOF_PROVIDERS_H_
diff --git a/quiche/common/platform/api/quiche_epoll.h b/quiche/common/platform/api/quiche_epoll.h
new file mode 100644
index 0000000..5fd470c
--- /dev/null
+++ b/quiche/common/platform/api/quiche_epoll.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2019 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_EPOLL_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_EPOLL_H_
+
+#include "quiche_platform_impl/quiche_epoll_impl.h"
+
+namespace quiche {
+
+using QuicheEpollServer = QuicheEpollServerImpl;
+using QuicheEpollEvent = QuicheEpollEventImpl;
+using QuicheEpollAlarmBase = QuicheEpollAlarmBaseImpl;
+using QuicheEpollCallbackInterface = QuicheEpollCallbackInterfaceImpl;
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_EPOLL_H_
diff --git a/quiche/common/platform/api/quiche_epoll_test_tools.h b/quiche/common/platform/api/quiche_epoll_test_tools.h
new file mode 100644
index 0000000..998ed83
--- /dev/null
+++ b/quiche/common/platform/api/quiche_epoll_test_tools.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2019 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_EPOLL_TEST_TOOLS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_EPOLL_TEST_TOOLS_H_
+
+#include "quiche_platform_impl/quiche_epoll_test_tools_impl.h"
+
+namespace quiche {
+
+using QuicheFakeEpollServer = QuicheFakeEpollServerImpl;
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_EPOLL_TEST_TOOLS_H_
diff --git a/quiche/common/platform/api/quiche_expect_bug.h b/quiche/common/platform/api/quiche_expect_bug.h
new file mode 100644
index 0000000..02ba8d1
--- /dev/null
+++ b/quiche/common/platform/api/quiche_expect_bug.h
@@ -0,0 +1,14 @@
+// Copyright (c) 2018 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_EXPECT_BUG_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_EXPECT_BUG_H_
+
+#include "quiche_platform_impl/quiche_expect_bug_impl.h"
+
+#define EXPECT_QUICHE_BUG EXPECT_QUICHE_BUG_IMPL
+#define EXPECT_QUICHE_PEER_BUG(statement, regex) \
+  EXPECT_QUICHE_PEER_BUG_IMPL(statement, regex)
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_EXPECT_BUG_H_
diff --git a/quiche/common/platform/api/quiche_export.h b/quiche/common/platform/api/quiche_export.h
new file mode 100644
index 0000000..4f64819
--- /dev/null
+++ b/quiche/common/platform/api/quiche_export.h
@@ -0,0 +1,21 @@
+// Copyright 2019 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_EXPORT_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_EXPORT_H_
+
+#include "quiche_platform_impl/quiche_export_impl.h"
+
+// QUICHE_EXPORT is not meant to be used.
+#define QUICHE_EXPORT QUICHE_EXPORT_IMPL
+
+// QUICHE_EXPORT_PRIVATE is meant for QUICHE functionality that is built in
+// Chromium as part of //net, and not fully contained in headers.
+#define QUICHE_EXPORT_PRIVATE QUICHE_EXPORT_PRIVATE_IMPL
+
+// QUICHE_NO_EXPORT is meant for QUICHE functionality that is either fully
+// defined in a header, or is built in Chromium as part of tests or tools.
+#define QUICHE_NO_EXPORT QUICHE_NO_EXPORT_IMPL
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_EXPORT_H_
diff --git a/quiche/common/platform/api/quiche_file_utils.cc b/quiche/common/platform/api/quiche_file_utils.cc
new file mode 100644
index 0000000..6453ea2
--- /dev/null
+++ b/quiche/common/platform/api/quiche_file_utils.cc
@@ -0,0 +1,51 @@
+#include "quiche/common/platform/api/quiche_file_utils.h"
+
+#include "quiche_platform_impl/quiche_file_utils_impl.h"
+
+namespace quiche {
+
+std::string JoinPath(absl::string_view a, absl::string_view b) {
+  return JoinPathImpl(a, b);
+}
+
+absl::optional<std::string> ReadFileContents(absl::string_view file) {
+  return ReadFileContentsImpl(file);
+}
+
+bool EnumerateDirectory(absl::string_view path,
+                        std::vector<std::string>& directories,
+                        std::vector<std::string>& files) {
+  return EnumerateDirectoryImpl(path, directories, files);
+}
+
+bool EnumerateDirectoryRecursivelyInner(absl::string_view path,
+                                        int recursion_limit,
+                                        std::vector<std::string>& files) {
+  if (recursion_limit < 0) {
+    return false;
+  }
+
+  std::vector<std::string> local_files;
+  std::vector<std::string> directories;
+  if (!EnumerateDirectory(path, directories, local_files)) {
+    return false;
+  }
+  for (const std::string& directory : directories) {
+    if (!EnumerateDirectoryRecursivelyInner(JoinPath(path, directory),
+                                            recursion_limit - 1, files)) {
+      return false;
+    }
+  }
+  for (const std::string& file : local_files) {
+    files.push_back(JoinPath(path, file));
+  }
+  return true;
+}
+
+bool EnumerateDirectoryRecursively(absl::string_view path,
+                                   std::vector<std::string>& files) {
+  constexpr int kRecursionLimit = 20;
+  return EnumerateDirectoryRecursivelyInner(path, kRecursionLimit, files);
+}
+
+}  // namespace quiche
diff --git a/quiche/common/platform/api/quiche_file_utils.h b/quiche/common/platform/api/quiche_file_utils.h
new file mode 100644
index 0000000..47723d1
--- /dev/null
+++ b/quiche/common/platform/api/quiche_file_utils.h
@@ -0,0 +1,40 @@
+// Copyright 2021 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.
+
+// This header contains basic filesystem functions for use in unit tests and CLI
+// tools.  Note that those are not 100% suitable for production use, as in, they
+// might be prone to race conditions and not always handle non-ASCII filenames
+// correctly.
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace quiche {
+
+// Join two paths in a platform-specific way.  Returns |a| if |b| is empty, and
+// vice versa.
+std::string JoinPath(absl::string_view a, absl::string_view b);
+
+// Reads the entire file into the memory.
+absl::optional<std::string> ReadFileContents(absl::string_view file);
+
+// Lists all files and directories in the directory specified by |path|. Returns
+// true on success, false on failure.
+bool EnumerateDirectory(absl::string_view path,
+                        std::vector<std::string>& directories,
+                        std::vector<std::string>& files);
+
+// Recursively enumerates all of the files in the directory and all of the
+// internal subdirectories.  Has a fairly small recursion limit.
+bool EnumerateDirectoryRecursively(absl::string_view path,
+                                   std::vector<std::string>& files);
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_
diff --git a/quiche/common/platform/api/quiche_file_utils_test.cc b/quiche/common/platform/api/quiche_file_utils_test.cc
new file mode 100644
index 0000000..68387a4
--- /dev/null
+++ b/quiche/common/platform/api/quiche_file_utils_test.cc
@@ -0,0 +1,86 @@
+#include "quiche/common/platform/api/quiche_file_utils.h"
+
+#include <vector>
+
+#include "absl/algorithm/container.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/strip.h"
+#include "absl/types/optional.h"
+#include "quiche/common/platform/api/quiche_test.h"
+
+namespace quiche {
+namespace test {
+namespace {
+
+using testing::UnorderedElementsAre;
+using testing::UnorderedElementsAreArray;
+
+TEST(QuicheFileUtilsTest, ReadFileContents) {
+  std::string path = absl::StrCat(QuicheGetCommonSourcePath(),
+                                  "/platform/api/testdir/testfile");
+  absl::optional<std::string> contents = ReadFileContents(path);
+  ASSERT_TRUE(contents.has_value());
+  EXPECT_EQ(*contents, "This is a test file.");
+}
+
+TEST(QuicheFileUtilsTest, ReadFileContentsFileNotFound) {
+  std::string path =
+      absl::StrCat(QuicheGetCommonSourcePath(),
+                   "/platform/api/testdir/file-that-does-not-exist");
+  absl::optional<std::string> contents = ReadFileContents(path);
+  EXPECT_FALSE(contents.has_value());
+}
+
+TEST(QuicheFileUtilsTest, EnumerateDirectory) {
+  std::string path =
+      absl::StrCat(QuicheGetCommonSourcePath(), "/platform/api/testdir");
+  std::vector<std::string> dirs;
+  std::vector<std::string> files;
+  bool success = EnumerateDirectory(path, dirs, files);
+  EXPECT_TRUE(success);
+  EXPECT_THAT(files, UnorderedElementsAre("testfile", "README.md"));
+  EXPECT_THAT(dirs, UnorderedElementsAre("a"));
+}
+
+TEST(QuicheFileUtilsTest, EnumerateDirectoryNoSuchDirectory) {
+  std::string path = absl::StrCat(QuicheGetCommonSourcePath(),
+                                  "/platform/api/testdir/no-such-directory");
+  std::vector<std::string> dirs;
+  std::vector<std::string> files;
+  bool success = EnumerateDirectory(path, dirs, files);
+  EXPECT_FALSE(success);
+}
+
+TEST(QuicheFileUtilsTest, EnumerateDirectoryNotADirectory) {
+  std::string path = absl::StrCat(QuicheGetCommonSourcePath(),
+                                  "/platform/api/testdir/testfile");
+  std::vector<std::string> dirs;
+  std::vector<std::string> files;
+  bool success = EnumerateDirectory(path, dirs, files);
+  EXPECT_FALSE(success);
+}
+
+TEST(QuicheFileUtilsTest, EnumerateDirectoryRecursively) {
+  std::vector<std::string> expected_paths = {"a/b/c/d/e", "a/subdir/testfile",
+                                             "a/z", "testfile", "README.md"};
+
+  std::string root_path =
+      absl::StrCat(QuicheGetCommonSourcePath(), "/platform/api/testdir");
+  for (std::string& path : expected_paths) {
+    // For Windows, use Windows path separators.
+    if (JoinPath("a", "b") == "a\\b") {
+      absl::c_replace(path, '/', '\\');
+    }
+
+    path = JoinPath(root_path, path);
+  }
+
+  std::vector<std::string> files;
+  bool success = EnumerateDirectoryRecursively(root_path, files);
+  EXPECT_TRUE(success);
+  EXPECT_THAT(files, UnorderedElementsAreArray(expected_paths));
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace quiche
diff --git a/quiche/common/platform/api/quiche_flag_utils.h b/quiche/common/platform/api/quiche_flag_utils.h
new file mode 100644
index 0000000..fcd6623
--- /dev/null
+++ b/quiche/common/platform/api/quiche_flag_utils.h
@@ -0,0 +1,19 @@
+// Copyright 2020 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_FLAG_UTILS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_FLAG_UTILS_H_
+
+#include "quiche_platform_impl/quiche_flag_utils_impl.h"
+
+#define QUICHE_RELOADABLE_FLAG_COUNT QUICHE_RELOADABLE_FLAG_COUNT_IMPL
+#define QUICHE_RELOADABLE_FLAG_COUNT_N QUICHE_RELOADABLE_FLAG_COUNT_N_IMPL
+
+#define QUICHE_RESTART_FLAG_COUNT QUICHE_RESTART_FLAG_COUNT_IMPL
+#define QUICHE_RESTART_FLAG_COUNT_N QUICHE_RESTART_FLAG_COUNT_N_IMPL
+
+#define QUICHE_CODE_COUNT QUICHE_CODE_COUNT_IMPL
+#define QUICHE_CODE_COUNT_N QUICHE_CODE_COUNT_N_IMPL
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_FLAG_UTILS_H_
diff --git a/quiche/common/platform/api/quiche_flags.h b/quiche/common/platform/api/quiche_flags.h
new file mode 100644
index 0000000..8b26edb
--- /dev/null
+++ b/quiche/common/platform/api/quiche_flags.h
@@ -0,0 +1,21 @@
+// Copyright 2020 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_FLAGS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_FLAGS_H_
+
+#include "quiche_platform_impl/quiche_flags_impl.h"
+
+#define GetQuicheReloadableFlag(module, flag) \
+  GetQuicheReloadableFlagImpl(module, flag)
+#define SetQuicheReloadableFlag(module, flag, value) \
+  SetQuicheReloadableFlagImpl(module, flag, value)
+#define GetQuicheRestartFlag(module, flag) \
+  GetQuicheRestartFlagImpl(module, flag)
+#define SetQuicheRestartFlag(module, flag, value) \
+  SetQuicheRestartFlagImpl(module, flag, value)
+#define GetQuicheFlag(flag) GetQuicheFlagImpl(flag)
+#define SetQuicheFlag(flag, value) SetQuicheFlagImpl(flag, value)
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_FLAGS_H_
diff --git a/quiche/common/platform/api/quiche_hostname_utils.cc b/quiche/common/platform/api/quiche_hostname_utils.cc
new file mode 100644
index 0000000..19ac83e
--- /dev/null
+++ b/quiche/common/platform/api/quiche_hostname_utils.cc
@@ -0,0 +1,109 @@
+// 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.
+
+#include "quiche/common/platform/api/quiche_hostname_utils.h"
+
+#include <string>
+
+#include "absl/strings/string_view.h"
+#include "url/url_canon.h"
+#include "url/url_canon_stdstring.h"
+#include "quiche/common/platform/api/quiche_logging.h"
+
+namespace quiche {
+
+// TODO(vasilvv): the functions below are forked from Chromium's
+// net/base/url_util.h; those should be moved to googleurl.
+namespace {
+
+std::string CanonicalizeHost(absl::string_view host,
+                             url::CanonHostInfo* host_info) {
+  // Try to canonicalize the host.
+  const url::Component raw_host_component(0, static_cast<int>(host.length()));
+  std::string canon_host;
+  url::StdStringCanonOutput canon_host_output(&canon_host);
+  url::CanonicalizeHostVerbose(host.data(), raw_host_component,
+                               &canon_host_output, host_info);
+
+  if (host_info->out_host.is_nonempty() &&
+      host_info->family != url::CanonHostInfo::BROKEN) {
+    // Success!  Assert that there's no extra garbage.
+    canon_host_output.Complete();
+    QUICHE_DCHECK_EQ(host_info->out_host.len,
+                     static_cast<int>(canon_host.length()));
+  } else {
+    // Empty host, or canonicalization failed.  We'll return empty.
+    canon_host.clear();
+  }
+
+  return canon_host;
+}
+
+bool IsHostCharAlphanumeric(char c) {
+  // We can just check lowercase because uppercase characters have already been
+  // normalized.
+  return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'));
+}
+
+bool IsCanonicalizedHostCompliant(const std::string& host) {
+  if (host.empty()) {
+    return false;
+  }
+
+  bool in_component = false;
+  bool most_recent_component_started_alphanumeric = false;
+
+  for (char c : host) {
+    if (!in_component) {
+      most_recent_component_started_alphanumeric = IsHostCharAlphanumeric(c);
+      if (!most_recent_component_started_alphanumeric && (c != '-') &&
+          (c != '_')) {
+        return false;
+      }
+      in_component = true;
+    } else if (c == '.') {
+      in_component = false;
+    } else if (!IsHostCharAlphanumeric(c) && (c != '-') && (c != '_')) {
+      return false;
+    }
+  }
+
+  return most_recent_component_started_alphanumeric;
+}
+
+}  // namespace
+
+// static
+bool QuicheHostnameUtils::IsValidSNI(absl::string_view sni) {
+  // TODO(rtenneti): Support RFC2396 hostname.
+  // NOTE: Microsoft does NOT enforce this spec, so if we throw away hostnames
+  // based on the above spec, we may be losing some hostnames that windows
+  // would consider valid. By far the most common hostname character NOT
+  // accepted by the above spec is '_'.
+  url::CanonHostInfo host_info;
+  std::string canonicalized_host = CanonicalizeHost(sni, &host_info);
+  return !host_info.IsIPAddress() &&
+         IsCanonicalizedHostCompliant(canonicalized_host);
+}
+
+// static
+std::string QuicheHostnameUtils::NormalizeHostname(absl::string_view hostname) {
+  url::CanonHostInfo host_info;
+  std::string host = CanonicalizeHost(hostname, &host_info);
+
+  // Walk backwards over the string, stopping at the first trailing dot.
+  size_t host_end = host.length();
+  while (host_end != 0 && host[host_end - 1] == '.') {
+    host_end--;
+  }
+
+  // Erase the trailing dots.
+  if (host_end != host.length()) {
+    host.erase(host_end, host.length() - host_end);
+  }
+
+  return host;
+}
+
+}  // namespace quiche
diff --git a/quiche/common/platform/api/quiche_hostname_utils.h b/quiche/common/platform/api/quiche_hostname_utils.h
new file mode 100644
index 0000000..00c611f
--- /dev/null
+++ b/quiche/common/platform/api/quiche_hostname_utils.h
@@ -0,0 +1,33 @@
+// 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_HOSTNAME_UTILS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_HOSTNAME_UTILS_H_
+
+#include <string>
+
+#include "absl/strings/string_view.h"
+#include "quiche/common/platform/api/quiche_export.h"
+
+namespace quiche {
+
+class QUICHE_EXPORT_PRIVATE QuicheHostnameUtils {
+ public:
+  QuicheHostnameUtils() = delete;
+
+  // Returns true if the sni is valid, false otherwise.
+  //  (1) disallow IP addresses;
+  //  (2) check that the hostname contains valid characters only; and
+  //  (3) contains at least one dot.
+  static bool IsValidSNI(absl::string_view sni);
+
+  // Canonicalizes the specified hostname.  This involves a wide variety of
+  // transformations, including lowercasing, removing trailing dots and IDNA
+  // conversion.
+  static std::string NormalizeHostname(absl::string_view hostname);
+};
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_HOSTNAME_UTILS_H_
diff --git a/quiche/common/platform/api/quiche_hostname_utils_test.cc b/quiche/common/platform/api/quiche_hostname_utils_test.cc
new file mode 100644
index 0000000..5d52c4f
--- /dev/null
+++ b/quiche/common/platform/api/quiche_hostname_utils_test.cc
@@ -0,0 +1,89 @@
+// 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.
+
+#include "quiche/common/platform/api/quiche_hostname_utils.h"
+
+#include <string>
+
+#include "absl/base/macros.h"
+#include "quiche/common/platform/api/quiche_test.h"
+
+namespace quiche {
+namespace test {
+namespace {
+
+class QuicheHostnameUtilsTest : public QuicheTest {};
+
+TEST_F(QuicheHostnameUtilsTest, IsValidSNI) {
+  // IP as SNI.
+  EXPECT_FALSE(QuicheHostnameUtils::IsValidSNI("192.168.0.1"));
+  // SNI without any dot.
+  EXPECT_TRUE(QuicheHostnameUtils::IsValidSNI("somedomain"));
+  // Invalid by RFC2396 but unfortunately domains of this form exist.
+  EXPECT_TRUE(QuicheHostnameUtils::IsValidSNI("some_domain.com"));
+  // An empty string must be invalid otherwise the QUIC client will try sending
+  // it.
+  EXPECT_FALSE(QuicheHostnameUtils::IsValidSNI(""));
+
+  // Valid SNI
+  EXPECT_TRUE(QuicheHostnameUtils::IsValidSNI("test.google.com"));
+}
+
+TEST_F(QuicheHostnameUtilsTest, NormalizeHostname) {
+  // clang-format off
+  struct {
+    const char *input, *expected;
+  } tests[] = {
+      {
+          "www.google.com",
+          "www.google.com",
+      },
+      {
+          "WWW.GOOGLE.COM",
+          "www.google.com",
+      },
+      {
+          "www.google.com.",
+          "www.google.com",
+      },
+      {
+          "www.google.COM.",
+          "www.google.com",
+      },
+      {
+          "www.google.com..",
+          "www.google.com",
+      },
+      {
+          "www.google.com........",
+          "www.google.com",
+      },
+      {
+          "",
+          "",
+      },
+      {
+          ".",
+          "",
+      },
+      {
+          "........",
+          "",
+      },
+      {
+          "\xe5\x85\x89.google.com",
+          "xn--54q.google.com",
+      },
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < ABSL_ARRAYSIZE(tests); ++i) {
+    EXPECT_EQ(std::string(tests[i].expected),
+              QuicheHostnameUtils::NormalizeHostname(tests[i].input));
+  }
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace quiche
diff --git a/quiche/common/platform/api/quiche_iovec.h b/quiche/common/platform/api/quiche_iovec.h
new file mode 100644
index 0000000..351e627
--- /dev/null
+++ b/quiche/common/platform/api/quiche_iovec.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2018 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_IOVEC_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_IOVEC_H_
+
+#include <cstddef>
+#include <type_traits>
+
+#include "quiche_platform_impl/quiche_iovec_impl.h"
+
+// The impl header has to export struct iovec, or a POSIX-compatible polyfill.
+// Below, we mostly assert that what we have is appropriate.
+static_assert(std::is_standard_layout<struct iovec>::value,
+              "iovec has to be a standard-layout struct");
+
+static_assert(offsetof(struct iovec, iov_base) < sizeof(struct iovec),
+              "iovec has to have iov_base");
+static_assert(offsetof(struct iovec, iov_len) < sizeof(struct iovec),
+              "iovec has to have iov_len");
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_IOVEC_H_
diff --git a/quiche/common/platform/api/quiche_logging.h b/quiche/common/platform/api/quiche_logging.h
new file mode 100644
index 0000000..940d492
--- /dev/null
+++ b/quiche/common/platform/api/quiche_logging.h
@@ -0,0 +1,59 @@
+// 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_LOGGING_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_LOGGING_H_
+
+#include "quiche_platform_impl/quiche_logging_impl.h"
+
+// Please note following QUICHE_LOG are platform dependent:
+// INFO severity can be degraded (to VLOG(1) or DVLOG(1)).
+// Some platforms may not support QUICHE_LOG_FIRST_N or QUICHE_LOG_EVERY_N_SEC,
+// and they would simply be translated to LOG.
+
+#define QUICHE_DVLOG(verbose_level) QUICHE_DVLOG_IMPL(verbose_level)
+#define QUICHE_DVLOG_IF(verbose_level, condition) \
+  QUICHE_DVLOG_IF_IMPL(verbose_level, condition)
+#define QUICHE_DLOG(severity) QUICHE_DLOG_IMPL(severity)
+#define QUICHE_DLOG_IF(severity, condition) \
+  QUICHE_DLOG_IF_IMPL(severity, condition)
+#define QUICHE_VLOG(verbose_level) QUICHE_VLOG_IMPL(verbose_level)
+#define QUICHE_LOG(severity) QUICHE_LOG_IMPL(severity)
+#define QUICHE_LOG_FIRST_N(severity, n) QUICHE_LOG_FIRST_N_IMPL(severity, n)
+#define QUICHE_LOG_EVERY_N_SEC(severity, seconds) \
+  QUICHE_LOG_EVERY_N_SEC_IMPL(severity, seconds)
+#define QUICHE_LOG_IF(severity, condition) \
+  QUICHE_LOG_IF_IMPL(severity, condition)
+
+#define QUICHE_PREDICT_FALSE(x) QUICHE_PREDICT_FALSE_IMPL(x)
+#define QUICHE_PREDICT_TRUE(x) QUICHE_PREDICT_TRUE_IMPL(x)
+
+// This is a noop in release build.
+#define QUICHE_NOTREACHED() QUICHE_NOTREACHED_IMPL()
+
+#define QUICHE_PLOG(severity) QUICHE_PLOG_IMPL(severity)
+
+#define QUICHE_DLOG_INFO_IS_ON() QUICHE_DLOG_INFO_IS_ON_IMPL()
+#define QUICHE_LOG_INFO_IS_ON() QUICHE_LOG_INFO_IS_ON_IMPL()
+#define QUICHE_LOG_WARNING_IS_ON() QUICHE_LOG_WARNING_IS_ON_IMPL()
+#define QUICHE_LOG_ERROR_IS_ON() QUICHE_LOG_ERROR_IS_ON_IMPL()
+
+#define QUICHE_CHECK(condition) QUICHE_CHECK_IMPL(condition)
+#define QUICHE_CHECK_OK(condition) QUICHE_CHECK_OK_IMPL(condition)
+#define QUICHE_CHECK_EQ(val1, val2) QUICHE_CHECK_EQ_IMPL(val1, val2)
+#define QUICHE_CHECK_NE(val1, val2) QUICHE_CHECK_NE_IMPL(val1, val2)
+#define QUICHE_CHECK_LE(val1, val2) QUICHE_CHECK_LE_IMPL(val1, val2)
+#define QUICHE_CHECK_LT(val1, val2) QUICHE_CHECK_LT_IMPL(val1, val2)
+#define QUICHE_CHECK_GE(val1, val2) QUICHE_CHECK_GE_IMPL(val1, val2)
+#define QUICHE_CHECK_GT(val1, val2) QUICHE_CHECK_GT_IMPL(val1, val2)
+
+#define QUICHE_DCHECK(condition) QUICHE_DCHECK_IMPL(condition)
+#define QUICHE_DCHECK_EQ(val1, val2) QUICHE_DCHECK_EQ_IMPL(val1, val2)
+#define QUICHE_DCHECK_NE(val1, val2) QUICHE_DCHECK_NE_IMPL(val1, val2)
+#define QUICHE_DCHECK_LE(val1, val2) QUICHE_DCHECK_LE_IMPL(val1, val2)
+#define QUICHE_DCHECK_LT(val1, val2) QUICHE_DCHECK_LT_IMPL(val1, val2)
+#define QUICHE_DCHECK_GE(val1, val2) QUICHE_DCHECK_GE_IMPL(val1, val2)
+#define QUICHE_DCHECK_GT(val1, val2) QUICHE_DCHECK_GT_IMPL(val1, val2)
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_LOGGING_H_
diff --git a/quiche/common/platform/api/quiche_lower_case_string.h b/quiche/common/platform/api/quiche_lower_case_string.h
new file mode 100644
index 0000000..dcaef3c
--- /dev/null
+++ b/quiche/common/platform/api/quiche_lower_case_string.h
@@ -0,0 +1,16 @@
+// Copyright 2022 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_LOWER_CASE_STRING_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_LOWER_CASE_STRING_H_
+
+#include "quiche_platform_impl/quiche_lower_case_string_impl.h"
+
+namespace quiche {
+
+using QuicheLowerCaseString = QuicheLowerCaseStringImpl;
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_LOWER_CASE_STRING_H_
diff --git a/quiche/common/platform/api/quiche_mem_slice.h b/quiche/common/platform/api/quiche_mem_slice.h
new file mode 100644
index 0000000..bb703a4
--- /dev/null
+++ b/quiche/common/platform/api/quiche_mem_slice.h
@@ -0,0 +1,71 @@
+// Copyright 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_MEM_SLICE_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_MEM_SLICE_H_
+
+#include <memory>
+
+#include "quiche_platform_impl/quiche_mem_slice_impl.h"
+#include "absl/strings/string_view.h"
+#include "quiche/common/platform/api/quiche_export.h"
+#include "quiche/common/quiche_buffer_allocator.h"
+
+namespace quiche {
+
+// QuicheMemSlice is a wrapper around a platform-specific I/O buffer type. It
+// may be reference counted, though QUICHE itself does not rely on that.
+class QUICHE_EXPORT_PRIVATE QuicheMemSlice {
+ public:
+  // Constructs a empty QuicheMemSlice with no underlying data.
+  QuicheMemSlice() = default;
+
+  // Constructs a QuicheMemSlice that takes ownership of |buffer|.  The length
+  // of the |buffer| must not be zero.  To construct an empty QuicheMemSlice,
+  // use the zero-argument constructor instead.
+  explicit QuicheMemSlice(QuicheBuffer buffer) : impl_(std::move(buffer)) {}
+
+  // Constructs a QuicheMemSlice that takes ownership of |buffer| allocated on
+  // heap.  |length| must not be zero.
+  QuicheMemSlice(std::unique_ptr<char[]> buffer, size_t length)
+      : impl_(std::move(buffer), length) {}
+
+  // Constructs QuicheMemSlice from |impl|. It takes the reference away from
+  // |impl|.
+  explicit QuicheMemSlice(QuicheMemSliceImpl impl) : impl_(std::move(impl)) {}
+
+  QuicheMemSlice(const QuicheMemSlice& other) = delete;
+  QuicheMemSlice& operator=(const QuicheMemSlice& other) = delete;
+
+  // Move constructors. |other| will not hold a reference to the data buffer
+  // after this call completes.
+  QuicheMemSlice(QuicheMemSlice&& other) = default;
+  QuicheMemSlice& operator=(QuicheMemSlice&& other) = default;
+
+  ~QuicheMemSlice() = default;
+
+  // Release the underlying reference. Further access the memory will result in
+  // undefined behavior.
+  void Reset() { impl_.Reset(); }
+
+  // Returns a const char pointer to underlying data buffer.
+  const char* data() const { return impl_.data(); }
+  // Returns the length of underlying data buffer.
+  size_t length() const { return impl_.length(); }
+  // Returns the representation of the underlying data as a string view.
+  absl::string_view AsStringView() const {
+    return absl::string_view(data(), length());
+  }
+
+  bool empty() const { return impl_.empty(); }
+
+  QuicheMemSliceImpl* impl() { return &impl_; }
+
+ private:
+  QuicheMemSliceImpl impl_;
+};
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_MEM_SLICE_H_
diff --git a/quiche/common/platform/api/quiche_mem_slice_test.cc b/quiche/common/platform/api/quiche_mem_slice_test.cc
new file mode 100644
index 0000000..472dbe1
--- /dev/null
+++ b/quiche/common/platform/api/quiche_mem_slice_test.cc
@@ -0,0 +1,76 @@
+// Copyright 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.
+
+#include "quiche/common/platform/api/quiche_mem_slice.h"
+
+#include <memory>
+
+#include "absl/strings/string_view.h"
+#include "quiche/common/platform/api/quiche_test.h"
+#include "quiche/common/quiche_buffer_allocator.h"
+#include "quiche/common/simple_buffer_allocator.h"
+
+namespace quiche {
+namespace test {
+namespace {
+
+class QuicheMemSliceTest : public QuicheTest {
+ public:
+  QuicheMemSliceTest() {
+    size_t length = 1024;
+    slice_ = QuicheMemSlice(QuicheBuffer(&allocator_, length));
+    orig_data_ = slice_.data();
+    orig_length_ = slice_.length();
+  }
+
+  SimpleBufferAllocator allocator_;
+  QuicheMemSlice slice_;
+  const char* orig_data_;
+  size_t orig_length_;
+};
+
+TEST_F(QuicheMemSliceTest, MoveConstruct) {
+  QuicheMemSlice moved(std::move(slice_));
+  EXPECT_EQ(moved.data(), orig_data_);
+  EXPECT_EQ(moved.length(), orig_length_);
+  EXPECT_EQ(nullptr, slice_.data());
+  EXPECT_EQ(0u, slice_.length());
+  EXPECT_TRUE(slice_.empty());
+}
+
+TEST_F(QuicheMemSliceTest, MoveAssign) {
+  QuicheMemSlice moved;
+  moved = std::move(slice_);
+  EXPECT_EQ(moved.data(), orig_data_);
+  EXPECT_EQ(moved.length(), orig_length_);
+  EXPECT_EQ(nullptr, slice_.data());
+  EXPECT_EQ(0u, slice_.length());
+  EXPECT_TRUE(slice_.empty());
+}
+
+TEST_F(QuicheMemSliceTest, SliceAllocatedOnHeap) {
+  auto buffer = std::make_unique<char[]>(128);
+  char* orig_data = buffer.get();
+  size_t used_length = 105;
+  QuicheMemSlice slice = QuicheMemSlice(std::move(buffer), used_length);
+  QuicheMemSlice moved = std::move(slice);
+  EXPECT_EQ(moved.data(), orig_data);
+  EXPECT_EQ(moved.length(), used_length);
+}
+
+TEST_F(QuicheMemSliceTest, SliceFromBuffer) {
+  const absl::string_view kTestString =
+      "RFC 9000 Release Celebration Memorial Test String";
+  auto buffer = QuicheBuffer::Copy(&allocator_, kTestString);
+  QuicheMemSlice slice(std::move(buffer));
+
+  EXPECT_EQ(buffer.data(), nullptr);  // NOLINT(bugprone-use-after-move)
+  EXPECT_EQ(buffer.size(), 0u);
+  EXPECT_EQ(slice.AsStringView(), kTestString);
+  EXPECT_EQ(slice.length(), kTestString.length());
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace quiche
diff --git a/quiche/common/platform/api/quiche_mock_log.h b/quiche/common/platform/api/quiche_mock_log.h
new file mode 100644
index 0000000..37f25de
--- /dev/null
+++ b/quiche/common/platform/api/quiche_mock_log.h
@@ -0,0 +1,18 @@
+// 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_MOCK_LOG_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_MOCK_LOG_H_
+
+#include "quiche_platform_impl/quiche_mock_log_impl.h"
+
+using QuicheMockLog = QuicheMockLogImpl;
+#define CREATE_QUICHE_MOCK_LOG(log) CREATE_QUICHE_MOCK_LOG_IMPL(log)
+
+#define EXPECT_QUICHE_LOG_CALL(log) EXPECT_QUICHE_LOG_CALL_IMPL(log)
+
+#define EXPECT_QUICHE_LOG_CALL_CONTAINS(log, level, content) \
+  EXPECT_QUICHE_LOG_CALL_CONTAINS_IMPL(log, level, content)
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_MOCK_LOG_H_
diff --git a/quiche/common/platform/api/quiche_mutex.cc b/quiche/common/platform/api/quiche_mutex.cc
new file mode 100644
index 0000000..e6d4b0c
--- /dev/null
+++ b/quiche/common/platform/api/quiche_mutex.cc
@@ -0,0 +1,31 @@
+// 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 "quiche/common/platform/api/quiche_mutex.h"
+
+namespace quiche {
+
+void QuicheMutex::WriterLock() { impl_.WriterLock(); }
+
+void QuicheMutex::WriterUnlock() { impl_.WriterUnlock(); }
+
+void QuicheMutex::ReaderLock() { impl_.ReaderLock(); }
+
+void QuicheMutex::ReaderUnlock() { impl_.ReaderUnlock(); }
+
+void QuicheMutex::AssertReaderHeld() const { impl_.AssertReaderHeld(); }
+
+QuicheReaderMutexLock::QuicheReaderMutexLock(QuicheMutex* lock) : lock_(lock) {
+  lock->ReaderLock();
+}
+
+QuicheReaderMutexLock::~QuicheReaderMutexLock() { lock_->ReaderUnlock(); }
+
+QuicheWriterMutexLock::QuicheWriterMutexLock(QuicheMutex* lock) : lock_(lock) {
+  lock->WriterLock();
+}
+
+QuicheWriterMutexLock::~QuicheWriterMutexLock() { lock_->WriterUnlock(); }
+
+}  // namespace quiche
diff --git a/quiche/common/platform/api/quiche_mutex.h b/quiche/common/platform/api/quiche_mutex.h
new file mode 100644
index 0000000..ce982bc
--- /dev/null
+++ b/quiche/common/platform/api/quiche_mutex.h
@@ -0,0 +1,101 @@
+// 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_MUTEX_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_MUTEX_H_
+
+#include "quiche_platform_impl/quiche_mutex_impl.h"
+
+#define QUICHE_EXCLUSIVE_LOCKS_REQUIRED QUICHE_EXCLUSIVE_LOCKS_REQUIRED_IMPL
+#define QUICHE_GUARDED_BY QUICHE_GUARDED_BY_IMPL
+#define QUICHE_LOCKABLE QUICHE_LOCKABLE_IMPL
+#define QUICHE_LOCKS_EXCLUDED QUICHE_LOCKS_EXCLUDED_IMPL
+#define QUICHE_SHARED_LOCKS_REQUIRED QUICHE_SHARED_LOCKS_REQUIRED_IMPL
+#define QUICHE_EXCLUSIVE_LOCK_FUNCTION QUICHE_EXCLUSIVE_LOCK_FUNCTION_IMPL
+#define QUICHE_UNLOCK_FUNCTION QUICHE_UNLOCK_FUNCTION_IMPL
+#define QUICHE_SHARED_LOCK_FUNCTION QUICHE_SHARED_LOCK_FUNCTION_IMPL
+#define QUICHE_SCOPED_LOCKABLE QUICHE_SCOPED_LOCKABLE_IMPL
+#define QUICHE_ASSERT_SHARED_LOCK QUICHE_ASSERT_SHARED_LOCK_IMPL
+
+namespace quiche {
+
+// A class representing a non-reentrant mutex in QUIC.
+class QUICHE_LOCKABLE QUICHE_EXPORT_PRIVATE QuicheMutex {
+ public:
+  QuicheMutex() = default;
+  QuicheMutex(const QuicheMutex&) = delete;
+  QuicheMutex& operator=(const QuicheMutex&) = delete;
+
+  // Block until this Mutex is free, then acquire it exclusively.
+  void WriterLock() QUICHE_EXCLUSIVE_LOCK_FUNCTION();
+
+  // Release this Mutex. Caller must hold it exclusively.
+  void WriterUnlock() QUICHE_UNLOCK_FUNCTION();
+
+  // Block until this Mutex is free or shared, then acquire a share of it.
+  void ReaderLock() QUICHE_SHARED_LOCK_FUNCTION();
+
+  // Release this Mutex. Caller could hold it in shared mode.
+  void ReaderUnlock() QUICHE_UNLOCK_FUNCTION();
+
+  // Returns immediately if current thread holds the Mutex in at least shared
+  // mode.  Otherwise, may report an error (typically by crashing with a
+  // diagnostic), or may return immediately.
+  void AssertReaderHeld() const QUICHE_ASSERT_SHARED_LOCK();
+
+ private:
+  QuicheLockImpl impl_;
+};
+
+// A helper class that acquires the given QuicheMutex shared lock while the
+// QuicheReaderMutexLock is in scope.
+class QUICHE_SCOPED_LOCKABLE QUICHE_EXPORT_PRIVATE QuicheReaderMutexLock {
+ public:
+  explicit QuicheReaderMutexLock(QuicheMutex* lock)
+      QUICHE_SHARED_LOCK_FUNCTION(lock);
+  QuicheReaderMutexLock(const QuicheReaderMutexLock&) = delete;
+  QuicheReaderMutexLock& operator=(const QuicheReaderMutexLock&) = delete;
+
+  ~QuicheReaderMutexLock() QUICHE_UNLOCK_FUNCTION();
+
+ private:
+  QuicheMutex* const lock_;
+};
+
+// A helper class that acquires the given QuicheMutex exclusive lock while the
+// QuicheWriterMutexLock is in scope.
+class QUICHE_SCOPED_LOCKABLE QUICHE_EXPORT_PRIVATE QuicheWriterMutexLock {
+ public:
+  explicit QuicheWriterMutexLock(QuicheMutex* lock)
+      QUICHE_EXCLUSIVE_LOCK_FUNCTION(lock);
+  QuicheWriterMutexLock(const QuicheWriterMutexLock&) = delete;
+  QuicheWriterMutexLock& operator=(const QuicheWriterMutexLock&) = delete;
+
+  ~QuicheWriterMutexLock() QUICHE_UNLOCK_FUNCTION();
+
+ private:
+  QuicheMutex* const lock_;
+};
+
+// A Notification allows threads to receive notification of a single occurrence
+// of a single event.
+class QUICHE_EXPORT_PRIVATE QuicheNotification {
+ public:
+  QuicheNotification() = default;
+  QuicheNotification(const QuicheNotification&) = delete;
+  QuicheNotification& operator=(const QuicheNotification&) = delete;
+
+  bool HasBeenNotified() { return impl_.HasBeenNotified(); }
+
+  void Notify() { impl_.Notify(); }
+
+  void WaitForNotification() { impl_.WaitForNotification(); }
+
+ private:
+  QuicheNotificationImpl impl_;
+};
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_MUTEX_H_
diff --git a/quiche/common/platform/api/quiche_prefetch.h b/quiche/common/platform/api/quiche_prefetch.h
new file mode 100644
index 0000000..706a709
--- /dev/null
+++ b/quiche/common/platform/api/quiche_prefetch.h
@@ -0,0 +1,39 @@
+// Copyright 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_PREFETCH_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_PREFETCH_H_
+
+#include "quiche_platform_impl/quiche_prefetch_impl.h"
+
+namespace quiche {
+
+// Move data into the cache before it is read, or "prefetch" it.
+//
+// The value of `addr` is the address of the memory to prefetch. If
+// the target and compiler support it, data prefetch instructions are
+// generated. If the prefetch is done some time before the memory is
+// read, it may be in the cache by the time the read occurs.
+//
+// The function names specify the temporal locality heuristic applied,
+// using the names of Intel prefetch instructions:
+//
+//   T0 - high degree of temporal locality; data should be left in as
+//        many levels of the cache possible
+//   T1 - moderate degree of temporal locality
+//   T2 - low degree of temporal locality
+//   Nta - no temporal locality, data need not be left in the cache
+//         after the read
+//
+// Incorrect or gratuitous use of these functions can degrade
+// performance, so use them only when representative benchmarks show
+// an improvement.
+
+inline void QuichePrefetchT0(const void* addr) {
+  return QuichePrefetchT0Impl(addr);
+}
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_PREFETCH_H_
diff --git a/quiche/common/platform/api/quiche_reference_counted.h b/quiche/common/platform/api/quiche_reference_counted.h
new file mode 100644
index 0000000..a2cc296
--- /dev/null
+++ b/quiche/common/platform/api/quiche_reference_counted.h
@@ -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.
+
+#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_
+#define QUICHE_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_
+
+#include "quiche_platform_impl/quiche_reference_counted_impl.h"
+#include "quiche/common/platform/api/quiche_export.h"
+
+namespace quiche {
+
+// Base class for explicitly reference-counted objects in QUIC.
+class QUICHE_EXPORT_PRIVATE QuicheReferenceCounted
+    : public QuicheReferenceCountedImpl {
+ public:
+  QuicheReferenceCounted() {}
+
+ protected:
+  ~QuicheReferenceCounted() override {}
+};
+
+// A class representing a reference counted pointer in QUIC.
+//
+// Construct or initialize QuicheReferenceCountedPointer from raw pointer. Here
+// raw pointer MUST be a newly created object. Reference count of a newly
+// created object is undefined, but that will be 1 after being added to
+// QuicheReferenceCountedPointer.
+// QuicheReferenceCountedPointer is used as a local variable.
+// QuicheReferenceCountedPointer<T> r_ptr(new T());
+// or, equivalently:
+// QuicheReferenceCountedPointer<T> r_ptr;
+// T* p = new T();
+// r_ptr = T;
+//
+// QuicheReferenceCountedPointer is used as a member variable:
+// MyClass::MyClass() : r_ptr(new T()) {}
+//
+// This is WRONG, since *p is not guaranteed to be newly created:
+// MyClass::MyClass(T* p) : r_ptr(p) {}
+//
+// Given an existing QuicheReferenceCountedPointer, create a duplicate that has
+// its own reference on the object:
+// QuicheReferenceCountedPointer<T> r_ptr_b(r_ptr_a);
+// or, equivalently:
+// QuicheReferenceCountedPointer<T> r_ptr_b = r_ptr_a;
+//
+// Given an existing QuicheReferenceCountedPointer, create a
+// QuicheReferenceCountedPointer that adopts the reference:
+// QuicheReferenceCountedPointer<T> r_ptr_b(std::move(r_ptr_a));
+// or, equivalently:
+// QuicheReferenceCountedPointer<T> r_ptr_b = std::move(r_ptr_a);
+
+template <class T>
+class QUICHE_NO_EXPORT QuicheReferenceCountedPointer {
+ public:
+  QuicheReferenceCountedPointer() = default;
+
+  // Constructor from raw pointer |p|. This guarantees that the reference count
+  // of *p is 1. This should be only called when a new object is created.
+  // Calling this on an already existent object does not increase its reference
+  // count.
+  explicit QuicheReferenceCountedPointer(T* p) : impl_(p) {}
+
+  // Allows implicit conversion from nullptr.
+  QuicheReferenceCountedPointer(std::nullptr_t) : impl_(nullptr) {}  // NOLINT
+
+  // Copy and copy conversion constructors. It does not take the reference away
+  // from |other| and they each end up with their own reference.
+  template <typename U>
+  QuicheReferenceCountedPointer(  // NOLINT
+      const QuicheReferenceCountedPointer<U>& other)
+      : impl_(other.impl()) {}
+  QuicheReferenceCountedPointer(const QuicheReferenceCountedPointer& other)
+      : impl_(other.impl()) {}
+
+  // Move constructors. After move, it adopts the reference from |other|.
+  template <typename U>
+  QuicheReferenceCountedPointer(
+      QuicheReferenceCountedPointer<U>&& other)  // NOLINT
+      : impl_(std::move(other.impl())) {}
+  QuicheReferenceCountedPointer(QuicheReferenceCountedPointer&& other)
+      : impl_(std::move(other.impl())) {}
+
+  ~QuicheReferenceCountedPointer() = default;
+
+  // Copy assignments.
+  QuicheReferenceCountedPointer& operator=(
+      const QuicheReferenceCountedPointer& other) {
+    impl_ = other.impl();
+    return *this;
+  }
+  template <typename U>
+  QuicheReferenceCountedPointer<T>& operator=(
+      const QuicheReferenceCountedPointer<U>& other) {
+    impl_ = other.impl();
+    return *this;
+  }
+
+  // Move assignments.
+  QuicheReferenceCountedPointer& operator=(
+      QuicheReferenceCountedPointer&& other) {
+    impl_ = std::move(other.impl());
+    return *this;
+  }
+  template <typename U>
+  QuicheReferenceCountedPointer<T>& operator=(
+      QuicheReferenceCountedPointer<U>&& other) {
+    impl_ = std::move(other.impl());
+    return *this;
+  }
+
+  // Accessors for the referenced object.
+  // operator*() and operator->() will assert() if there is no current object.
+  T& operator*() const { return *impl_; }
+  T* operator->() const { return impl_.get(); }
+
+  explicit operator bool() const { return static_cast<bool>(impl_); }
+
+  // Assignment operator on raw pointer. Drops a reference to current pointee,
+  // if any, and replaces it with |p|. This guarantees that the reference count
+  // of *p is 1. This should only be used when a new object is created.  Calling
+  // this on an already existent object is undefined behavior.
+  QuicheReferenceCountedPointer<T>& operator=(T* p) {
+    impl_ = p;
+    return *this;
+  }
+
+  // Returns the raw pointer with no change in reference count.
+  T* get() const { return impl_.get(); }
+
+  QuicheReferenceCountedPointerImpl<T>& impl() { return impl_; }
+  const QuicheReferenceCountedPointerImpl<T>& impl() const { return impl_; }
+
+  // Comparisons against same type.
+  friend bool operator==(const QuicheReferenceCountedPointer& a,
+                         const QuicheReferenceCountedPointer& b) {
+    return a.get() == b.get();
+  }
+  friend bool operator!=(const QuicheReferenceCountedPointer& a,
+                         const QuicheReferenceCountedPointer& b) {
+    return a.get() != b.get();
+  }
+
+  // Comparisons against nullptr.
+  friend bool operator==(const QuicheReferenceCountedPointer& a,
+                         std::nullptr_t) {
+    return a.get() == nullptr;
+  }
+  friend bool operator==(std::nullptr_t,
+                         const QuicheReferenceCountedPointer& b) {
+    return nullptr == b.get();
+  }
+  friend bool operator!=(const QuicheReferenceCountedPointer& a,
+                         std::nullptr_t) {
+    return a.get() != nullptr;
+  }
+  friend bool operator!=(std::nullptr_t,
+                         const QuicheReferenceCountedPointer& b) {
+    return nullptr != b.get();
+  }
+
+ private:
+  QuicheReferenceCountedPointerImpl<T> impl_;
+};
+
+}  // namespace quiche
+
+#endif  // QUICHE_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_
diff --git a/quiche/common/platform/api/quiche_reference_counted_test.cc b/quiche/common/platform/api/quiche_reference_counted_test.cc
new file mode 100644
index 0000000..7c05d7a
--- /dev/null
+++ b/quiche/common/platform/api/quiche_reference_counted_test.cc
@@ -0,0 +1,173 @@
+// 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 "quiche/common/platform/api/quiche_reference_counted.h"
+
+#include "quiche/common/platform/api/quiche_test.h"
+
+namespace quiche {
+namespace test {
+namespace {
+
+class Base : public QuicheReferenceCounted {
+ public:
+  explicit Base(bool* destroyed) : destroyed_(destroyed) {
+    *destroyed_ = false;
+  }
+
+ protected:
+  ~Base() override { *destroyed_ = true; }
+
+ private:
+  bool* destroyed_;
+};
+
+class Derived : public Base {
+ public:
+  explicit Derived(bool* destroyed) : Base(destroyed) {}
+
+ private:
+  ~Derived() override {}
+};
+
+class QuicheReferenceCountedTest : public QuicheTest {};
+
+TEST_F(QuicheReferenceCountedTest, DefaultConstructor) {
+  QuicheReferenceCountedPointer<Base> a;
+  EXPECT_EQ(nullptr, a);
+  EXPECT_EQ(nullptr, a.get());
+  EXPECT_FALSE(a);
+}
+
+TEST_F(QuicheReferenceCountedTest, ConstructFromRawPointer) {
+  bool destroyed = false;
+  {
+    QuicheReferenceCountedPointer<Base> a(new Base(&destroyed));
+    EXPECT_FALSE(destroyed);
+  }
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(QuicheReferenceCountedTest, RawPointerAssignment) {
+  bool destroyed = false;
+  {
+    QuicheReferenceCountedPointer<Base> a;
+    Base* rct = new Base(&destroyed);
+    a = rct;
+    EXPECT_FALSE(destroyed);
+  }
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(QuicheReferenceCountedTest, PointerCopy) {
+  bool destroyed = false;
+  {
+    QuicheReferenceCountedPointer<Base> a(new Base(&destroyed));
+    {
+      QuicheReferenceCountedPointer<Base> b(a);
+      EXPECT_EQ(a, b);
+      EXPECT_FALSE(destroyed);
+    }
+    EXPECT_FALSE(destroyed);
+  }
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(QuicheReferenceCountedTest, PointerCopyAssignment) {
+  bool destroyed = false;
+  {
+    QuicheReferenceCountedPointer<Base> a(new Base(&destroyed));
+    {
+      QuicheReferenceCountedPointer<Base> b = a;
+      EXPECT_EQ(a, b);
+      EXPECT_FALSE(destroyed);
+    }
+    EXPECT_FALSE(destroyed);
+  }
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(QuicheReferenceCountedTest, PointerCopyFromOtherType) {
+  bool destroyed = false;
+  {
+    QuicheReferenceCountedPointer<Derived> a(new Derived(&destroyed));
+    {
+      QuicheReferenceCountedPointer<Base> b(a);
+      EXPECT_EQ(a.get(), b.get());
+      EXPECT_FALSE(destroyed);
+    }
+    EXPECT_FALSE(destroyed);
+  }
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(QuicheReferenceCountedTest, PointerCopyAssignmentFromOtherType) {
+  bool destroyed = false;
+  {
+    QuicheReferenceCountedPointer<Derived> a(new Derived(&destroyed));
+    {
+      QuicheReferenceCountedPointer<Base> b = a;
+      EXPECT_EQ(a.get(), b.get());
+      EXPECT_FALSE(destroyed);
+    }
+    EXPECT_FALSE(destroyed);
+  }
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(QuicheReferenceCountedTest, PointerMove) {
+  bool destroyed = false;
+  QuicheReferenceCountedPointer<Base> a(new Derived(&destroyed));
+  EXPECT_FALSE(destroyed);
+  QuicheReferenceCountedPointer<Base> b(std::move(a));
+  EXPECT_FALSE(destroyed);
+  EXPECT_NE(nullptr, b);
+  EXPECT_EQ(nullptr, a);  // NOLINT
+
+  b = nullptr;
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(QuicheReferenceCountedTest, PointerMoveAssignment) {
+  bool destroyed = false;
+  QuicheReferenceCountedPointer<Base> a(new Derived(&destroyed));
+  EXPECT_FALSE(destroyed);
+  QuicheReferenceCountedPointer<Base> b = std::move(a);
+  EXPECT_FALSE(destroyed);
+  EXPECT_NE(nullptr, b);
+  EXPECT_EQ(nullptr, a);  // NOLINT
+
+  b = nullptr;
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(QuicheReferenceCountedTest, PointerMoveFromOtherType) {
+  bool destroyed = false;
+  QuicheReferenceCountedPointer<Derived> a(new Derived(&destroyed));
+  EXPECT_FALSE(destroyed);
+  QuicheReferenceCountedPointer<Base> b(std::move(a));
+  EXPECT_FALSE(destroyed);
+  EXPECT_NE(nullptr, b);
+  EXPECT_EQ(nullptr, a);  // NOLINT
+
+  b = nullptr;
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(QuicheReferenceCountedTest, PointerMoveAssignmentFromOtherType) {
+  bool destroyed = false;
+  QuicheReferenceCountedPointer<Derived> a(new Derived(&destroyed));
+  EXPECT_FALSE(destroyed);
+  QuicheReferenceCountedPointer<Base> b = std::move(a);
+  EXPECT_FALSE(destroyed);
+  EXPECT_NE(nullptr, b);
+  EXPECT_EQ(nullptr, a);  // NOLINT
+
+  b = nullptr;
+  EXPECT_TRUE(destroyed);
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace quiche
diff --git a/quiche/common/platform/api/quiche_server_stats.h b/quiche/common/platform/api/quiche_server_stats.h
new file mode 100644
index 0000000..e8ad499
--- /dev/null
+++ b/quiche/common/platform/api/quiche_server_stats.h
@@ -0,0 +1,82 @@
+// Copyright 2018 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_SERVER_STATS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_SERVER_STATS_H_
+
+#include "quiche_platform_impl/quiche_server_stats_impl.h"
+
+namespace quiche {
+
+//------------------------------------------------------------------------------
+// Enumeration histograms.
+//
+// Sample usage:
+//   // In Chrome, these values are persisted to logs. Entries should not be
+//   // renumbered and numeric values should never be reused.
+//   enum class MyEnum {
+//     FIRST_VALUE = 0,
+//     SECOND_VALUE = 1,
+//     ...
+//     FINAL_VALUE = N,
+//     COUNT
+//   };
+//   QUICHE_SERVER_HISTOGRAM_ENUM("My.Enumeration", MyEnum::SOME_VALUE,
+//   MyEnum::COUNT, "Number of time $foo equals to some enum value");
+//
+// Note: The value in |sample| must be strictly less than |enum_size|.
+
+#define QUICHE_SERVER_HISTOGRAM_ENUM(name, sample, enum_size, docstring) \
+  QUICHE_SERVER_HISTOGRAM_ENUM_IMPL(name, sample, enum_size, docstring)
+
+//------------------------------------------------------------------------------
+// Histogram for boolean values.
+
+// Sample usage:
+//   QUICHE_SERVER_HISTOGRAM_BOOL("My.Boolean", bool,
+//   "Number of times $foo is true or false");
+#define QUICHE_SERVER_HISTOGRAM_BOOL(name, sample, docstring) \
+  QUICHE_SERVER_HISTOGRAM_BOOL_IMPL(name, sample, docstring)
+
+//------------------------------------------------------------------------------
+// Timing histograms. These are used for collecting timing data (generally
+// latencies).
+
+// These macros create exponentially sized histograms (lengths of the bucket
+// ranges exponentially increase as the sample range increases). The units for
+// sample and max are unspecified, but they must be the same for one histogram.
+
+// Sample usage:
+//   QUICHE_SERVER_HISTOGRAM_TIMES("Very.Long.Timing.Histogram", time_delta,
+//       QuicTime::Delta::FromSeconds(1), QuicTime::Delta::FromSecond(3600 *
+//       24), 100, "Time spent in doing operation.");
+#define QUICHE_SERVER_HISTOGRAM_TIMES(name, sample, min, max, bucket_count, \
+                                      docstring)                            \
+  QUICHE_SERVER_HISTOGRAM_TIMES_IMPL(name, sample, min, max, bucket_count,  \
+                                     docstring)
+
+//------------------------------------------------------------------------------
+// Count histograms. These are used for collecting numeric data.
+
+// These macros default to exponential histograms - i.e. the lengths of the
+// bucket ranges exponentially increase as the sample range increases.
+
+// All of these macros must be called with |name| as a runtime constant.
+
+// Any data outside the range here will be put in underflow and overflow
+// buckets. Min values should be >=1 as emitted 0s will still go into the
+// underflow bucket.
+
+// Sample usage:
+//   QUICHE_SERVER_SERVER_HISTOGRAM_CUSTOM_COUNTS("My.Histogram", 1, 100000000,
+//   100, "Counters of hitting certian code.");
+
+#define QUICHE_SERVER_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count, \
+                                       docstring)                            \
+  QUICHE_SERVER_HISTOGRAM_COUNTS_IMPL(name, sample, min, max, bucket_count,  \
+                                      docstring)
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_SERVER_STATS_H_
diff --git a/quiche/common/platform/api/quiche_stack_trace.h b/quiche/common/platform/api/quiche_stack_trace.h
new file mode 100644
index 0000000..876cc98
--- /dev/null
+++ b/quiche/common/platform/api/quiche_stack_trace.h
@@ -0,0 +1,18 @@
+// 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_STACK_TRACE_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_STACK_TRACE_H_
+
+#include <string>
+
+#include "quiche_platform_impl/quiche_stack_trace_impl.h"
+
+namespace quiche {
+
+inline std::string QuicheStackTrace() { return QuicheStackTraceImpl(); }
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_STACK_TRACE_H_
diff --git a/quiche/common/platform/api/quiche_stream_buffer_allocator.h b/quiche/common/platform/api/quiche_stream_buffer_allocator.h
new file mode 100644
index 0000000..16e5e7c
--- /dev/null
+++ b/quiche/common/platform/api/quiche_stream_buffer_allocator.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2019 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_STREAM_BUFFER_ALLOCATOR_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_STREAM_BUFFER_ALLOCATOR_H_
+
+#include "quiche_platform_impl/quiche_stream_buffer_allocator_impl.h"
+
+namespace quiche {
+
+using QuicheStreamBufferAllocator = QuicheStreamBufferAllocatorImpl;
+
+}
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_STREAM_BUFFER_ALLOCATOR_H_
diff --git a/quiche/common/platform/api/quiche_system_event_loop.h b/quiche/common/platform/api/quiche_system_event_loop.h
new file mode 100644
index 0000000..41ed45a
--- /dev/null
+++ b/quiche/common/platform/api/quiche_system_event_loop.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2019 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_SYSTEM_EVENT_LOOP_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_SYSTEM_EVENT_LOOP_H_
+
+#include "quiche_platform_impl/quiche_system_event_loop_impl.h"
+
+namespace quiche {
+
+inline void QuicheRunSystemEventLoopIteration() {
+  QuicheRunSystemEventLoopIterationImpl();
+}
+
+using QuicheSystemEventLoop = QuicheSystemEventLoopImpl;
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_SYSTEM_EVENT_LOOP_H_
diff --git a/quiche/common/platform/api/quiche_test.h b/quiche/common/platform/api/quiche_test.h
new file mode 100644
index 0000000..afc298a
--- /dev/null
+++ b/quiche/common/platform/api/quiche_test.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2019 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_TEST_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_H_
+
+#include "quiche_platform_impl/quiche_test_impl.h"
+
+using QuicheTest = quiche::test::QuicheTest;
+
+template <class T>
+using QuicheTestWithParam = quiche::test::QuicheTestWithParamImpl<T>;
+
+using QuicheFlagSaver = QuicheFlagSaverImpl;
+
+// Class which needs to be instantiated in tests which use threads.
+using ScopedEnvironmentForThreads = ScopedEnvironmentForThreadsImpl;
+
+inline std::string QuicheGetTestMemoryCachePath() {
+  return QuicheGetTestMemoryCachePathImpl();
+}
+
+namespace quiche {
+namespace test {
+
+// Returns the path to quiche/common directory where the test data could be
+// located.
+inline std::string QuicheGetCommonSourcePath() {
+  return QuicheGetCommonSourcePathImpl();
+}
+
+}  // namespace test
+}  // namespace quiche
+
+#define EXPECT_QUICHE_DEBUG_DEATH(condition, message) \
+  EXPECT_QUICHE_DEBUG_DEATH_IMPL(condition, message)
+
+#define QUICHE_TEST_DISABLED_IN_CHROME(name) \
+  QUICHE_TEST_DISABLED_IN_CHROME_IMPL(name)
+
+#define QUICHE_SLOW_TEST(test) QUICHE_SLOW_TEST_IMPL(test)
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_H_
diff --git a/quiche/common/platform/api/quiche_test_helpers.h b/quiche/common/platform/api/quiche_test_helpers.h
new file mode 100644
index 0000000..2dbe611
--- /dev/null
+++ b/quiche/common/platform/api/quiche_test_helpers.h
@@ -0,0 +1,8 @@
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_HELPERS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_HELPERS_H_
+
+#include "quiche_platform_impl/quiche_test_helpers_impl.h"
+
+#define EXPECT_QUICHE_BUG EXPECT_QUICHE_BUG_IMPL
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_HELPERS_H_
diff --git a/quiche/common/platform/api/quiche_test_loopback.cc b/quiche/common/platform/api/quiche_test_loopback.cc
new file mode 100644
index 0000000..07d3ccf
--- /dev/null
+++ b/quiche/common/platform/api/quiche_test_loopback.cc
@@ -0,0 +1,21 @@
+// 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.
+
+#include "quiche/common/platform/api/quiche_test_loopback.h"
+
+namespace quiche {
+
+quic::IpAddressFamily AddressFamilyUnderTest() {
+  return AddressFamilyUnderTestImpl();
+}
+
+quic::QuicIpAddress TestLoopback4() { return TestLoopback4Impl(); }
+
+quic::QuicIpAddress TestLoopback6() { return TestLoopback6Impl(); }
+
+quic::QuicIpAddress TestLoopback() { return TestLoopbackImpl(); }
+
+quic::QuicIpAddress TestLoopback(int index) { return TestLoopbackImpl(index); }
+
+}  // namespace quiche
diff --git a/quiche/common/platform/api/quiche_test_loopback.h b/quiche/common/platform/api/quiche_test_loopback.h
new file mode 100644
index 0000000..b493ca4
--- /dev/null
+++ b/quiche/common/platform/api/quiche_test_loopback.h
@@ -0,0 +1,34 @@
+// 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_TEST_LOOPBACK_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_LOOPBACK_H_
+
+#include "quiche_platform_impl/quiche_test_loopback_impl.h"
+#include "quiche/quic/platform/api/quic_ip_address.h"
+#include "quiche/quic/platform/api/quic_ip_address_family.h"
+
+namespace quiche {
+
+// Returns the address family (IPv4 or IPv6) used to run test under.
+quic::IpAddressFamily AddressFamilyUnderTest();
+
+// Returns an IPv4 loopback address.
+quic::QuicIpAddress TestLoopback4();
+
+// Returns the only IPv6 loopback address.
+quic::QuicIpAddress TestLoopback6();
+
+// Returns an appropriate IPv4/Ipv6 loopback address based upon whether the
+// test's environment.
+quic::QuicIpAddress TestLoopback();
+
+// If address family under test is IPv4, returns an indexed IPv4 loopback
+// address. If address family under test is IPv6, the address returned is
+// platform-dependent.
+quic::QuicIpAddress TestLoopback(int index);
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_LOOPBACK_H_
diff --git a/quiche/common/platform/api/quiche_test_output.h b/quiche/common/platform/api/quiche_test_output.h
new file mode 100644
index 0000000..b28a8a7
--- /dev/null
+++ b/quiche/common/platform/api/quiche_test_output.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2018 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_TEST_OUTPUT_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_OUTPUT_H_
+
+#include "quiche_platform_impl/quiche_test_output_impl.h"
+#include "absl/strings/string_view.h"
+
+namespace quiche {
+
+// Save |data| into ${QUICHE_TEST_OUTPUT_DIR}/filename. If a file with the same
+// path already exists, overwrite it.
+inline void QuicheSaveTestOutput(absl::string_view filename,
+                                 absl::string_view data) {
+  QuicheSaveTestOutputImpl(filename, data);
+}
+
+// Load the content of ${QUICHE_TEST_OUTPUT_DIR}/filename into |*data|.
+// Return whether it is successfully loaded.
+inline bool QuicheLoadTestOutput(absl::string_view filename,
+                                 std::string* data) {
+  return QuicheLoadTestOutputImpl(filename, data);
+}
+
+// Records a QUIC trace file(.qtr) into a directory specified by the
+// QUICHE_TEST_OUTPUT_DIR environment variable.  Assumes that it's called from a
+// unit test.
+//
+// The |identifier| is a human-readable identifier that will be combined with
+// the name of the unit test and a timestamp.  |data| is the serialized
+// quic_trace.Trace protobuf that is being recorded into the file.
+inline void QuicheRecordTrace(absl::string_view identifier,
+                              absl::string_view data) {
+  QuicheRecordTraceImpl(identifier, data);
+}
+
+}  // namespace quiche
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_OUTPUT_H_
diff --git a/quiche/common/platform/api/quiche_testvalue.h b/quiche/common/platform/api/quiche_testvalue.h
new file mode 100644
index 0000000..ec50cd9
--- /dev/null
+++ b/quiche/common/platform/api/quiche_testvalue.h
@@ -0,0 +1,25 @@
+// Copyright 2020 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_TESTVALUE_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_TESTVALUE_H_
+
+#include "quiche_platform_impl/quiche_testvalue_impl.h"
+#include "absl/strings/string_view.h"
+
+namespace quiche {
+
+// Interface allowing injection of test-specific code in production codepaths.
+// |label| is an arbitrary value identifying the location, and |var| is a
+// pointer to the value to be modified.
+//
+// Note that this method does nothing in Chromium.
+template <class T>
+void AdjustTestValue(absl::string_view label, T* var) {
+  AdjustTestValueImpl(label, var);
+}
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_TESTVALUE_H_
diff --git a/quiche/common/platform/api/quiche_thread.h b/quiche/common/platform/api/quiche_thread.h
new file mode 100644
index 0000000..96a596b
--- /dev/null
+++ b/quiche/common/platform/api/quiche_thread.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2018 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_THREAD_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_H_
+
+#include <string>
+
+#include "quiche_platform_impl/quiche_thread_impl.h"
+#include "quiche/common/platform/api/quiche_export.h"
+
+namespace quiche {
+
+// A class representing a thread of execution in QUIC.
+class QUICHE_EXPORT_PRIVATE QuicheThread : public QuicheThreadImpl {
+ public:
+  QuicheThread(const std::string& string) : QuicheThreadImpl(string) {}
+  QuicheThread(const QuicheThread&) = delete;
+  QuicheThread& operator=(const QuicheThread&) = delete;
+
+  // Impl defines a virtual void Run() method which subclasses
+  // must implement.
+};
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_H_
diff --git a/quiche/common/platform/api/quiche_thread_local.h b/quiche/common/platform/api/quiche_thread_local.h
new file mode 100644
index 0000000..c2d58e1
--- /dev/null
+++ b/quiche/common/platform/api/quiche_thread_local.h
@@ -0,0 +1,27 @@
+// Copyright 2021 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_THREAD_LOCAL_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_LOCAL_H_
+
+#include "quiche_platform_impl/quiche_thread_local_impl.h"
+
+// Define a thread local |type*| with |name|. Conceptually, this is a
+//
+//  static thread_local type* name = nullptr;
+//
+// It is wrapped in a macro because the thread_local keyword is banned from
+// Chromium.
+#define DEFINE_QUICHE_THREAD_LOCAL_POINTER(name, type) \
+  DEFINE_QUICHE_THREAD_LOCAL_POINTER_IMPL(name, type)
+
+// Get the value of |name| for the current thread.
+#define GET_QUICHE_THREAD_LOCAL_POINTER(name) \
+  GET_QUICHE_THREAD_LOCAL_POINTER_IMPL(name)
+
+// Set the |value| of |name| for the current thread.
+#define SET_QUICHE_THREAD_LOCAL_POINTER(name, value) \
+  SET_QUICHE_THREAD_LOCAL_POINTER_IMPL(name, value)
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_LOCAL_H_
diff --git a/quiche/common/platform/api/quiche_time_utils.h b/quiche/common/platform/api/quiche_time_utils.h
new file mode 100644
index 0000000..9a957b0
--- /dev/null
+++ b/quiche/common/platform/api/quiche_time_utils.h
@@ -0,0 +1,31 @@
+// Copyright 2020 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_TIME_UTILS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_TIME_UTILS_H_
+
+#include <cstdint>
+
+#include "quiche_platform_impl/quiche_time_utils_impl.h"
+
+namespace quiche {
+
+// Converts a civil time specified in UTC into a number of seconds since the
+// Unix epoch.  This function is strict about validity of accepted dates.  For
+// instance, it will reject February 29 on non-leap years, or 25 hours in a day.
+// As a notable exception, 60 seconds is accepted to deal with potential leap
+// seconds.  If the date predates Unix epoch, nullopt will be returned.
+inline absl::optional<int64_t> QuicheUtcDateTimeToUnixSeconds(int year,
+                                                              int month,
+                                                              int day,
+                                                              int hour,
+                                                              int minute,
+                                                              int second) {
+  return QuicheUtcDateTimeToUnixSecondsImpl(year, month, day, hour, minute,
+                                            second);
+}
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_TIME_UTILS_H_
diff --git a/quiche/common/platform/api/quiche_time_utils_test.cc b/quiche/common/platform/api/quiche_time_utils_test.cc
new file mode 100644
index 0000000..5d09004
--- /dev/null
+++ b/quiche/common/platform/api/quiche_time_utils_test.cc
@@ -0,0 +1,51 @@
+// Copyright 2020 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 "quiche/common/platform/api/quiche_time_utils.h"
+
+#include "absl/types/optional.h"
+#include "quiche/common/platform/api/quiche_test.h"
+
+namespace quiche {
+namespace {
+
+TEST(QuicheTimeUtilsTest, Basic) {
+  EXPECT_EQ(1, QuicheUtcDateTimeToUnixSeconds(1970, 1, 1, 0, 0, 1));
+  EXPECT_EQ(365 * 86400, QuicheUtcDateTimeToUnixSeconds(1971, 1, 1, 0, 0, 0));
+  // Some arbitrary timestamps closer to the present, compared to the output of
+  // "Date(...).getTime()" from the JavaScript console.
+  EXPECT_EQ(1152966896,
+            QuicheUtcDateTimeToUnixSeconds(2006, 7, 15, 12, 34, 56));
+  EXPECT_EQ(1591130001, QuicheUtcDateTimeToUnixSeconds(2020, 6, 2, 20, 33, 21));
+
+  EXPECT_EQ(absl::nullopt,
+            QuicheUtcDateTimeToUnixSeconds(1970, 2, 29, 0, 0, 1));
+  EXPECT_NE(absl::nullopt,
+            QuicheUtcDateTimeToUnixSeconds(1972, 2, 29, 0, 0, 1));
+}
+
+TEST(QuicheTimeUtilsTest, Bounds) {
+  EXPECT_EQ(absl::nullopt,
+            QuicheUtcDateTimeToUnixSeconds(1970, 1, 32, 0, 0, 1));
+  EXPECT_EQ(absl::nullopt,
+            QuicheUtcDateTimeToUnixSeconds(1970, 4, 31, 0, 0, 1));
+  EXPECT_EQ(absl::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 1, 0, 0, 0, 1));
+  EXPECT_EQ(absl::nullopt,
+            QuicheUtcDateTimeToUnixSeconds(1970, 13, 1, 0, 0, 1));
+  EXPECT_EQ(absl::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 0, 1, 0, 0, 1));
+  EXPECT_EQ(absl::nullopt,
+            QuicheUtcDateTimeToUnixSeconds(1970, 1, 1, 24, 0, 0));
+  EXPECT_EQ(absl::nullopt,
+            QuicheUtcDateTimeToUnixSeconds(1970, 1, 1, 0, 60, 0));
+}
+
+TEST(QuicheTimeUtilsTest, LeapSecond) {
+  EXPECT_EQ(QuicheUtcDateTimeToUnixSeconds(2015, 6, 30, 23, 59, 60),
+            QuicheUtcDateTimeToUnixSeconds(2015, 7, 1, 0, 0, 0));
+  EXPECT_EQ(QuicheUtcDateTimeToUnixSeconds(2015, 6, 30, 25, 59, 60),
+            absl::nullopt);
+}
+
+}  // namespace
+}  // namespace quiche
diff --git a/quiche/common/platform/api/quiche_udp_socket_platform_api.h b/quiche/common/platform/api/quiche_udp_socket_platform_api.h
new file mode 100644
index 0000000..474e89d
--- /dev/null
+++ b/quiche/common/platform/api/quiche_udp_socket_platform_api.h
@@ -0,0 +1,29 @@
+// Copyright 2019 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_UDP_SOCKET_PLATFORM_API_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_UDP_SOCKET_PLATFORM_API_H_
+
+#include "quiche_platform_impl/quiche_udp_socket_platform_impl.h"
+
+namespace quiche {
+
+const size_t kCmsgSpaceForGooglePacketHeader =
+    kCmsgSpaceForGooglePacketHeaderImpl;
+
+inline bool GetGooglePacketHeadersFromControlMessage(
+    struct ::cmsghdr* cmsg,
+    char** packet_headers,
+    size_t* packet_headers_len) {
+  return GetGooglePacketHeadersFromControlMessageImpl(cmsg, packet_headers,
+                                                      packet_headers_len);
+}
+
+inline void SetGoogleSocketOptions(int fd) {
+  SetGoogleSocketOptionsImpl(fd);
+}
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_UDP_SOCKET_PLATFORM_API_H_
diff --git a/quiche/common/platform/api/quiche_url_utils.h b/quiche/common/platform/api/quiche_url_utils.h
new file mode 100644
index 0000000..e6c9fc9
--- /dev/null
+++ b/quiche/common/platform/api/quiche_url_utils.h
@@ -0,0 +1,38 @@
+// Copyright 2021 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_URL_UTILS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_URL_UTILS_H_
+
+#include <string>
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "quiche_platform_impl/quiche_url_utils_impl.h"
+
+namespace quiche {
+
+// Produces concrete URLs in |target| from templated ones in |uri_template|.
+// Parameters are URL-encoded. Collects the names of any expanded variables in
+// |vars_found|. Returns true if the template was parseable, false if it was
+// malformed.
+inline bool ExpandURITemplate(
+    const std::string& uri_template,
+    const absl::flat_hash_map<std::string, std::string>& parameters,
+    std::string* target,
+    absl::flat_hash_set<std::string>* vars_found = nullptr) {
+  return ExpandURITemplateImpl(uri_template, parameters, target, vars_found);
+}
+
+// Decodes a URL-encoded string and converts it to ASCII. If the decoded input
+// contains non-ASCII characters, decoding fails and absl::nullopt is returned.
+inline absl::optional<std::string> AsciiUrlDecode(absl::string_view input) {
+  return AsciiUrlDecodeImpl(input);
+}
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_URL_UTILS_H_
diff --git a/quiche/common/platform/api/quiche_url_utils_test.cc b/quiche/common/platform/api/quiche_url_utils_test.cc
new file mode 100644
index 0000000..33a30ec
--- /dev/null
+++ b/quiche/common/platform/api/quiche_url_utils_test.cc
@@ -0,0 +1,80 @@
+// Copyright 2021 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 "quiche/common/platform/api/quiche_url_utils.h"
+
+#include <set>
+#include <string>
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/types/optional.h"
+#include "quiche/common/platform/api/quiche_test.h"
+
+namespace quiche {
+namespace {
+
+void ValidateExpansion(
+    const std::string& uri_template,
+    const absl::flat_hash_map<std::string, std::string>& parameters,
+    const std::string& expected_expansion,
+    const absl::flat_hash_set<std::string>& expected_vars_found) {
+  absl::flat_hash_set<std::string> vars_found;
+  std::string target;
+  ASSERT_TRUE(
+      ExpandURITemplate(uri_template, parameters, &target, &vars_found));
+  EXPECT_EQ(expected_expansion, target);
+  EXPECT_EQ(vars_found, expected_vars_found);
+}
+
+TEST(QuicheUrlUtilsTest, Basic) {
+  ValidateExpansion("/{foo}/{bar}/", {{"foo", "123"}, {"bar", "456"}},
+                    "/123/456/", {"foo", "bar"});
+}
+
+TEST(QuicheUrlUtilsTest, ExtraParameter) {
+  ValidateExpansion("/{foo}/{bar}/{baz}/", {{"foo", "123"}, {"bar", "456"}},
+                    "/123/456//", {"foo", "bar"});
+}
+
+TEST(QuicheUrlUtilsTest, MissingParameter) {
+  ValidateExpansion("/{foo}/{baz}/", {{"foo", "123"}, {"bar", "456"}}, "/123//",
+                    {"foo"});
+}
+
+TEST(QuicheUrlUtilsTest, RepeatedParameter) {
+  ValidateExpansion("/{foo}/{bar}/{foo}/", {{"foo", "123"}, {"bar", "456"}},
+                    "/123/456/123/", {"foo", "bar"});
+}
+
+TEST(QuicheUrlUtilsTest, URLEncoding) {
+  ValidateExpansion("/{foo}/{bar}/", {{"foo", "123"}, {"bar", ":"}},
+                    "/123/%3A/", {"foo", "bar"});
+}
+
+void ValidateUrlDecode(const std::string& input,
+                       const absl::optional<std::string>& expected_output) {
+  absl::optional<std::string> decode_result = AsciiUrlDecode(input);
+  if (!expected_output.has_value()) {
+    EXPECT_FALSE(decode_result.has_value());
+    return;
+  }
+  ASSERT_TRUE(decode_result.has_value());
+  EXPECT_EQ(decode_result.value(), expected_output);
+}
+
+TEST(QuicheUrlUtilsTest, DecodeNoChange) {
+  ValidateUrlDecode("foobar", "foobar");
+}
+
+TEST(QuicheUrlUtilsTest, DecodeReplace) {
+  ValidateUrlDecode("%7Bfoobar%7D", "{foobar}");
+}
+
+TEST(QuicheUrlUtilsTest, DecodeFail) {
+  ValidateUrlDecode("%FF", absl::nullopt);
+}
+
+}  // namespace
+}  // namespace quiche