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