pw_kvs: Introduce Input interface

- Provide the Input interface, which provides a generic Read function.
- Switch to non-virtual interfaces to allow for potential future
  pre/post operations (e.g. error handling, debug logging).

Change-Id: If7e95c3c47a090c7dc0a72426e6224c9ed04b62a
diff --git a/pw_kvs/alignment_test.cc b/pw_kvs/alignment_test.cc
index e82fee9..ab23388 100644
--- a/pw_kvs/alignment_test.cc
+++ b/pw_kvs/alignment_test.cc
@@ -186,7 +186,8 @@
    public:
     enum { kKeepGoing, kBreakOnNext, kBroken } state = kKeepGoing;
 
-    StatusWithSize Write(span<const byte> data) override {
+   private:
+    StatusWithSize DoWrite(span<const byte> data) override {
       switch (state) {
         case kKeepGoing:
           return StatusWithSize(data.size());
diff --git a/pw_kvs/flash_memory.cc b/pw_kvs/flash_memory.cc
index 0d164d8..71d9c14 100644
--- a/pw_kvs/flash_memory.cc
+++ b/pw_kvs/flash_memory.cc
@@ -26,12 +26,18 @@
 
 using std::byte;
 
-StatusWithSize FlashPartition::Output::Write(span<const byte> data) {
+StatusWithSize FlashPartition::Output::DoWrite(span<const byte> data) {
   TRY_WITH_SIZE(flash_.Write(address_, data));
   address_ += data.size();
   return StatusWithSize(data.size());
 }
 
+StatusWithSize FlashPartition::Input::DoRead(span<byte> data) {
+  StatusWithSize result = flash_.Read(address_, data);
+  address_ += result.size();
+  return result;
+}
+
 Status FlashPartition::Erase(Address address, size_t num_sectors) {
   if (permission_ == PartitionPermission::kReadOnly) {
     return Status::PERMISSION_DENIED;
diff --git a/pw_kvs/public/pw_kvs/flash_memory.h b/pw_kvs/public/pw_kvs/flash_memory.h
index 05b823f..b284415 100644
--- a/pw_kvs/public/pw_kvs/flash_memory.h
+++ b/pw_kvs/public/pw_kvs/flash_memory.h
@@ -134,9 +134,22 @@
     constexpr Output(FlashPartition& flash, FlashPartition::Address address)
         : flash_(flash), address_(address) {}
 
-    StatusWithSize Write(span<const std::byte> data) override;
+   private:
+    StatusWithSize DoWrite(span<const std::byte> data) override;
+
+    FlashPartition& flash_;
+    FlashPartition::Address address_;
+  };
+
+  // Implement Input for the Read method.
+  class Input final : public pw::Input {
+   public:
+    constexpr Input(FlashPartition& flash, FlashPartition::Address address)
+        : flash_(flash), address_(address) {}
 
    private:
+    StatusWithSize DoRead(span<std::byte> data) override;
+
     FlashPartition& flash_;
     FlashPartition::Address address_;
   };
diff --git a/pw_kvs/public/pw_kvs/io.h b/pw_kvs/public/pw_kvs/io.h
index fae001f..71d1eb2 100644
--- a/pw_kvs/public/pw_kvs/io.h
+++ b/pw_kvs/public/pw_kvs/io.h
@@ -37,7 +37,7 @@
 // span of bytes and returns a Status.
 class Output {
  public:
-  virtual StatusWithSize Write(span<const std::byte> data) = 0;
+  StatusWithSize Write(span<const std::byte> data) { return DoWrite(data); }
 
   // Convenience wrapper for writing data from a pointer and length.
   StatusWithSize Write(const void* data, size_t size_bytes) {
@@ -46,6 +46,25 @@
 
  protected:
   ~Output() = default;
+
+ private:
+  virtual StatusWithSize DoWrite(span<const std::byte> data) = 0;
+};
+
+class Input {
+ public:
+  StatusWithSize Read(span<std::byte> data) { return DoRead(data); }
+
+  // Convenience wrapper for reading data from a pointer and length.
+  StatusWithSize Read(void* data, size_t size_bytes) {
+    return Read(span(static_cast<std::byte*>(data), size_bytes));
+  }
+
+ protected:
+  ~Input() = default;
+
+ private:
+  virtual StatusWithSize DoRead(span<std::byte> data) = 0;
 };
 
 // Output adapter that calls a method on a class with a span of bytes. If the
@@ -58,7 +77,8 @@
  public:
   constexpr OutputToMethod(Class* object) : object_(*object) {}
 
-  StatusWithSize Write(span<const std::byte> data) override {
+ private:
+  StatusWithSize DoWrite(span<const std::byte> data) override {
     using Return = typename internal::FunctionTraits<decltype(kMethod)>::Return;
 
     if constexpr (std::is_void_v<Return>) {
@@ -79,7 +99,8 @@
   OutputToFunction(StatusWithSize (*function)(span<const std::byte>))
       : function_(function) {}
 
-  StatusWithSize Write(span<const std::byte> data) override {
+ private:
+  StatusWithSize DoWrite(span<const std::byte> data) override {
     return function_(data);
   }