Lift generic functionality from QuicDataReader/QuicDataWriter into Quiche

The QUIC-specific functions stay in QuicDataReader/QuicDataWriter. Generally useful functions are moved into QuicheDataReader/QuicheDataWriter.

gfe-relnote: n/a, no functional change
PiperOrigin-RevId: 288584295
Change-Id: I53b102f56f43019a89db0aa624898ed44bb6ec11
diff --git a/common/quiche_data_reader.cc b/common/quiche_data_reader.cc
new file mode 100644
index 0000000..9842add
--- /dev/null
+++ b/common/quiche_data_reader.cc
@@ -0,0 +1,189 @@
+// Copyright (c) 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 "net/third_party/quiche/src/common/quiche_data_reader.h"
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+namespace quiche {
+
+QuicheDataReader::QuicheDataReader(quiche::QuicheStringPiece data)
+    : QuicheDataReader(data.data(), data.length(), quiche::NETWORK_BYTE_ORDER) {
+}
+
+QuicheDataReader::QuicheDataReader(const char* data, const size_t len)
+    : QuicheDataReader(data, len, quiche::NETWORK_BYTE_ORDER) {}
+
+QuicheDataReader::QuicheDataReader(const char* data,
+                                   const size_t len,
+                                   quiche::Endianness endianness)
+    : data_(data), len_(len), pos_(0), endianness_(endianness) {}
+
+bool QuicheDataReader::ReadUInt8(uint8_t* result) {
+  return ReadBytes(result, sizeof(*result));
+}
+
+bool QuicheDataReader::ReadUInt16(uint16_t* result) {
+  if (!ReadBytes(result, sizeof(*result))) {
+    return false;
+  }
+  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+    *result = quiche::QuicheEndian::NetToHost16(*result);
+  }
+  return true;
+}
+
+bool QuicheDataReader::ReadUInt32(uint32_t* result) {
+  if (!ReadBytes(result, sizeof(*result))) {
+    return false;
+  }
+  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+    *result = quiche::QuicheEndian::NetToHost32(*result);
+  }
+  return true;
+}
+
+bool QuicheDataReader::ReadUInt64(uint64_t* result) {
+  if (!ReadBytes(result, sizeof(*result))) {
+    return false;
+  }
+  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+    *result = quiche::QuicheEndian::NetToHost64(*result);
+  }
+  return true;
+}
+
+bool QuicheDataReader::ReadBytesToUInt64(size_t num_bytes, uint64_t* result) {
+  *result = 0u;
+  if (num_bytes > sizeof(*result)) {
+    return false;
+  }
+  if (endianness_ == quiche::HOST_BYTE_ORDER) {
+    return ReadBytes(result, num_bytes);
+  }
+
+  if (!ReadBytes(reinterpret_cast<char*>(result) + sizeof(*result) - num_bytes,
+                 num_bytes)) {
+    return false;
+  }
+  *result = quiche::QuicheEndian::NetToHost64(*result);
+  return true;
+}
+
+bool QuicheDataReader::ReadStringPiece16(quiche::QuicheStringPiece* result) {
+  // Read resultant length.
+  uint16_t result_len;
+  if (!ReadUInt16(&result_len)) {
+    // OnFailure() already called.
+    return false;
+  }
+
+  return ReadStringPiece(result, result_len);
+}
+
+bool QuicheDataReader::ReadStringPiece(quiche::QuicheStringPiece* result,
+                                       size_t size) {
+  // Make sure that we have enough data to read.
+  if (!CanRead(size)) {
+    OnFailure();
+    return false;
+  }
+
+  // Set result.
+  *result = quiche::QuicheStringPiece(data_ + pos_, size);
+
+  // Iterate.
+  pos_ += size;
+
+  return true;
+}
+
+bool QuicheDataReader::ReadTag(uint32_t* tag) {
+  return ReadBytes(tag, sizeof(*tag));
+}
+
+quiche::QuicheStringPiece QuicheDataReader::ReadRemainingPayload() {
+  quiche::QuicheStringPiece payload = PeekRemainingPayload();
+  pos_ = len_;
+  return payload;
+}
+
+quiche::QuicheStringPiece QuicheDataReader::PeekRemainingPayload() const {
+  return quiche::QuicheStringPiece(data_ + pos_, len_ - pos_);
+}
+
+quiche::QuicheStringPiece QuicheDataReader::FullPayload() const {
+  return quiche::QuicheStringPiece(data_, len_);
+}
+
+bool QuicheDataReader::ReadBytes(void* result, size_t size) {
+  // Make sure that we have enough data to read.
+  if (!CanRead(size)) {
+    OnFailure();
+    return false;
+  }
+
+  // Read into result.
+  memcpy(result, data_ + pos_, size);
+
+  // Iterate.
+  pos_ += size;
+
+  return true;
+}
+
+bool QuicheDataReader::Seek(size_t size) {
+  if (!CanRead(size)) {
+    OnFailure();
+    return false;
+  }
+  pos_ += size;
+  return true;
+}
+
+bool QuicheDataReader::IsDoneReading() const {
+  return len_ == pos_;
+}
+
+size_t QuicheDataReader::BytesRemaining() const {
+  return len_ - pos_;
+}
+
+bool QuicheDataReader::TruncateRemaining(size_t truncation_length) {
+  if (truncation_length > BytesRemaining()) {
+    return false;
+  }
+  len_ = pos_ + truncation_length;
+  return true;
+}
+
+bool QuicheDataReader::CanRead(size_t bytes) const {
+  return bytes <= (len_ - pos_);
+}
+
+void QuicheDataReader::OnFailure() {
+  // Set our iterator to the end of the buffer so that further reads fail
+  // immediately.
+  pos_ = len_;
+}
+
+uint8_t QuicheDataReader::PeekByte() const {
+  if (pos_ >= len_) {
+    QUICHE_LOG(FATAL)
+        << "Reading is done, cannot peek next byte. Tried to read pos = "
+        << pos_ << " buffer length = " << len_;
+    return 0;
+  }
+  return data_[pos_];
+}
+
+std::string QuicheDataReader::DebugString() const {
+  return quiche::QuicheStrCat(" { length: ", len_, ", position: ", pos_, " }");
+}
+
+#undef ENDPOINT  // undef for jumbo builds
+}  // namespace quiche
diff --git a/common/quiche_data_reader.h b/common/quiche_data_reader.h
new file mode 100644
index 0000000..45c0961
--- /dev/null
+++ b/common/quiche_data_reader.h
@@ -0,0 +1,173 @@
+// Copyright (c) 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_QUICHE_DATA_READER_H_
+#define QUICHE_COMMON_QUICHE_DATA_READER_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#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"
+
+namespace quiche {
+
+// To use, simply construct a QuicheDataReader using the underlying buffer that
+// you'd like to read fields from, then call one of the Read*() methods to
+// actually do some reading.
+//
+// This class keeps an internal iterator to keep track of what's already been
+// read and each successive Read*() call automatically increments said iterator
+// on success. On failure, internal state of the QuicheDataReader should not be
+// trusted and it is up to the caller to throw away the failed instance and
+// handle the error as appropriate. None of the Read*() methods should ever be
+// called after failure, as they will also fail immediately.
+class QUICHE_EXPORT_PRIVATE QuicheDataReader {
+ public:
+  // Constructs a reader using NETWORK_BYTE_ORDER endianness.
+  // Caller must provide an underlying buffer to work on.
+  explicit QuicheDataReader(quiche::QuicheStringPiece data);
+  // Constructs a reader using NETWORK_BYTE_ORDER endianness.
+  // Caller must provide an underlying buffer to work on.
+  QuicheDataReader(const char* data, const size_t len);
+  // Constructs a reader using the specified endianness.
+  // Caller must provide an underlying buffer to work on.
+  QuicheDataReader(const char* data,
+                   const size_t len,
+                   quiche::Endianness endianness);
+  QuicheDataReader(const QuicheDataReader&) = delete;
+  QuicheDataReader& operator=(const QuicheDataReader&) = delete;
+
+  // Empty destructor.
+  ~QuicheDataReader() {}
+
+  // Reads an 8/16/32/64-bit unsigned integer into the given output
+  // parameter. Forwards the internal iterator on success. Returns true on
+  // success, false otherwise.
+  bool ReadUInt8(uint8_t* result);
+  bool ReadUInt16(uint16_t* result);
+  bool ReadUInt32(uint32_t* result);
+  bool ReadUInt64(uint64_t* result);
+
+  // Set |result| to 0, then read |num_bytes| bytes in the correct byte order
+  // into least significant bytes of |result|.
+  bool ReadBytesToUInt64(size_t num_bytes, uint64_t* result);
+
+  // Reads a string prefixed with 16-bit length into the given output parameter.
+  //
+  // NOTE: Does not copy but rather references strings in the underlying buffer.
+  // This should be kept in mind when handling memory management!
+  //
+  // Forwards the internal iterator on success.
+  // Returns true on success, false otherwise.
+  bool ReadStringPiece16(quiche::QuicheStringPiece* result);
+
+  // Reads a given number of bytes into the given buffer. The buffer
+  // must be of adequate size.
+  // Forwards the internal iterator on success.
+  // Returns true on success, false otherwise.
+  bool ReadStringPiece(quiche::QuicheStringPiece* result, size_t size);
+
+  // Reads tag represented as 32-bit unsigned integer into given output
+  // parameter. Tags are in big endian on the wire (e.g., CHLO is
+  // 'C','H','L','O') and are read in byte order, so tags in memory are in big
+  // endian.
+  bool ReadTag(uint32_t* tag);
+
+  // Returns the remaining payload as a quiche::QuicheStringPiece.
+  //
+  // NOTE: Does not copy but rather references strings in the underlying buffer.
+  // This should be kept in mind when handling memory management!
+  //
+  // Forwards the internal iterator.
+  quiche::QuicheStringPiece ReadRemainingPayload();
+
+  // Returns the remaining payload as a quiche::QuicheStringPiece.
+  //
+  // NOTE: Does not copy but rather references strings in the underlying buffer.
+  // This should be kept in mind when handling memory management!
+  //
+  // DOES NOT forward the internal iterator.
+  quiche::QuicheStringPiece PeekRemainingPayload() const;
+
+  // Returns the entire payload as a quiche::QuicheStringPiece.
+  //
+  // NOTE: Does not copy but rather references strings in the underlying buffer.
+  // This should be kept in mind when handling memory management!
+  //
+  // DOES NOT forward the internal iterator.
+  quiche::QuicheStringPiece FullPayload() const;
+
+  // Reads a given number of bytes into the given buffer. The buffer
+  // must be of adequate size.
+  // Forwards the internal iterator on success.
+  // Returns true on success, false otherwise.
+  bool ReadBytes(void* result, size_t size);
+
+  // Skips over |size| bytes from the buffer and forwards the internal iterator.
+  // Returns true if there are at least |size| bytes remaining to read, false
+  // otherwise.
+  bool Seek(size_t size);
+
+  // Returns true if the entirety of the underlying buffer has been read via
+  // Read*() calls.
+  bool IsDoneReading() const;
+
+  // Returns the number of bytes remaining to be read.
+  size_t BytesRemaining() const;
+
+  // Truncates the reader down by reducing its internal length.
+  // If called immediately after calling this, BytesRemaining will
+  // return |truncation_length|. If truncation_length is less than the
+  // current value of BytesRemaining, this does nothing and returns false.
+  bool TruncateRemaining(size_t truncation_length);
+
+  // Returns the next byte that to be read. Must not be called when there are no
+  // bytes to be read.
+  //
+  // DOES NOT forward the internal iterator.
+  uint8_t PeekByte() const;
+
+  std::string DebugString() const;
+
+ protected:
+  // Returns true if the underlying buffer has enough room to read the given
+  // amount of bytes.
+  bool CanRead(size_t bytes) const;
+
+  // To be called when a read fails for any reason.
+  void OnFailure();
+
+  const char* data() const { return data_; }
+
+  size_t pos() const { return pos_; }
+
+  void AdvancePos(size_t amount) {
+    DCHECK_LE(pos_, std::numeric_limits<size_t>::max() - amount);
+    DCHECK_LE(pos_, len_ - amount);
+    pos_ += amount;
+  }
+
+  quiche::Endianness endianness() const { return endianness_; }
+
+ private:
+  // TODO(fkastenholz, b/73004262) change buffer_, et al, to be uint8_t, not
+  // char. The data buffer that we're reading from.
+  const char* data_;
+
+  // The length of the data buffer that we're reading from.
+  size_t len_;
+
+  // The location of the next read from our data buffer.
+  size_t pos_;
+
+  // The endianness to read integers and floating numbers.
+  quiche::Endianness endianness_;
+};
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_QUICHE_DATA_READER_H_
diff --git a/common/quiche_data_writer.cc b/common/quiche_data_writer.cc
new file mode 100644
index 0000000..4488f72
--- /dev/null
+++ b/common/quiche_data_writer.cc
@@ -0,0 +1,152 @@
+// Copyright (c) 2012 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/quiche_data_writer.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+namespace quiche {
+
+QuicheDataWriter::QuicheDataWriter(size_t size, char* buffer)
+    : QuicheDataWriter(size, buffer, quiche::NETWORK_BYTE_ORDER) {}
+
+QuicheDataWriter::QuicheDataWriter(size_t size,
+                                   char* buffer,
+                                   quiche::Endianness endianness)
+    : buffer_(buffer), capacity_(size), length_(0), endianness_(endianness) {}
+
+QuicheDataWriter::~QuicheDataWriter() {}
+
+char* QuicheDataWriter::data() {
+  return buffer_;
+}
+
+bool QuicheDataWriter::WriteUInt8(uint8_t value) {
+  return WriteBytes(&value, sizeof(value));
+}
+
+bool QuicheDataWriter::WriteUInt16(uint16_t value) {
+  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+    value = quiche::QuicheEndian::HostToNet16(value);
+  }
+  return WriteBytes(&value, sizeof(value));
+}
+
+bool QuicheDataWriter::WriteUInt32(uint32_t value) {
+  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+    value = quiche::QuicheEndian::HostToNet32(value);
+  }
+  return WriteBytes(&value, sizeof(value));
+}
+
+bool QuicheDataWriter::WriteUInt64(uint64_t value) {
+  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+    value = quiche::QuicheEndian::HostToNet64(value);
+  }
+  return WriteBytes(&value, sizeof(value));
+}
+
+bool QuicheDataWriter::WriteBytesToUInt64(size_t num_bytes, uint64_t value) {
+  if (num_bytes > sizeof(value)) {
+    return false;
+  }
+  if (endianness_ == quiche::HOST_BYTE_ORDER) {
+    return WriteBytes(&value, num_bytes);
+  }
+
+  value = quiche::QuicheEndian::HostToNet64(value);
+  return WriteBytes(reinterpret_cast<char*>(&value) + sizeof(value) - num_bytes,
+                    num_bytes);
+}
+
+bool QuicheDataWriter::WriteStringPiece16(quiche::QuicheStringPiece val) {
+  if (val.size() > std::numeric_limits<uint16_t>::max()) {
+    return false;
+  }
+  if (!WriteUInt16(static_cast<uint16_t>(val.size()))) {
+    return false;
+  }
+  return WriteBytes(val.data(), val.size());
+}
+
+bool QuicheDataWriter::WriteStringPiece(quiche::QuicheStringPiece val) {
+  return WriteBytes(val.data(), val.size());
+}
+
+char* QuicheDataWriter::BeginWrite(size_t length) {
+  if (length_ > capacity_) {
+    return nullptr;
+  }
+
+  if (capacity_ - length_ < length) {
+    return nullptr;
+  }
+
+#ifdef ARCH_CPU_64_BITS
+  DCHECK_LE(length, std::numeric_limits<uint32_t>::max());
+#endif
+
+  return buffer_ + length_;
+}
+
+bool QuicheDataWriter::WriteBytes(const void* data, size_t data_len) {
+  char* dest = BeginWrite(data_len);
+  if (!dest) {
+    return false;
+  }
+
+  memcpy(dest, data, data_len);
+
+  length_ += data_len;
+  return true;
+}
+
+bool QuicheDataWriter::WriteRepeatedByte(uint8_t byte, size_t count) {
+  char* dest = BeginWrite(count);
+  if (!dest) {
+    return false;
+  }
+
+  memset(dest, byte, count);
+
+  length_ += count;
+  return true;
+}
+
+void QuicheDataWriter::WritePadding() {
+  DCHECK_LE(length_, capacity_);
+  if (length_ > capacity_) {
+    return;
+  }
+  memset(buffer_ + length_, 0x00, capacity_ - length_);
+  length_ = capacity_;
+}
+
+bool QuicheDataWriter::WritePaddingBytes(size_t count) {
+  return WriteRepeatedByte(0x00, count);
+}
+
+bool QuicheDataWriter::WriteTag(uint32_t tag) {
+  return WriteBytes(&tag, sizeof(tag));
+}
+
+bool QuicheDataWriter::Seek(size_t length) {
+  if (!BeginWrite(length)) {
+    return false;
+  }
+  length_ += length;
+  return true;
+}
+
+std::string QuicheDataWriter::DebugString() const {
+  return quiche::QuicheStrCat(" { capacity: ", capacity_, ", length: ", length_,
+                              " }");
+}
+
+}  // namespace quiche
diff --git a/common/quiche_data_writer.h b/common/quiche_data_writer.h
new file mode 100644
index 0000000..8df1f90
--- /dev/null
+++ b/common/quiche_data_writer.h
@@ -0,0 +1,110 @@
+// Copyright (c) 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_QUICHE_DATA_WRITER_H_
+#define QUICHE_COMMON_QUICHE_DATA_WRITER_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#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"
+
+namespace quiche {
+
+// This class provides facilities for packing binary data.
+//
+// The QuicheDataWriter supports appending primitive values (int, string, etc)
+// to a frame instance.  The internal memory buffer is exposed as the "data"
+// of the QuicheDataWriter.
+class QUICHE_EXPORT_PRIVATE QuicheDataWriter {
+ public:
+  // Creates a QuicheDataWriter where |buffer| is not owned
+  // using NETWORK_BYTE_ORDER endianness.
+  QuicheDataWriter(size_t size, char* buffer);
+  // Creates a QuicheDataWriter where |buffer| is not owned
+  // using the specified endianness.
+  QuicheDataWriter(size_t size, char* buffer, quiche::Endianness endianness);
+  QuicheDataWriter(const QuicheDataWriter&) = delete;
+  QuicheDataWriter& operator=(const QuicheDataWriter&) = delete;
+
+  ~QuicheDataWriter();
+
+  // Returns the size of the QuicheDataWriter's data.
+  size_t length() const { return length_; }
+
+  // Retrieves the buffer from the QuicheDataWriter without changing ownership.
+  char* data();
+
+  // Methods for adding to the payload.  These values are appended to the end
+  // of the QuicheDataWriter payload.
+
+  // Writes 8/16/32/64-bit unsigned integers.
+  bool WriteUInt8(uint8_t value);
+  bool WriteUInt16(uint16_t value);
+  bool WriteUInt32(uint32_t value);
+  bool WriteUInt64(uint64_t value);
+
+  // Writes least significant |num_bytes| of a 64-bit unsigned integer in the
+  // correct byte order.
+  bool WriteBytesToUInt64(size_t num_bytes, uint64_t value);
+
+  bool WriteStringPiece(quiche::QuicheStringPiece val);
+  bool WriteStringPiece16(quiche::QuicheStringPiece val);
+  bool WriteBytes(const void* data, size_t data_len);
+  bool WriteRepeatedByte(uint8_t byte, size_t count);
+  // Fills the remaining buffer with null characters.
+  void WritePadding();
+  // Write padding of |count| bytes.
+  bool WritePaddingBytes(size_t count);
+
+  // Write tag as a 32-bit unsigned integer to the payload. As tags are already
+  // converted to big endian (e.g., CHLO is 'C','H','L','O') in memory by TAG or
+  // MakeQuicTag and tags are written in byte order, so tags on the wire are
+  // in big endian.
+  bool WriteTag(uint32_t tag);
+
+  // Advance the writer's position for writing by |length| bytes without writing
+  // anything. This method only makes sense to be used on a buffer that has
+  // already been written to (and is having certain parts rewritten).
+  bool Seek(size_t length);
+
+  size_t capacity() const { return capacity_; }
+
+  size_t remaining() const { return capacity_ - length_; }
+
+  std::string DebugString() const;
+
+ protected:
+  // Returns the location that the data should be written at, or nullptr if
+  // there is not enough room. Call EndWrite with the returned offset and the
+  // given length to pad out for the next write.
+  char* BeginWrite(size_t length);
+
+  quiche::Endianness endianness() const { return endianness_; }
+
+  char* buffer() const { return buffer_; }
+
+  void IncreaseLength(size_t delta) {
+    DCHECK_LE(length_, std::numeric_limits<size_t>::max() - delta);
+    DCHECK_LE(length_, capacity_ - delta);
+    length_ += delta;
+  }
+
+ private:
+  // TODO(fkastenholz, b/73004262) change buffer_, et al, to be uint8_t, not
+  // char.
+  char* buffer_;
+  size_t capacity_;  // Allocation size of payload (or -1 if buffer is const).
+  size_t length_;    // Current length of the buffer.
+
+  // The endianness to write integers and floating numbers.
+  quiche::Endianness endianness_;
+};
+
+}  // namespace quiche
+
+#endif  // QUICHE_COMMON_QUICHE_DATA_WRITER_H_
diff --git a/common/quiche_data_writer_test.cc b/common/quiche_data_writer_test.cc
new file mode 100644
index 0000000..78f8abf
--- /dev/null
+++ b/common/quiche_data_writer_test.cc
@@ -0,0 +1,419 @@
+// Copyright (c) 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 "net/third_party/quiche/src/common/quiche_data_writer.h"
+
+#include <cstdint>
+#include <cstring>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#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"
+#include "net/third_party/quiche/src/common/quiche_data_reader.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
+
+namespace quiche {
+namespace test {
+namespace {
+
+char* AsChars(unsigned char* data) {
+  return reinterpret_cast<char*>(data);
+}
+
+struct TestParams {
+  explicit TestParams(quiche::Endianness endianness) : endianness(endianness) {}
+
+  quiche::Endianness endianness;
+};
+
+// Used by ::testing::PrintToStringParamName().
+std::string PrintToString(const TestParams& p) {
+  return quiche::QuicheStrCat(
+      (p.endianness == quiche::NETWORK_BYTE_ORDER ? "Network" : "Host"),
+      "ByteOrder");
+}
+
+std::vector<TestParams> GetTestParams() {
+  std::vector<TestParams> params;
+  for (quiche::Endianness endianness :
+       {quiche::NETWORK_BYTE_ORDER, quiche::HOST_BYTE_ORDER}) {
+    params.push_back(TestParams(endianness));
+  }
+  return params;
+}
+
+class QuicheDataWriterTest : public QuicheTestWithParam<TestParams> {};
+
+INSTANTIATE_TEST_SUITE_P(QuicheDataWriterTests,
+                         QuicheDataWriterTest,
+                         ::testing::ValuesIn(GetTestParams()),
+                         ::testing::PrintToStringParamName());
+
+TEST_P(QuicheDataWriterTest, Write16BitUnsignedIntegers) {
+  char little_endian16[] = {0x22, 0x11};
+  char big_endian16[] = {0x11, 0x22};
+  char buffer16[2];
+  {
+    uint16_t in_memory16 = 0x1122;
+    QuicheDataWriter writer(2, buffer16, GetParam().endianness);
+    writer.WriteUInt16(in_memory16);
+    test::CompareCharArraysWithHexError(
+        "uint16_t", buffer16, 2,
+        GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian16
+                                                            : little_endian16,
+        2);
+
+    uint16_t read_number16;
+    QuicheDataReader reader(buffer16, 2, GetParam().endianness);
+    reader.ReadUInt16(&read_number16);
+    EXPECT_EQ(in_memory16, read_number16);
+  }
+
+  {
+    uint64_t in_memory16 = 0x0000000000001122;
+    QuicheDataWriter writer(2, buffer16, GetParam().endianness);
+    writer.WriteBytesToUInt64(2, in_memory16);
+    test::CompareCharArraysWithHexError(
+        "uint16_t", buffer16, 2,
+        GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian16
+                                                            : little_endian16,
+        2);
+
+    uint64_t read_number16;
+    QuicheDataReader reader(buffer16, 2, GetParam().endianness);
+    reader.ReadBytesToUInt64(2, &read_number16);
+    EXPECT_EQ(in_memory16, read_number16);
+  }
+}
+
+TEST_P(QuicheDataWriterTest, Write24BitUnsignedIntegers) {
+  char little_endian24[] = {0x33, 0x22, 0x11};
+  char big_endian24[] = {0x11, 0x22, 0x33};
+  char buffer24[3];
+  uint64_t in_memory24 = 0x0000000000112233;
+  QuicheDataWriter writer(3, buffer24, GetParam().endianness);
+  writer.WriteBytesToUInt64(3, in_memory24);
+  test::CompareCharArraysWithHexError(
+      "uint24", buffer24, 3,
+      GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian24
+                                                          : little_endian24,
+      3);
+
+  uint64_t read_number24;
+  QuicheDataReader reader(buffer24, 3, GetParam().endianness);
+  reader.ReadBytesToUInt64(3, &read_number24);
+  EXPECT_EQ(in_memory24, read_number24);
+}
+
+TEST_P(QuicheDataWriterTest, Write32BitUnsignedIntegers) {
+  char little_endian32[] = {0x44, 0x33, 0x22, 0x11};
+  char big_endian32[] = {0x11, 0x22, 0x33, 0x44};
+  char buffer32[4];
+  {
+    uint32_t in_memory32 = 0x11223344;
+    QuicheDataWriter writer(4, buffer32, GetParam().endianness);
+    writer.WriteUInt32(in_memory32);
+    test::CompareCharArraysWithHexError(
+        "uint32_t", buffer32, 4,
+        GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian32
+                                                            : little_endian32,
+        4);
+
+    uint32_t read_number32;
+    QuicheDataReader reader(buffer32, 4, GetParam().endianness);
+    reader.ReadUInt32(&read_number32);
+    EXPECT_EQ(in_memory32, read_number32);
+  }
+
+  {
+    uint64_t in_memory32 = 0x11223344;
+    QuicheDataWriter writer(4, buffer32, GetParam().endianness);
+    writer.WriteBytesToUInt64(4, in_memory32);
+    test::CompareCharArraysWithHexError(
+        "uint32_t", buffer32, 4,
+        GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian32
+                                                            : little_endian32,
+        4);
+
+    uint64_t read_number32;
+    QuicheDataReader reader(buffer32, 4, GetParam().endianness);
+    reader.ReadBytesToUInt64(4, &read_number32);
+    EXPECT_EQ(in_memory32, read_number32);
+  }
+}
+
+TEST_P(QuicheDataWriterTest, Write40BitUnsignedIntegers) {
+  uint64_t in_memory40 = 0x0000001122334455;
+  char little_endian40[] = {0x55, 0x44, 0x33, 0x22, 0x11};
+  char big_endian40[] = {0x11, 0x22, 0x33, 0x44, 0x55};
+  char buffer40[5];
+  QuicheDataWriter writer(5, buffer40, GetParam().endianness);
+  writer.WriteBytesToUInt64(5, in_memory40);
+  test::CompareCharArraysWithHexError(
+      "uint40", buffer40, 5,
+      GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian40
+                                                          : little_endian40,
+      5);
+
+  uint64_t read_number40;
+  QuicheDataReader reader(buffer40, 5, GetParam().endianness);
+  reader.ReadBytesToUInt64(5, &read_number40);
+  EXPECT_EQ(in_memory40, read_number40);
+}
+
+TEST_P(QuicheDataWriterTest, Write48BitUnsignedIntegers) {
+  uint64_t in_memory48 = 0x0000112233445566;
+  char little_endian48[] = {0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
+  char big_endian48[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+  char buffer48[6];
+  QuicheDataWriter writer(6, buffer48, GetParam().endianness);
+  writer.WriteBytesToUInt64(6, in_memory48);
+  test::CompareCharArraysWithHexError(
+      "uint48", buffer48, 6,
+      GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian48
+                                                          : little_endian48,
+      6);
+
+  uint64_t read_number48;
+  QuicheDataReader reader(buffer48, 6, GetParam().endianness);
+  reader.ReadBytesToUInt64(6., &read_number48);
+  EXPECT_EQ(in_memory48, read_number48);
+}
+
+TEST_P(QuicheDataWriterTest, Write56BitUnsignedIntegers) {
+  uint64_t in_memory56 = 0x0011223344556677;
+  char little_endian56[] = {0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
+  char big_endian56[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  char buffer56[7];
+  QuicheDataWriter writer(7, buffer56, GetParam().endianness);
+  writer.WriteBytesToUInt64(7, in_memory56);
+  test::CompareCharArraysWithHexError(
+      "uint56", buffer56, 7,
+      GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian56
+                                                          : little_endian56,
+      7);
+
+  uint64_t read_number56;
+  QuicheDataReader reader(buffer56, 7, GetParam().endianness);
+  reader.ReadBytesToUInt64(7, &read_number56);
+  EXPECT_EQ(in_memory56, read_number56);
+}
+
+TEST_P(QuicheDataWriterTest, Write64BitUnsignedIntegers) {
+  uint64_t in_memory64 = 0x1122334455667788;
+  unsigned char little_endian64[] = {0x88, 0x77, 0x66, 0x55,
+                                     0x44, 0x33, 0x22, 0x11};
+  unsigned char big_endian64[] = {0x11, 0x22, 0x33, 0x44,
+                                  0x55, 0x66, 0x77, 0x88};
+  char buffer64[8];
+  QuicheDataWriter writer(8, buffer64, GetParam().endianness);
+  writer.WriteBytesToUInt64(8, in_memory64);
+  test::CompareCharArraysWithHexError(
+      "uint64_t", buffer64, 8,
+      GetParam().endianness == quiche::NETWORK_BYTE_ORDER
+          ? AsChars(big_endian64)
+          : AsChars(little_endian64),
+      8);
+
+  uint64_t read_number64;
+  QuicheDataReader reader(buffer64, 8, GetParam().endianness);
+  reader.ReadBytesToUInt64(8, &read_number64);
+  EXPECT_EQ(in_memory64, read_number64);
+
+  QuicheDataWriter writer2(8, buffer64, GetParam().endianness);
+  writer2.WriteUInt64(in_memory64);
+  test::CompareCharArraysWithHexError(
+      "uint64_t", buffer64, 8,
+      GetParam().endianness == quiche::NETWORK_BYTE_ORDER
+          ? AsChars(big_endian64)
+          : AsChars(little_endian64),
+      8);
+  read_number64 = 0u;
+  QuicheDataReader reader2(buffer64, 8, GetParam().endianness);
+  reader2.ReadUInt64(&read_number64);
+  EXPECT_EQ(in_memory64, read_number64);
+}
+
+TEST_P(QuicheDataWriterTest, WriteIntegers) {
+  char buf[43];
+  uint8_t i8 = 0x01;
+  uint16_t i16 = 0x0123;
+  uint32_t i32 = 0x01234567;
+  uint64_t i64 = 0x0123456789ABCDEF;
+  QuicheDataWriter writer(46, buf, GetParam().endianness);
+  for (size_t i = 0; i < 10; ++i) {
+    switch (i) {
+      case 0u:
+        EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
+        break;
+      case 1u:
+        EXPECT_TRUE(writer.WriteUInt8(i8));
+        EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
+        break;
+      case 2u:
+        EXPECT_TRUE(writer.WriteUInt16(i16));
+        EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
+        break;
+      case 3u:
+        EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
+        break;
+      case 4u:
+        EXPECT_TRUE(writer.WriteUInt32(i32));
+        EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
+        break;
+      case 5u:
+      case 6u:
+      case 7u:
+      case 8u:
+        EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
+        break;
+      default:
+        EXPECT_FALSE(writer.WriteBytesToUInt64(i, i64));
+    }
+  }
+
+  QuicheDataReader reader(buf, 46, GetParam().endianness);
+  for (size_t i = 0; i < 10; ++i) {
+    uint8_t read8;
+    uint16_t read16;
+    uint32_t read32;
+    uint64_t read64;
+    switch (i) {
+      case 0u:
+        EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
+        EXPECT_EQ(0u, read64);
+        break;
+      case 1u:
+        EXPECT_TRUE(reader.ReadUInt8(&read8));
+        EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
+        EXPECT_EQ(i8, read8);
+        EXPECT_EQ(0xEFu, read64);
+        break;
+      case 2u:
+        EXPECT_TRUE(reader.ReadUInt16(&read16));
+        EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
+        EXPECT_EQ(i16, read16);
+        EXPECT_EQ(0xCDEFu, read64);
+        break;
+      case 3u:
+        EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
+        EXPECT_EQ(0xABCDEFu, read64);
+        break;
+      case 4u:
+        EXPECT_TRUE(reader.ReadUInt32(&read32));
+        EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
+        EXPECT_EQ(i32, read32);
+        EXPECT_EQ(0x89ABCDEFu, read64);
+        break;
+      case 5u:
+        EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
+        EXPECT_EQ(0x6789ABCDEFu, read64);
+        break;
+      case 6u:
+        EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
+        EXPECT_EQ(0x456789ABCDEFu, read64);
+        break;
+      case 7u:
+        EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
+        EXPECT_EQ(0x23456789ABCDEFu, read64);
+        break;
+      case 8u:
+        EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
+        EXPECT_EQ(0x0123456789ABCDEFu, read64);
+        break;
+      default:
+        EXPECT_FALSE(reader.ReadBytesToUInt64(i, &read64));
+    }
+  }
+}
+
+TEST_P(QuicheDataWriterTest, WriteBytes) {
+  char bytes[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
+  char buf[QUICHE_ARRAYSIZE(bytes)];
+  QuicheDataWriter writer(QUICHE_ARRAYSIZE(buf), buf, GetParam().endianness);
+  EXPECT_TRUE(writer.WriteBytes(bytes, QUICHE_ARRAYSIZE(bytes)));
+  for (unsigned int i = 0; i < QUICHE_ARRAYSIZE(bytes); ++i) {
+    EXPECT_EQ(bytes[i], buf[i]);
+  }
+}
+
+TEST_P(QuicheDataWriterTest, Seek) {
+  char buffer[3] = {};
+  QuicheDataWriter writer(QUICHE_ARRAYSIZE(buffer), buffer,
+                          GetParam().endianness);
+  EXPECT_TRUE(writer.WriteUInt8(42));
+  EXPECT_TRUE(writer.Seek(1));
+  EXPECT_TRUE(writer.WriteUInt8(3));
+
+  char expected[] = {42, 0, 3};
+  for (size_t i = 0; i < QUICHE_ARRAYSIZE(expected); ++i) {
+    EXPECT_EQ(buffer[i], expected[i]);
+  }
+}
+
+TEST_P(QuicheDataWriterTest, SeekTooFarFails) {
+  char buffer[20];
+
+  // Check that one can seek to the end of the writer, but not past.
+  {
+    QuicheDataWriter writer(QUICHE_ARRAYSIZE(buffer), buffer,
+                            GetParam().endianness);
+    EXPECT_TRUE(writer.Seek(20));
+    EXPECT_FALSE(writer.Seek(1));
+  }
+
+  // Seeking several bytes past the end fails.
+  {
+    QuicheDataWriter writer(QUICHE_ARRAYSIZE(buffer), buffer,
+                            GetParam().endianness);
+    EXPECT_FALSE(writer.Seek(100));
+  }
+
+  // Seeking so far that arithmetic overflow could occur also fails.
+  {
+    QuicheDataWriter writer(QUICHE_ARRAYSIZE(buffer), buffer,
+                            GetParam().endianness);
+    EXPECT_TRUE(writer.Seek(10));
+    EXPECT_FALSE(writer.Seek(std::numeric_limits<size_t>::max()));
+  }
+}
+
+TEST_P(QuicheDataWriterTest, PayloadReads) {
+  char buffer[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+  char expected_first_read[4] = {1, 2, 3, 4};
+  char expected_remaining[12] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+  QuicheDataReader reader(buffer, sizeof(buffer));
+  char first_read_buffer[4] = {};
+  EXPECT_TRUE(reader.ReadBytes(first_read_buffer, sizeof(first_read_buffer)));
+  test::CompareCharArraysWithHexError(
+      "first read", first_read_buffer, sizeof(first_read_buffer),
+      expected_first_read, sizeof(expected_first_read));
+  quiche::QuicheStringPiece peeked_remaining_payload =
+      reader.PeekRemainingPayload();
+  test::CompareCharArraysWithHexError(
+      "peeked_remaining_payload", peeked_remaining_payload.data(),
+      peeked_remaining_payload.length(), expected_remaining,
+      sizeof(expected_remaining));
+  quiche::QuicheStringPiece full_payload = reader.FullPayload();
+  test::CompareCharArraysWithHexError("full_payload", full_payload.data(),
+                                      full_payload.length(), buffer,
+                                      sizeof(buffer));
+  quiche::QuicheStringPiece read_remaining_payload =
+      reader.ReadRemainingPayload();
+  test::CompareCharArraysWithHexError(
+      "read_remaining_payload", read_remaining_payload.data(),
+      read_remaining_payload.length(), expected_remaining,
+      sizeof(expected_remaining));
+  EXPECT_TRUE(reader.IsDoneReading());
+  quiche::QuicheStringPiece full_payload2 = reader.FullPayload();
+  test::CompareCharArraysWithHexError("full_payload2", full_payload2.data(),
+                                      full_payload2.length(), buffer,
+                                      sizeof(buffer));
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace quiche
diff --git a/quic/core/quic_data_reader.cc b/quic/core/quic_data_reader.cc
index 3982cc9..882573d 100644
--- a/quic/core/quic_data_reader.cc
+++ b/quic/core/quic_data_reader.cc
@@ -15,7 +15,7 @@
 namespace quic {
 
 QuicDataReader::QuicDataReader(quiche::QuicheStringPiece data)
-    : QuicDataReader(data.data(), data.length(), quiche::NETWORK_BYTE_ORDER) {}
+    : quiche::QuicheDataReader(data) {}
 
 QuicDataReader::QuicDataReader(const char* data, const size_t len)
     : QuicDataReader(data, len, quiche::NETWORK_BYTE_ORDER) {}
@@ -23,58 +23,7 @@
 QuicDataReader::QuicDataReader(const char* data,
                                const size_t len,
                                quiche::Endianness endianness)
-    : data_(data), len_(len), pos_(0), endianness_(endianness) {}
-
-bool QuicDataReader::ReadUInt8(uint8_t* result) {
-  return ReadBytes(result, sizeof(*result));
-}
-
-bool QuicDataReader::ReadUInt16(uint16_t* result) {
-  if (!ReadBytes(result, sizeof(*result))) {
-    return false;
-  }
-  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
-    *result = quiche::QuicheEndian::NetToHost16(*result);
-  }
-  return true;
-}
-
-bool QuicDataReader::ReadUInt32(uint32_t* result) {
-  if (!ReadBytes(result, sizeof(*result))) {
-    return false;
-  }
-  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
-    *result = quiche::QuicheEndian::NetToHost32(*result);
-  }
-  return true;
-}
-
-bool QuicDataReader::ReadUInt64(uint64_t* result) {
-  if (!ReadBytes(result, sizeof(*result))) {
-    return false;
-  }
-  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
-    *result = quiche::QuicheEndian::NetToHost64(*result);
-  }
-  return true;
-}
-
-bool QuicDataReader::ReadBytesToUInt64(size_t num_bytes, uint64_t* result) {
-  *result = 0u;
-  if (num_bytes > sizeof(*result)) {
-    return false;
-  }
-  if (endianness_ == quiche::HOST_BYTE_ORDER) {
-    return ReadBytes(result, num_bytes);
-  }
-
-  if (!ReadBytes(reinterpret_cast<char*>(result) + sizeof(*result) - num_bytes,
-                 num_bytes)) {
-    return false;
-  }
-  *result = quiche::QuicheEndian::NetToHost64(*result);
-  return true;
-}
+    : quiche::QuicheDataReader(data, len, endianness) {}
 
 bool QuicDataReader::ReadUFloat16(uint64_t* result) {
   uint16_t value;
@@ -109,34 +58,6 @@
   return true;
 }
 
-bool QuicDataReader::ReadStringPiece16(quiche::QuicheStringPiece* result) {
-  // Read resultant length.
-  uint16_t result_len;
-  if (!ReadUInt16(&result_len)) {
-    // OnFailure() already called.
-    return false;
-  }
-
-  return ReadStringPiece(result, result_len);
-}
-
-bool QuicDataReader::ReadStringPiece(quiche::QuicheStringPiece* result,
-                                     size_t size) {
-  // Make sure that we have enough data to read.
-  if (!CanRead(size)) {
-    OnFailure();
-    return false;
-  }
-
-  // Set result.
-  *result = quiche::QuicheStringPiece(data_ + pos_, size);
-
-  // Iterate.
-  pos_ += size;
-
-  return true;
-}
-
 bool QuicDataReader::ReadConnectionId(QuicConnectionId* connection_id,
                                       uint8_t length) {
   if (!GetQuicRestartFlag(quic_allow_very_long_connection_ids)) {
@@ -180,57 +101,10 @@
   return ReadConnectionId(connection_id, connection_id_length);
 }
 
-bool QuicDataReader::ReadTag(uint32_t* tag) {
-  return ReadBytes(tag, sizeof(*tag));
-}
-
-quiche::QuicheStringPiece QuicDataReader::ReadRemainingPayload() {
-  quiche::QuicheStringPiece payload = PeekRemainingPayload();
-  pos_ = len_;
-  return payload;
-}
-
-quiche::QuicheStringPiece QuicDataReader::PeekRemainingPayload() const {
-  return quiche::QuicheStringPiece(data_ + pos_, len_ - pos_);
-}
-
-quiche::QuicheStringPiece QuicDataReader::FullPayload() const {
-  return quiche::QuicheStringPiece(data_, len_);
-}
-
-bool QuicDataReader::ReadBytes(void* result, size_t size) {
-  // Make sure that we have enough data to read.
-  if (!CanRead(size)) {
-    OnFailure();
-    return false;
-  }
-
-  // Read into result.
-  memcpy(result, data_ + pos_, size);
-
-  // Iterate.
-  pos_ += size;
-
-  return true;
-}
-
-bool QuicDataReader::Seek(size_t size) {
-  if (!CanRead(size)) {
-    OnFailure();
-    return false;
-  }
-  pos_ += size;
-  return true;
-}
-
-bool QuicDataReader::IsDoneReading() const {
-  return len_ == pos_;
-}
-
 QuicVariableLengthIntegerLength QuicDataReader::PeekVarInt62Length() {
-  DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
+  DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
   const unsigned char* next =
-      reinterpret_cast<const unsigned char*>(data_ + pos_);
+      reinterpret_cast<const unsigned char*>(data() + pos());
   if (BytesRemaining() == 0) {
     return VARIABLE_LENGTH_INTEGER_LENGTH_0;
   }
@@ -238,37 +112,6 @@
       1 << ((*next & 0b11000000) >> 6));
 }
 
-size_t QuicDataReader::BytesRemaining() const {
-  return len_ - pos_;
-}
-
-bool QuicDataReader::TruncateRemaining(size_t truncation_length) {
-  if (truncation_length > BytesRemaining()) {
-    return false;
-  }
-  len_ = pos_ + truncation_length;
-  return true;
-}
-
-bool QuicDataReader::CanRead(size_t bytes) const {
-  return bytes <= (len_ - pos_);
-}
-
-void QuicDataReader::OnFailure() {
-  // Set our iterator to the end of the buffer so that further reads fail
-  // immediately.
-  pos_ = len_;
-}
-
-uint8_t QuicDataReader::PeekByte() const {
-  if (pos_ >= len_) {
-    QUIC_BUG << "Reading is done, cannot peek next byte. Tried to read pos = "
-             << pos_ << " buffer length = " << len_;
-    return 0;
-  }
-  return data_[pos_];
-}
-
 // Read an IETF/QUIC formatted 62-bit Variable Length Integer.
 //
 // Performance notes
@@ -286,11 +129,11 @@
 // Low-level optimization is useful here because this function will be
 // called frequently, leading to outsize benefits.
 bool QuicDataReader::ReadVarInt62(uint64_t* result) {
-  DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
+  DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
 
   size_t remaining = BytesRemaining();
   const unsigned char* next =
-      reinterpret_cast<const unsigned char*>(data_ + pos_);
+      reinterpret_cast<const unsigned char*>(data() + pos());
   if (remaining != 0) {
     switch (*next & 0xc0) {
       case 0xc0:
@@ -304,7 +147,7 @@
                     (static_cast<uint64_t>(*(next + 5)) << 16) +
                     (static_cast<uint64_t>(*(next + 6)) << 8) +
                     (static_cast<uint64_t>(*(next + 7)) << 0);
-          pos_ += 8;
+          AdvancePos(8);
           return true;
         }
         return false;
@@ -314,7 +157,7 @@
         if (remaining >= 4) {
           *result = (((*(next)) & 0x3f) << 24) + (((*(next + 1)) << 16)) +
                     (((*(next + 2)) << 8)) + (((*(next + 3)) << 0));
-          pos_ += 4;
+          AdvancePos(4);
           return true;
         }
         return false;
@@ -323,7 +166,7 @@
         // Leading 0b01...... is 2 byte encoding
         if (remaining >= 2) {
           *result = (((*(next)) & 0x3f) << 8) + (*(next + 1));
-          pos_ += 2;
+          AdvancePos(2);
           return true;
         }
         return false;
@@ -331,7 +174,7 @@
       case 0x00:
         // Leading 0b00...... is 1 byte encoding
         *result = (*next) & 0x3f;
-        pos_++;
+        AdvancePos(1);
         return true;
     }
   }
@@ -352,9 +195,5 @@
   return true;
 }
 
-std::string QuicDataReader::DebugString() const {
-  return quiche::QuicheStrCat(" { length: ", len_, ", position: ", pos_, " }");
-}
-
 #undef ENDPOINT  // undef for jumbo builds
 }  // namespace quic
diff --git a/quic/core/quic_data_reader.h b/quic/core/quic_data_reader.h
index 40ad4fc..08366b9 100644
--- a/quic/core/quic_data_reader.h
+++ b/quic/core/quic_data_reader.h
@@ -12,6 +12,7 @@
 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
 #include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
 #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/quiche_data_reader.h"
 
 namespace quic {
 
@@ -29,7 +30,7 @@
 // trusted and it is up to the caller to throw away the failed instance and
 // handle the error as appropriate. None of the Read*() methods should ever be
 // called after failure, as they will also fail immediately.
-class QUIC_EXPORT_PRIVATE QuicDataReader {
+class QUIC_EXPORT_PRIVATE QuicDataReader : public quiche::QuicheDataReader {
  public:
   // Constructs a reader using NETWORK_BYTE_ORDER endianness.
   // Caller must provide an underlying buffer to work on.
@@ -48,38 +49,11 @@
   // Empty destructor.
   ~QuicDataReader() {}
 
-  // Reads an 8/16/32/64-bit unsigned integer into the given output
-  // parameter. Forwards the internal iterator on success. Returns true on
-  // success, false otherwise.
-  bool ReadUInt8(uint8_t* result);
-  bool ReadUInt16(uint16_t* result);
-  bool ReadUInt32(uint32_t* result);
-  bool ReadUInt64(uint64_t* result);
-
-  // Set |result| to 0, then read |num_bytes| bytes in the correct byte order
-  // into least significant bytes of |result|.
-  bool ReadBytesToUInt64(size_t num_bytes, uint64_t* result);
-
   // Reads a 16-bit unsigned float into the given output parameter.
   // Forwards the internal iterator on success.
   // Returns true on success, false otherwise.
   bool ReadUFloat16(uint64_t* result);
 
-  // Reads a string prefixed with 16-bit length into the given output parameter.
-  //
-  // NOTE: Does not copy but rather references strings in the underlying buffer.
-  // This should be kept in mind when handling memory management!
-  //
-  // Forwards the internal iterator on success.
-  // Returns true on success, false otherwise.
-  bool ReadStringPiece16(quiche::QuicheStringPiece* result);
-
-  // Reads a given number of bytes into the given buffer. The buffer
-  // must be of adequate size.
-  // Forwards the internal iterator on success.
-  // Returns true on success, false otherwise.
-  bool ReadStringPiece(quiche::QuicheStringPiece* result, size_t len);
-
   // Reads connection ID into the given output parameter.
   // Forwards the internal iterator on success.
   // Returns true on success, false otherwise.
@@ -90,70 +64,10 @@
   // Returns true on success, false otherwise.
   bool ReadLengthPrefixedConnectionId(QuicConnectionId* connection_id);
 
-  // Reads tag represented as 32-bit unsigned integer into given output
-  // parameter. Tags are in big endian on the wire (e.g., CHLO is
-  // 'C','H','L','O') and are read in byte order, so tags in memory are in big
-  // endian.
-  bool ReadTag(uint32_t* tag);
-
-  // Returns the remaining payload as a quiche::QuicheStringPiece.
-  //
-  // NOTE: Does not copy but rather references strings in the underlying buffer.
-  // This should be kept in mind when handling memory management!
-  //
-  // Forwards the internal iterator.
-  quiche::QuicheStringPiece ReadRemainingPayload();
-
-  // Returns the remaining payload as a quiche::QuicheStringPiece.
-  //
-  // NOTE: Does not copy but rather references strings in the underlying buffer.
-  // This should be kept in mind when handling memory management!
-  //
-  // DOES NOT forward the internal iterator.
-  quiche::QuicheStringPiece PeekRemainingPayload() const;
-
-  // Returns the entire payload as a quiche::QuicheStringPiece.
-  //
-  // NOTE: Does not copy but rather references strings in the underlying buffer.
-  // This should be kept in mind when handling memory management!
-  //
-  // DOES NOT forward the internal iterator.
-  quiche::QuicheStringPiece FullPayload() const;
-
-  // Reads a given number of bytes into the given buffer. The buffer
-  // must be of adequate size.
-  // Forwards the internal iterator on success.
-  // Returns true on success, false otherwise.
-  bool ReadBytes(void* result, size_t size);
-
-  // Skips over |size| bytes from the buffer and forwards the internal iterator.
-  // Returns true if there are at least |size| bytes remaining to read, false
-  // otherwise.
-  bool Seek(size_t size);
-
-  // Returns true if the entirety of the underlying buffer has been read via
-  // Read*() calls.
-  bool IsDoneReading() const;
-
   // Returns the length in bytes of a variable length integer based on the next
   // two bits available. Returns 1, 2, 4, or 8 on success, and 0 on failure.
   QuicVariableLengthIntegerLength PeekVarInt62Length();
 
-  // Returns the number of bytes remaining to be read.
-  size_t BytesRemaining() const;
-
-  // Truncates the reader down by reducing its internal length.
-  // If called immediately after calling this, BytesRemaining will
-  // return |truncation_length|. If truncation_length is less than the
-  // current value of BytesRemaining, this does nothing and returns false.
-  bool TruncateRemaining(size_t truncation_length);
-
-  // Returns the next byte that to be read. Must not be called when there are no
-  // bytes to be read.
-  //
-  // DOES NOT forward the internal iterator.
-  uint8_t PeekByte() const;
-
   // Read an IETF-encoded Variable Length Integer and place the result
   // in |*result|.
   // Returns true if it works, false if not. The only error is that
@@ -168,29 +82,6 @@
   // returns false if there is a read error or if the value is
   // greater than (2^32)-1.
   bool ReadVarIntU32(uint32_t* result);
-
-  std::string DebugString() const;
-
- private:
-  // Returns true if the underlying buffer has enough room to read the given
-  // amount of bytes.
-  bool CanRead(size_t bytes) const;
-
-  // To be called when a read fails for any reason.
-  void OnFailure();
-
-  // TODO(fkastenholz, b/73004262) change buffer_, et al, to be uint8_t, not
-  // char. The data buffer that we're reading from.
-  const char* data_;
-
-  // The length of the data buffer that we're reading from.
-  size_t len_;
-
-  // The location of the next read from our data buffer.
-  size_t pos_;
-
-  // The endianness to read integers and floating numbers.
-  quiche::Endianness endianness_;
 };
 
 }  // namespace quic
diff --git a/quic/core/quic_data_writer.cc b/quic/core/quic_data_writer.cc
index 28af68b..41c374c 100644
--- a/quic/core/quic_data_writer.cc
+++ b/quic/core/quic_data_writer.cc
@@ -18,57 +18,15 @@
 namespace quic {
 
 QuicDataWriter::QuicDataWriter(size_t size, char* buffer)
-    : QuicDataWriter(size, buffer, quiche::NETWORK_BYTE_ORDER) {}
+    : quiche::QuicheDataWriter(size, buffer) {}
 
 QuicDataWriter::QuicDataWriter(size_t size,
                                char* buffer,
                                quiche::Endianness endianness)
-    : buffer_(buffer), capacity_(size), length_(0), endianness_(endianness) {}
+    : quiche::QuicheDataWriter(size, buffer, endianness) {}
 
 QuicDataWriter::~QuicDataWriter() {}
 
-char* QuicDataWriter::data() {
-  return buffer_;
-}
-
-bool QuicDataWriter::WriteUInt8(uint8_t value) {
-  return WriteBytes(&value, sizeof(value));
-}
-
-bool QuicDataWriter::WriteUInt16(uint16_t value) {
-  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
-    value = quiche::QuicheEndian::HostToNet16(value);
-  }
-  return WriteBytes(&value, sizeof(value));
-}
-
-bool QuicDataWriter::WriteUInt32(uint32_t value) {
-  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
-    value = quiche::QuicheEndian::HostToNet32(value);
-  }
-  return WriteBytes(&value, sizeof(value));
-}
-
-bool QuicDataWriter::WriteUInt64(uint64_t value) {
-  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
-    value = quiche::QuicheEndian::HostToNet64(value);
-  }
-  return WriteBytes(&value, sizeof(value));
-}
-
-bool QuicDataWriter::WriteBytesToUInt64(size_t num_bytes, uint64_t value) {
-  if (num_bytes > sizeof(value)) {
-    return false;
-  }
-  if (endianness_ == quiche::HOST_BYTE_ORDER) {
-    return WriteBytes(&value, num_bytes);
-  }
-
-  value = quiche::QuicheEndian::HostToNet64(value);
-  return WriteBytes(reinterpret_cast<char*>(&value) + sizeof(value) - num_bytes,
-                    num_bytes);
-}
-
 bool QuicDataWriter::WriteUFloat16(uint64_t value) {
   uint16_t result;
   if (value < (UINT64_C(1) << kUFloat16MantissaEffectiveBits)) {
@@ -105,79 +63,12 @@
     result = static_cast<uint16_t>(value + (exponent << kUFloat16MantissaBits));
   }
 
-  if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+  if (endianness() == quiche::NETWORK_BYTE_ORDER) {
     result = quiche::QuicheEndian::HostToNet16(result);
   }
   return WriteBytes(&result, sizeof(result));
 }
 
-bool QuicDataWriter::WriteStringPiece16(quiche::QuicheStringPiece val) {
-  if (val.size() > std::numeric_limits<uint16_t>::max()) {
-    return false;
-  }
-  if (!WriteUInt16(static_cast<uint16_t>(val.size()))) {
-    return false;
-  }
-  return WriteBytes(val.data(), val.size());
-}
-
-bool QuicDataWriter::WriteStringPiece(quiche::QuicheStringPiece val) {
-  return WriteBytes(val.data(), val.size());
-}
-
-char* QuicDataWriter::BeginWrite(size_t length) {
-  if (length_ > capacity_) {
-    return nullptr;
-  }
-
-  if (capacity_ - length_ < length) {
-    return nullptr;
-  }
-
-#ifdef ARCH_CPU_64_BITS
-  DCHECK_LE(length, std::numeric_limits<uint32_t>::max());
-#endif
-
-  return buffer_ + length_;
-}
-
-bool QuicDataWriter::WriteBytes(const void* data, size_t data_len) {
-  char* dest = BeginWrite(data_len);
-  if (!dest) {
-    return false;
-  }
-
-  memcpy(dest, data, data_len);
-
-  length_ += data_len;
-  return true;
-}
-
-bool QuicDataWriter::WriteRepeatedByte(uint8_t byte, size_t count) {
-  char* dest = BeginWrite(count);
-  if (!dest) {
-    return false;
-  }
-
-  memset(dest, byte, count);
-
-  length_ += count;
-  return true;
-}
-
-void QuicDataWriter::WritePadding() {
-  DCHECK_LE(length_, capacity_);
-  if (length_ > capacity_) {
-    return;
-  }
-  memset(buffer_ + length_, 0x00, capacity_ - length_);
-  length_ = capacity_;
-}
-
-bool QuicDataWriter::WritePaddingBytes(size_t count) {
-  return WriteRepeatedByte(0x00, count);
-}
-
 bool QuicDataWriter::WriteConnectionId(QuicConnectionId connection_id) {
   if (connection_id.IsEmpty()) {
     return true;
@@ -190,10 +81,6 @@
   return WriteUInt8(connection_id.length()) && WriteConnectionId(connection_id);
 }
 
-bool QuicDataWriter::WriteTag(uint32_t tag) {
-  return WriteBytes(&tag, sizeof(tag));
-}
-
 bool QuicDataWriter::WriteRandomBytes(QuicRandom* random, size_t length) {
   char* dest = BeginWrite(length);
   if (!dest) {
@@ -201,17 +88,10 @@
   }
 
   random->RandBytes(dest, length);
-  length_ += length;
+  IncreaseLength(length);
   return true;
 }
 
-bool QuicDataWriter::Seek(size_t length) {
-  if (!BeginWrite(length)) {
-    return false;
-  }
-  length_ += length;
-  return true;
-}
 
 // Converts a uint64_t into an IETF/Quic formatted Variable Length
 // Integer. IETF Variable Length Integers have 62 significant bits, so
@@ -231,10 +111,10 @@
 // Low-level optimization is useful here because this function will be
 // called frequently, leading to outsize benefits.
 bool QuicDataWriter::WriteVarInt62(uint64_t value) {
-  DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
+  DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
 
-  size_t remaining = capacity_ - length_;
-  char* next = buffer_ + length_;
+  size_t remaining_bytes = remaining();
+  char* next = buffer() + length();
 
   if ((value & kVarInt62ErrorMask) == 0) {
     // We know the high 2 bits are 0 so |value| is legal.
@@ -242,7 +122,7 @@
     if ((value & kVarInt62Mask8Bytes) != 0) {
       // Someplace in the high-4 bytes is a 1-bit. Do an 8-byte
       // encoding.
-      if (remaining >= 8) {
+      if (remaining_bytes >= 8) {
         *(next + 0) = ((value >> 56) & 0x3f) + 0xc0;
         *(next + 1) = (value >> 48) & 0xff;
         *(next + 2) = (value >> 40) & 0xff;
@@ -251,7 +131,7 @@
         *(next + 5) = (value >> 16) & 0xff;
         *(next + 6) = (value >> 8) & 0xff;
         *(next + 7) = value & 0xff;
-        length_ += 8;
+        IncreaseLength(8);
         return true;
       }
       return false;
@@ -261,12 +141,12 @@
     if ((value & kVarInt62Mask4Bytes) != 0) {
       // The encoding will not fit into 2 bytes, Do a 4-byte
       // encoding.
-      if (remaining >= 4) {
+      if (remaining_bytes >= 4) {
         *(next + 0) = ((value >> 24) & 0x3f) + 0x80;
         *(next + 1) = (value >> 16) & 0xff;
         *(next + 2) = (value >> 8) & 0xff;
         *(next + 3) = value & 0xff;
-        length_ += 4;
+        IncreaseLength(4);
         return true;
       }
       return false;
@@ -279,18 +159,18 @@
     // are not 0)
     if ((value & kVarInt62Mask2Bytes) != 0) {
       // Do 2-byte encoding
-      if (remaining >= 2) {
+      if (remaining_bytes >= 2) {
         *(next + 0) = ((value >> 8) & 0x3f) + 0x40;
         *(next + 1) = (value)&0xff;
-        length_ += 2;
+        IncreaseLength(2);
         return true;
       }
       return false;
     }
-    if (remaining >= 1) {
+    if (remaining_bytes >= 1) {
       // Do 1-byte encoding
       *next = (value & 0x3f);
-      length_ += 1;
+      IncreaseLength(1);
       return true;
     }
     return false;
@@ -302,10 +182,10 @@
 bool QuicDataWriter::WriteVarInt62(
     uint64_t value,
     QuicVariableLengthIntegerLength write_length) {
-  DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
+  DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
 
-  size_t remaining = capacity_ - length_;
-  if (remaining < write_length) {
+  size_t remaining_bytes = remaining();
+  if (remaining_bytes < write_length) {
     return false;
   }
 
@@ -366,9 +246,4 @@
   return true;
 }
 
-std::string QuicDataWriter::DebugString() const {
-  return quiche::QuicheStrCat(" { capacity: ", capacity_, ", length: ", length_,
-                              " }");
-}
-
 }  // namespace quic
diff --git a/quic/core/quic_data_writer.h b/quic/core/quic_data_writer.h
index 7d90f39..3926c1a 100644
--- a/quic/core/quic_data_writer.h
+++ b/quic/core/quic_data_writer.h
@@ -12,6 +12,7 @@
 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
 #include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
 #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/quiche_data_writer.h"
 
 namespace quic {
 
@@ -35,7 +36,7 @@
 // The QuicDataWriter supports appending primitive values (int, string, etc)
 // to a frame instance.  The internal memory buffer is exposed as the "data"
 // of the QuicDataWriter.
-class QUIC_EXPORT_PRIVATE QuicDataWriter {
+class QUIC_EXPORT_PRIVATE QuicDataWriter : public quiche::QuicheDataWriter {
  public:
   // Creates a QuicDataWriter where |buffer| is not owned
   // using NETWORK_BYTE_ORDER endianness.
@@ -48,21 +49,9 @@
 
   ~QuicDataWriter();
 
-  // Returns the size of the QuicDataWriter's data.
-  size_t length() const { return length_; }
-
-  // Retrieves the buffer from the QuicDataWriter without changing ownership.
-  char* data();
-
   // Methods for adding to the payload.  These values are appended to the end
   // of the QuicDataWriter payload.
 
-  // Writes 8/16/32/64-bit unsigned integers.
-  bool WriteUInt8(uint8_t value);
-  bool WriteUInt16(uint16_t value);
-  bool WriteUInt32(uint32_t value);
-  bool WriteUInt64(uint64_t value);
-
   // Write an unsigned-integer value per the IETF QUIC/Variable Length
   // Integer encoding rules (see draft-ietf-quic-transport-08.txt).
   // IETF Variable Length Integers have 62 significant bits, so the
@@ -88,63 +77,18 @@
   // is too large to encode.
   static QuicVariableLengthIntegerLength GetVarInt62Len(uint64_t value);
 
-  // Writes least significant |num_bytes| of a 64-bit unsigned integer in the
-  // correct byte order.
-  bool WriteBytesToUInt64(size_t num_bytes, uint64_t value);
-
   // Write unsigned floating point corresponding to the value. Large values are
   // clamped to the maximum representable (kUFloat16MaxValue). Values that can
   // not be represented directly are rounded down.
   bool WriteUFloat16(uint64_t value);
-  bool WriteStringPiece(quiche::QuicheStringPiece val);
-  bool WriteStringPiece16(quiche::QuicheStringPiece val);
-  bool WriteBytes(const void* data, size_t data_len);
-  bool WriteRepeatedByte(uint8_t byte, size_t count);
-  // Fills the remaining buffer with null characters.
-  void WritePadding();
-  // Write padding of |count| bytes.
-  bool WritePaddingBytes(size_t count);
-
   // Write connection ID to the payload.
   bool WriteConnectionId(QuicConnectionId connection_id);
 
   // Write 8-bit length followed by connection ID to the payload.
   bool WriteLengthPrefixedConnectionId(QuicConnectionId connection_id);
 
-  // Write tag as a 32-bit unsigned integer to the payload. As tags are already
-  // converted to big endian (e.g., CHLO is 'C','H','L','O') in memory by TAG or
-  // MakeQuicTag and tags are written in byte order, so tags on the wire are
-  // in big endian.
-  bool WriteTag(uint32_t tag);
-
   // Write |length| random bytes generated by |random|.
   bool WriteRandomBytes(QuicRandom* random, size_t length);
-
-  // Advance the writer's position for writing by |length| bytes without writing
-  // anything. This method only makes sense to be used on a buffer that has
-  // already been written to (and is having certain parts rewritten).
-  bool Seek(size_t length);
-
-  size_t capacity() const { return capacity_; }
-
-  size_t remaining() const { return capacity_ - length_; }
-
-  std::string DebugString() const;
-
- private:
-  // Returns the location that the data should be written at, or nullptr if
-  // there is not enough room. Call EndWrite with the returned offset and the
-  // given length to pad out for the next write.
-  char* BeginWrite(size_t length);
-
-  // TODO(fkastenholz, b/73004262) change buffer_, et al, to be uint8_t, not
-  // char.
-  char* buffer_;
-  size_t capacity_;  // Allocation size of payload (or -1 if buffer is const).
-  size_t length_;    // Current length of the buffer.
-
-  // The endianness to write integers and floating numbers.
-  quiche::Endianness endianness_;
 };
 
 }  // namespace quic