Adds a DataSource class to represent a HTTP message body.

PiperOrigin-RevId: 374412322
diff --git a/http2/adapter/data_source.cc b/http2/adapter/data_source.cc
new file mode 100644
index 0000000..13f89d2
--- /dev/null
+++ b/http2/adapter/data_source.cc
@@ -0,0 +1,23 @@
+#include "http2/adapter/data_source.h"
+
+namespace http2 {
+namespace adapter {
+
+StringDataSource::StringDataSource(std::string data)
+    : data_(std::move(data)), remaining_(data_) {
+  state_ = remaining_.empty() ? DONE : READY;
+}
+
+absl::string_view StringDataSource::NextData() const {
+  return remaining_;
+}
+
+void StringDataSource::Consume(size_t bytes) {
+  remaining_.remove_prefix(std::min(bytes, remaining_.size()));
+  if (remaining_.empty()) {
+    state_ = DONE;
+  }
+}
+
+}  // namespace adapter
+}  // namespace http2
diff --git a/http2/adapter/data_source.h b/http2/adapter/data_source.h
new file mode 100644
index 0000000..e170104
--- /dev/null
+++ b/http2/adapter/data_source.h
@@ -0,0 +1,53 @@
+#ifndef QUICHE_HTTP2_ADAPTER_DATA_SOURCE_H_
+#define QUICHE_HTTP2_ADAPTER_DATA_SOURCE_H_
+
+#include <string>
+
+#include "absl/strings/string_view.h"
+
+namespace http2 {
+namespace adapter {
+
+// Represents a HTTP message body.
+class DataSource {
+ public:
+  virtual ~DataSource() {}
+
+  enum State {
+    // The source is not done, but cannot currently provide more data.
+    NOT_READY,
+    // The source can provide more data.
+    READY,
+    // The source is done.
+    DONE,
+  };
+
+  State state() const { return state_; }
+
+  // The next range of data provided by this data source.
+  virtual absl::string_view NextData() const = 0;
+
+  // Indicates that |bytes| bytes have been consumed by the caller.
+  virtual void Consume(size_t bytes) = 0;
+
+ protected:
+  State state_ = NOT_READY;
+};
+
+// A simple implementation constructible from a string_view or std::string.
+class StringDataSource : public DataSource {
+ public:
+  explicit StringDataSource(std::string data);
+
+  absl::string_view NextData() const override;
+  void Consume(size_t bytes) override;
+
+ private:
+  const std::string data_;
+  absl::string_view remaining_;
+};
+
+}  // namespace adapter
+}  // namespace http2
+
+#endif  // QUICHE_HTTP2_ADAPTER_DATA_SOURCE_H_
diff --git a/http2/adapter/data_source_test.cc b/http2/adapter/data_source_test.cc
new file mode 100644
index 0000000..c290124
--- /dev/null
+++ b/http2/adapter/data_source_test.cc
@@ -0,0 +1,40 @@
+#include "http2/adapter/data_source.h"
+
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+TEST(StringDataSourceTest, EmptyString) {
+  StringDataSource source("");
+
+  EXPECT_EQ(source.state(), DataSource::DONE);
+  EXPECT_THAT(source.NextData(), testing::IsEmpty());
+}
+
+TEST(StringDataSourceTest, PartialConsume) {
+  StringDataSource source("I'm a HTTP message body. Really!");
+
+  EXPECT_EQ(source.state(), DataSource::READY);
+  EXPECT_THAT(source.NextData(), testing::Not(testing::IsEmpty()));
+  source.Consume(6);
+  EXPECT_EQ(source.state(), DataSource::READY);
+  EXPECT_THAT(source.NextData(), testing::StartsWith("HTTP"));
+
+  source.Consume(0);
+  EXPECT_EQ(source.state(), DataSource::READY);
+  EXPECT_THAT(source.NextData(), testing::StartsWith("HTTP"));
+
+  // Consumes more than the remaining bytes available.
+  source.Consume(50);
+  EXPECT_THAT(source.NextData(), testing::IsEmpty())
+      << "next data: " << source.NextData();
+  EXPECT_EQ(source.state(), DataSource::DONE);
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace adapter
+}  // namespace http2