pw_stream: Provide default read/write limit functions

- Have default ConservativeReadLimit and ConservativeWriteLimit
  functions that return std::numeric_limits<size_t>::max().
- Add a NullReader to accompany the NullWriter
- Add tests for the default read/write limit functions.

Change-Id: Id211dbc1ceef2f4f0046e936749b989516484e9f
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/26765
Reviewed-by: Ewout van Bekkum <ewout@google.com>
Reviewed-by: Armando Montanez <amontanez@google.com>
Commit-Queue: Wyatt Hepler <hepler@google.com>
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
diff --git a/pw_stream/BUILD b/pw_stream/BUILD
index 242d460..996c044 100644
--- a/pw_stream/BUILD
+++ b/pw_stream/BUILD
@@ -24,15 +24,14 @@
 
 pw_cc_library(
     name = "pw_stream",
-    hdrs = [
-      "public/pw_stream/buffered_stream.h",
-      "public/pw_stream/memory_stream.h",
-      "public/pw_stream/null_stream.h",
-      "public/pw_stream/stream.h",
-    ],
     srcs = [
-      "memory_stream.cc",
-      "buffered_stream.cc",
+        "buffered_stream.cc",
+        "memory_stream.cc",
+    ],
+    hdrs = [
+        "public/pw_stream/memory_stream.h",
+        "public/pw_stream/null_stream.h",
+        "public/pw_stream/stream.h",
     ],
     includes = ["public"],
     deps = [
@@ -49,8 +48,8 @@
     srcs = ["socket_stream.cc"],
     hdrs = ["public/pw_stream/socket_stream.h"],
     deps = [
-        "//pw_sys_io",
         "//pw_stream",
+        "//pw_sys_io",
     ],
 )
 
@@ -58,8 +57,8 @@
     name = "pw_stream_sys_io",
     hdrs = ["public/pw_stream/sys_io_stream.h"],
     deps = [
-        "//pw_sys_io",
         "//pw_stream",
+        "//pw_sys_io",
     ],
 )
 
@@ -75,9 +74,9 @@
 )
 
 pw_cc_test(
-    name = "buffered_stream_test",
+    name = "stream_test",
     srcs = [
-        "buffered_stream_test.cc",
+        "stream_test.cc",
     ],
     deps = [
         ":pw_stream",
diff --git a/pw_stream/BUILD.gn b/pw_stream/BUILD.gn
index a8efd15..cb7d6cf 100644
--- a/pw_stream/BUILD.gn
+++ b/pw_stream/BUILD.gn
@@ -63,10 +63,18 @@
 }
 
 pw_test_group("tests") {
-  tests = [ ":memory_stream_test" ]
+  tests = [
+    ":memory_stream_test",
+    ":stream_test",
+  ]
 }
 
 pw_test("memory_stream_test") {
   sources = [ "memory_stream_test.cc" ]
   deps = [ ":pw_stream" ]
 }
+
+pw_test("stream_test") {
+  sources = [ "stream_test.cc" ]
+  deps = [ ":pw_stream" ]
+}
diff --git a/pw_stream/public/pw_stream/null_stream.h b/pw_stream/public/pw_stream/null_stream.h
index 70048dc..eda1209 100644
--- a/pw_stream/public/pw_stream/null_stream.h
+++ b/pw_stream/public/pw_stream/null_stream.h
@@ -25,15 +25,15 @@
 
 // Stream writer which quietly drops all of the data, similar to /dev/null.
 class NullWriter final : public Writer {
- public:
-  size_t ConservativeWriteLimit() const override {
-    // In theory this can sink as much as is addressable, however this way it is
-    // compliant with pw::StatusWithSize.
-    return StatusWithSize::max_size();
-  }
-
  private:
-  Status DoWrite(ConstByteSpan data) override { return Status::Ok(); }
+  Status DoWrite(ConstByteSpan) final { return Status::Ok(); }
+};
+
+// Stream reader which never reads any bytes. Always returns OUT_OF_RANGE, which
+// indicates there is no more data to read.
+class NullReader final : public Reader {
+ private:
+  StatusWithSize DoRead(ByteSpan) final { return StatusWithSize::OutOfRange(); }
 };
 
 }  // namespace pw::stream
diff --git a/pw_stream/public/pw_stream/socket_stream.h b/pw_stream/public/pw_stream/socket_stream.h
index ac8e9e0..b7079e6 100644
--- a/pw_stream/public/pw_stream/socket_stream.h
+++ b/pw_stream/public/pw_stream/socket_stream.h
@@ -38,14 +38,6 @@
   // Listen to the port and return after a client is connected
   Status Init(uint16_t port);
 
-  size_t ConservativeWriteLimit() const override {
-    return std::numeric_limits<size_t>::max();
-  }
-
-  size_t ConservativeReadLimit() const override {
-    return std::numeric_limits<size_t>::max();
-  }
-
  private:
   Status DoWrite(std::span<const std::byte> data) override;
 
diff --git a/pw_stream/public/pw_stream/stream.h b/pw_stream/public/pw_stream/stream.h
index e52bb7c..9bbb069 100644
--- a/pw_stream/public/pw_stream/stream.h
+++ b/pw_stream/public/pw_stream/stream.h
@@ -75,7 +75,12 @@
   // other contexts write data this number can go up or down for some Writers.
   // Returns zero if, in the current state, Write() would not return
   // Status::Ok().
-  virtual size_t ConservativeWriteLimit() const = 0;
+  //
+  // Returns std::numeric_limits<size_t>::max() if the implementation has no
+  // limits on write sizes.
+  virtual size_t ConservativeWriteLimit() const {
+    return std::numeric_limits<size_t>::max();
+  }
 
  private:
   virtual Status DoWrite(ConstByteSpan data) = 0;
@@ -128,7 +133,12 @@
   // number can go up or down for some Readers.
   // Returns zero if, in the current state, Read() would not return
   // Status::Ok().
-  virtual size_t ConservativeReadLimit() const = 0;
+  //
+  // Returns std::numeric_limits<size_t>::max() if the implementation imposes no
+  // limits on read sizes.
+  virtual size_t ConservativeReadLimit() const {
+    return std::numeric_limits<size_t>::max();
+  }
 
  private:
   virtual StatusWithSize DoRead(ByteSpan dest) = 0;
diff --git a/pw_stream/public/pw_stream/sys_io_stream.h b/pw_stream/public/pw_stream/sys_io_stream.h
index e4c79ce..446f5a4 100644
--- a/pw_stream/public/pw_stream/sys_io_stream.h
+++ b/pw_stream/public/pw_stream/sys_io_stream.h
@@ -24,11 +24,6 @@
 namespace pw::stream {
 
 class SysIoWriter : public Writer {
- public:
-  size_t ConservativeWriteLimit() const override {
-    return std::numeric_limits<size_t>::max();
-  }
-
  private:
   Status DoWrite(std::span<const std::byte> data) override {
     return pw::sys_io::WriteBytes(data).status();
@@ -36,11 +31,6 @@
 };
 
 class SysIoReader : public Reader {
- public:
-  size_t ConservativeReadLimit() const override {
-    return std::numeric_limits<size_t>::max();
-  }
-
  private:
   StatusWithSize DoRead(ByteSpan dest) override {
     return pw::sys_io::ReadBytes(dest);
diff --git a/pw_stream/stream_test.cc b/pw_stream/stream_test.cc
new file mode 100644
index 0000000..fad335a
--- /dev/null
+++ b/pw_stream/stream_test.cc
@@ -0,0 +1,37 @@
+// Copyright 2020 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include "pw_stream/stream.h"
+
+#include <limits>
+
+#include "gtest/gtest.h"
+#include "pw_stream/null_stream.h"
+
+namespace pw::stream {
+namespace {
+
+TEST(Stream, DefaultConservativeWriteLimit) {
+  NullWriter stream;
+  EXPECT_EQ(stream.ConservativeWriteLimit(),
+            std::numeric_limits<size_t>::max());
+}
+
+TEST(Stream, DefaultConservativeReadLimit) {
+  NullReader stream;
+  EXPECT_EQ(stream.ConservativeReadLimit(), std::numeric_limits<size_t>::max());
+}
+
+}  // namespace
+}  // namespace pw::stream