pw_rpc: Reorganize Nanopb implementation

As with raw, replace "nanopb_" file prefixes with a directory path.

Change-Id: Id7e21069850fbfe61bcc3d644881d5f0411830e6
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/52863
Commit-Queue: Wyatt Hepler <hepler@google.com>
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
Reviewed-by: Alexei Frolov <frolv@google.com>
diff --git a/pw_metric/metric_service_nanopb_test.cc b/pw_metric/metric_service_nanopb_test.cc
index 5810982..bbb1e2d 100644
--- a/pw_metric/metric_service_nanopb_test.cc
+++ b/pw_metric/metric_service_nanopb_test.cc
@@ -16,7 +16,7 @@
 
 #include "gtest/gtest.h"
 #include "pw_log/log.h"
-#include "pw_rpc/nanopb_test_method_context.h"
+#include "pw_rpc/nanopb/test_method_context.h"
 
 namespace pw::metric {
 namespace {
diff --git a/pw_rpc/BUILD.bazel b/pw_rpc/BUILD.bazel
index 14677b7..b346123 100644
--- a/pw_rpc/BUILD.bazel
+++ b/pw_rpc/BUILD.bazel
@@ -144,21 +144,22 @@
 filegroup(
     name = "nanopb",
     srcs = [
+        "nanopb/client_call.cc",
+        "nanopb/client_call_test.cc",
         "nanopb/codegen_test.cc",
+        "nanopb/common.cc",
         "nanopb/echo_service_test.cc",
+        "nanopb/method.cc",
         "nanopb/method_lookup_test.cc",
-        "nanopb/nanopb_client_call.cc",
-        "nanopb/nanopb_client_call_test.cc",
-        "nanopb/nanopb_common.cc",
-        "nanopb/nanopb_method.cc",
-        "nanopb/nanopb_method_test.cc",
-        "nanopb/nanopb_method_union_test.cc",
+        "nanopb/method_test.cc",
+        "nanopb/method_union_test.cc",
         "nanopb/public/pw_rpc/echo_service_nanopb.h",
-        "nanopb/public/pw_rpc/internal/nanopb_common.h",
-        "nanopb/public/pw_rpc/internal/nanopb_method.h",
-        "nanopb/public/pw_rpc/internal/nanopb_method_union.h",
+        "nanopb/public/pw_rpc/nanopb/client_call.h",
+        "nanopb/public/pw_rpc/nanopb/internal/common.h",
+        "nanopb/public/pw_rpc/nanopb/internal/method.h",
+        "nanopb/public/pw_rpc/nanopb/internal/method_union.h",
         "nanopb/public/pw_rpc/nanopb/server_reader_writer.h",
-        "nanopb/public/pw_rpc/nanopb_client_call.h",
+        "nanopb/public/pw_rpc/nanopb/test_method_context.h",
         "nanopb/public/pw_rpc/nanopb_test_method_context.h",
         "nanopb/pw_rpc_nanopb_private/internal_test_utils.h",
         "nanopb/server_reader_writer.cc",
diff --git a/pw_rpc/nanopb/BUILD.gn b/pw_rpc/nanopb/BUILD.gn
index 8d4be43..6f72c77 100644
--- a/pw_rpc/nanopb/BUILD.gn
+++ b/pw_rpc/nanopb/BUILD.gn
@@ -27,11 +27,11 @@
 pw_source_set("method") {
   public_configs = [ ":public" ]
   public = [
-    "public/pw_rpc/internal/nanopb_method.h",
+    "public/pw_rpc/nanopb/internal/method.h",
     "public/pw_rpc/nanopb/server_reader_writer.h",
   ]
   sources = [
-    "nanopb_method.cc",
+    "method.cc",
     "server_reader_writer.cc",
   ]
   public_deps = [
@@ -45,7 +45,7 @@
 
 pw_source_set("method_union") {
   public_configs = [ ":public" ]
-  public = [ "public/pw_rpc/internal/nanopb_method_union.h" ]
+  public = [ "public/pw_rpc/nanopb/internal/method_union.h" ]
   public_deps = [
     ":method",
     "$dir_pw_rpc/raw:method_union",
@@ -59,15 +59,15 @@
     "..:client",
     dir_pw_function,
   ]
-  public = [ "public/pw_rpc/nanopb_client_call.h" ]
-  sources = [ "nanopb_client_call.cc" ]
+  public = [ "public/pw_rpc/nanopb/client_call.h" ]
+  sources = [ "client_call.cc" ]
 }
 
 pw_source_set("common") {
   public_deps = [ dir_pw_bytes ]
   public_configs = [ ":public" ]
-  public = [ "public/pw_rpc/internal/nanopb_common.h" ]
-  sources = [ "nanopb_common.cc" ]
+  public = [ "public/pw_rpc/nanopb/internal/common.h" ]
+  sources = [ "common.cc" ]
 
   if (dir_pw_third_party_nanopb != "") {
     public_deps += [ "$dir_pw_third_party/nanopb" ]
@@ -76,7 +76,10 @@
 
 pw_source_set("test_method_context") {
   public_configs = [ ":public" ]
-  public = [ "public/pw_rpc/nanopb_test_method_context.h" ]
+  public = [
+    "public/pw_rpc/nanopb/test_method_context.h",
+    "public/pw_rpc/nanopb_test_method_context.h",
+  ]
   public_deps = [
     ":method",
     "..:test_utils",
@@ -109,8 +112,8 @@
     ":codegen_test",
     ":echo_service_test",
     ":method_lookup_test",
-    ":nanopb_method_test",
-    ":nanopb_method_union_test",
+    ":method_test",
+    ":method_union_test",
     ":stub_generation_test",
   ]
 }
@@ -122,7 +125,7 @@
     "..:test_protos.nanopb",
     "..:test_utils",
   ]
-  sources = [ "nanopb_client_call_test.cc" ]
+  sources = [ "client_call_test.cc" ]
   enable_if = dir_pw_third_party_nanopb != ""
 }
 
@@ -139,7 +142,7 @@
   enable_if = dir_pw_third_party_nanopb != ""
 }
 
-pw_test("nanopb_method_test") {
+pw_test("method_test") {
   deps = [
     ":internal_test_utils",
     ":method_union",
@@ -147,7 +150,7 @@
     "..:test_protos.nanopb",
     "..:test_utils",
   ]
-  sources = [ "nanopb_method_test.cc" ]
+  sources = [ "method_test.cc" ]
   enable_if = dir_pw_third_party_nanopb != ""
 }
 
@@ -163,14 +166,14 @@
   enable_if = dir_pw_third_party_nanopb != ""
 }
 
-pw_test("nanopb_method_union_test") {
+pw_test("method_union_test") {
   deps = [
     ":internal_test_utils",
     ":method_union",
     "..:test_protos.nanopb",
     "..:test_utils",
   ]
-  sources = [ "nanopb_method_union_test.cc" ]
+  sources = [ "method_union_test.cc" ]
   enable_if = dir_pw_third_party_nanopb != ""
 }
 
diff --git a/pw_rpc/nanopb/CMakeLists.txt b/pw_rpc/nanopb/CMakeLists.txt
index 66547f9..6f879f7 100644
--- a/pw_rpc/nanopb/CMakeLists.txt
+++ b/pw_rpc/nanopb/CMakeLists.txt
@@ -16,7 +16,7 @@
 
 pw_add_module_library(pw_rpc.nanopb.method
   SOURCES
-    nanopb_method.cc
+    method.cc
   PUBLIC_DEPS
     pw_rpc.nanopb.common
     pw_rpc.server
@@ -35,7 +35,7 @@
 
 pw_add_module_library(pw_rpc.nanopb.client
   SOURCES
-    nanopb_client_call.cc
+    client_call.cc
   PUBLIC_DEPS
     pw_function
     pw_rpc.nanopb.common
@@ -44,7 +44,7 @@
 
 pw_add_module_library(pw_rpc.nanopb.common
   SOURCES
-    nanopb_common.cc
+    common.cc
   PUBLIC_DEPS
     pw_bytes
     pw_rpc.common
diff --git a/pw_rpc/nanopb/nanopb_client_call.cc b/pw_rpc/nanopb/client_call.cc
similarity index 96%
rename from pw_rpc/nanopb/nanopb_client_call.cc
rename to pw_rpc/nanopb/client_call.cc
index 89440a6..e7b4939 100644
--- a/pw_rpc/nanopb/nanopb_client_call.cc
+++ b/pw_rpc/nanopb/client_call.cc
@@ -12,7 +12,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-#include "pw_rpc/nanopb_client_call.h"
+#include "pw_rpc/nanopb/client_call.h"
 
 namespace pw::rpc {
 namespace internal {
diff --git a/pw_rpc/nanopb/nanopb_client_call_test.cc b/pw_rpc/nanopb/client_call_test.cc
similarity index 99%
rename from pw_rpc/nanopb/nanopb_client_call_test.cc
rename to pw_rpc/nanopb/client_call_test.cc
index c9d87d2..ae24fd7 100644
--- a/pw_rpc/nanopb/nanopb_client_call_test.cc
+++ b/pw_rpc/nanopb/client_call_test.cc
@@ -12,7 +12,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-#include "pw_rpc/nanopb_client_call.h"
+#include "pw_rpc/nanopb/client_call.h"
 
 #include "gtest/gtest.h"
 #include "pw_rpc_nanopb_private/internal_test_utils.h"
diff --git a/pw_rpc/nanopb/codegen_test.cc b/pw_rpc/nanopb/codegen_test.cc
index cbc2619..5c9fbe8 100644
--- a/pw_rpc/nanopb/codegen_test.cc
+++ b/pw_rpc/nanopb/codegen_test.cc
@@ -14,7 +14,7 @@
 
 #include "gtest/gtest.h"
 #include "pw_rpc/internal/hash.h"
-#include "pw_rpc/nanopb_test_method_context.h"
+#include "pw_rpc/nanopb/test_method_context.h"
 #include "pw_rpc_nanopb_private/internal_test_utils.h"
 #include "pw_rpc_private/internal_test_utils.h"
 #include "pw_rpc_test_protos/test.rpc.pb.h"
diff --git a/pw_rpc/nanopb/nanopb_common.cc b/pw_rpc/nanopb/common.cc
similarity index 97%
rename from pw_rpc/nanopb/nanopb_common.cc
rename to pw_rpc/nanopb/common.cc
index 6e6e611..9f959e5 100644
--- a/pw_rpc/nanopb/nanopb_common.cc
+++ b/pw_rpc/nanopb/common.cc
@@ -12,7 +12,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-#include "pw_rpc/internal/nanopb_common.h"
+#include "pw_rpc/nanopb/internal/common.h"
 
 #include "pb_decode.h"
 #include "pb_encode.h"
diff --git a/pw_rpc/nanopb/echo_service_test.cc b/pw_rpc/nanopb/echo_service_test.cc
index 11a0608..4d134c2 100644
--- a/pw_rpc/nanopb/echo_service_test.cc
+++ b/pw_rpc/nanopb/echo_service_test.cc
@@ -14,7 +14,7 @@
 
 #include "gtest/gtest.h"
 #include "pw_rpc/echo_service_nanopb.h"
-#include "pw_rpc/nanopb_test_method_context.h"
+#include "pw_rpc/nanopb/test_method_context.h"
 
 namespace pw::rpc {
 namespace {
diff --git a/pw_rpc/nanopb/nanopb_method.cc b/pw_rpc/nanopb/method.cc
similarity index 98%
rename from pw_rpc/nanopb/nanopb_method.cc
rename to pw_rpc/nanopb/method.cc
index 6ae45be..03ec30e 100644
--- a/pw_rpc/nanopb/nanopb_method.cc
+++ b/pw_rpc/nanopb/method.cc
@@ -12,7 +12,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-#include "pw_rpc/internal/nanopb_method.h"
+#include "pw_rpc/nanopb/internal/method.h"
 
 #include "pb_decode.h"
 #include "pb_encode.h"
diff --git a/pw_rpc/nanopb/method_lookup_test.cc b/pw_rpc/nanopb/method_lookup_test.cc
index bfb0da8..cc28a35 100644
--- a/pw_rpc/nanopb/method_lookup_test.cc
+++ b/pw_rpc/nanopb/method_lookup_test.cc
@@ -13,7 +13,7 @@
 // the License.
 
 #include "gtest/gtest.h"
-#include "pw_rpc/nanopb_test_method_context.h"
+#include "pw_rpc/nanopb/test_method_context.h"
 #include "pw_rpc/raw/test_method_context.h"
 #include "pw_rpc_test_protos/test.rpc.pb.h"
 
diff --git a/pw_rpc/nanopb/nanopb_method_test.cc b/pw_rpc/nanopb/method_test.cc
similarity index 99%
rename from pw_rpc/nanopb/nanopb_method_test.cc
rename to pw_rpc/nanopb/method_test.cc
index 8964ac4..5eb2e78 100644
--- a/pw_rpc/nanopb/nanopb_method_test.cc
+++ b/pw_rpc/nanopb/method_test.cc
@@ -12,12 +12,12 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-#include "pw_rpc/internal/nanopb_method.h"
+#include "pw_rpc/nanopb/internal/method.h"
 
 #include <array>
 
 #include "gtest/gtest.h"
-#include "pw_rpc/internal/nanopb_method_union.h"
+#include "pw_rpc/nanopb/internal/method_union.h"
 #include "pw_rpc/server_context.h"
 #include "pw_rpc/service.h"
 #include "pw_rpc_nanopb_private/internal_test_utils.h"
diff --git a/pw_rpc/nanopb/nanopb_method_union_test.cc b/pw_rpc/nanopb/method_union_test.cc
similarity index 99%
rename from pw_rpc/nanopb/nanopb_method_union_test.cc
rename to pw_rpc/nanopb/method_union_test.cc
index cb3ef71..5710087 100644
--- a/pw_rpc/nanopb/nanopb_method_union_test.cc
+++ b/pw_rpc/nanopb/method_union_test.cc
@@ -12,7 +12,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-#include "pw_rpc/internal/nanopb_method_union.h"
+#include "pw_rpc/nanopb/internal/method_union.h"
 
 #include <array>
 
diff --git a/pw_rpc/nanopb/public/pw_rpc/nanopb_client_call.h b/pw_rpc/nanopb/public/pw_rpc/nanopb/client_call.h
similarity index 98%
rename from pw_rpc/nanopb/public/pw_rpc/nanopb_client_call.h
rename to pw_rpc/nanopb/public/pw_rpc/nanopb/client_call.h
index 1f4d285..c1e6c95 100644
--- a/pw_rpc/nanopb/public/pw_rpc/nanopb_client_call.h
+++ b/pw_rpc/nanopb/public/pw_rpc/nanopb/client_call.h
@@ -19,7 +19,7 @@
 #include "pw_function/function.h"
 #include "pw_rpc/internal/base_client_call.h"
 #include "pw_rpc/internal/method_type.h"
-#include "pw_rpc/internal/nanopb_common.h"
+#include "pw_rpc/nanopb/internal/common.h"
 #include "pw_status/status.h"
 
 namespace pw::rpc {
diff --git a/pw_rpc/nanopb/public/pw_rpc/internal/nanopb_common.h b/pw_rpc/nanopb/public/pw_rpc/nanopb/internal/common.h
similarity index 100%
rename from pw_rpc/nanopb/public/pw_rpc/internal/nanopb_common.h
rename to pw_rpc/nanopb/public/pw_rpc/nanopb/internal/common.h
diff --git a/pw_rpc/nanopb/public/pw_rpc/internal/nanopb_method.h b/pw_rpc/nanopb/public/pw_rpc/nanopb/internal/method.h
similarity index 99%
rename from pw_rpc/nanopb/public/pw_rpc/internal/nanopb_method.h
rename to pw_rpc/nanopb/public/pw_rpc/nanopb/internal/method.h
index e7cedb5..415ba75 100644
--- a/pw_rpc/nanopb/public/pw_rpc/internal/nanopb_method.h
+++ b/pw_rpc/nanopb/public/pw_rpc/nanopb/internal/method.h
@@ -23,8 +23,8 @@
 #include "pw_rpc/internal/config.h"
 #include "pw_rpc/internal/method.h"
 #include "pw_rpc/internal/method_type.h"
-#include "pw_rpc/internal/nanopb_common.h"
 #include "pw_rpc/internal/responder.h"
+#include "pw_rpc/nanopb/internal/common.h"
 #include "pw_rpc/nanopb/server_reader_writer.h"
 #include "pw_rpc/server_context.h"
 #include "pw_status/status.h"
diff --git a/pw_rpc/nanopb/public/pw_rpc/internal/nanopb_method_union.h b/pw_rpc/nanopb/public/pw_rpc/nanopb/internal/method_union.h
similarity index 97%
rename from pw_rpc/nanopb/public/pw_rpc/internal/nanopb_method_union.h
rename to pw_rpc/nanopb/public/pw_rpc/nanopb/internal/method_union.h
index 3914397..12bfe1d 100644
--- a/pw_rpc/nanopb/public/pw_rpc/internal/nanopb_method_union.h
+++ b/pw_rpc/nanopb/public/pw_rpc/nanopb/internal/method_union.h
@@ -15,7 +15,7 @@
 
 #include "pw_bytes/span.h"
 #include "pw_rpc/internal/method_union.h"
-#include "pw_rpc/internal/nanopb_method.h"
+#include "pw_rpc/nanopb/internal/method.h"
 #include "pw_rpc/raw/internal/method_union.h"
 
 namespace pw::rpc::internal {
diff --git a/pw_rpc/nanopb/public/pw_rpc/nanopb/test_method_context.h b/pw_rpc/nanopb/public/pw_rpc/nanopb/test_method_context.h
new file mode 100644
index 0000000..cc36b3d
--- /dev/null
+++ b/pw_rpc/nanopb/public/pw_rpc/nanopb/test_method_context.h
@@ -0,0 +1,272 @@
+// 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.
+#pragma once
+
+#include <tuple>
+#include <utility>
+
+#include "pw_assert/assert.h"
+#include "pw_bytes/span.h"
+#include "pw_containers/vector.h"
+#include "pw_preprocessor/arguments.h"
+#include "pw_rpc/internal/hash.h"
+#include "pw_rpc/internal/method_lookup.h"
+#include "pw_rpc/internal/test_method_context.h"
+#include "pw_rpc/nanopb/internal/method.h"
+#include "pw_rpc_private/fake_channel_output.h"
+
+namespace pw::rpc {
+
+// Declares a context object that may be used to invoke an RPC. The context is
+// declared with the name of the implemented service and the method to invoke.
+// The RPC can then be invoked with the call method.
+//
+// For a unary RPC, context.call(request) returns the status, and the response
+// struct can be accessed via context.response().
+//
+//   PW_NANOPB_TEST_METHOD_CONTEXT(my::CoolService, TheMethod) context;
+//   EXPECT_EQ(OkStatus(), context.call({.some_arg = 123}));
+//   EXPECT_EQ(500, context.response().some_response_value);
+//
+// For a server streaming RPC, context.call(request) invokes the method. As in a
+// normal RPC, the method completes when the ServerWriter's Finish method is
+// called (or it goes out of scope).
+//
+//   PW_NANOPB_TEST_METHOD_CONTEXT(my::CoolService, TheStreamingMethod) context;
+//   context.call({.some_arg = 123});
+//
+//   EXPECT_TRUE(context.done());  // Check that the RPC completed
+//   EXPECT_EQ(OkStatus(), context.status());  // Check the status
+//
+//   EXPECT_EQ(3u, context.responses().size());
+//   EXPECT_EQ(123, context.responses()[0].value); // check individual responses
+//
+//   for (const MyResponse& response : context.responses()) {
+//     // iterate over the responses
+//   }
+//
+// PW_NANOPB_TEST_METHOD_CONTEXT forwards its constructor arguments to the
+// underlying serivce. For example:
+//
+//   PW_NANOPB_TEST_METHOD_CONTEXT(MyService, Go) context(service, args);
+//
+// PW_NANOPB_TEST_METHOD_CONTEXT takes two optional arguments:
+//
+//   size_t kMaxResponses: maximum responses to store; ignored unless streaming
+//   size_t kOutputSizeBytes: buffer size; must be large enough for a packet
+//
+// Example:
+//
+//   PW_NANOPB_TEST_METHOD_CONTEXT(MyService, BestMethod, 3, 256) context;
+//   ASSERT_EQ(3u, context.responses().max_size());
+//
+#define PW_NANOPB_TEST_METHOD_CONTEXT(service, method, ...)              \
+  ::pw::rpc::NanopbTestMethodContext<service,                            \
+                                     &service::method,                   \
+                                     ::pw::rpc::internal::Hash(#method), \
+                                     ##__VA_ARGS__>
+template <typename Service,
+          auto kMethod,
+          uint32_t kMethodId,
+          size_t kMaxResponses = 4,
+          size_t kOutputSizeBytes = 128>
+class NanopbTestMethodContext;
+
+// Internal classes that implement NanopbTestMethodContext.
+namespace internal::test::nanopb {
+
+// A ChannelOutput implementation that stores the outgoing payloads and status.
+template <typename Response, size_t kMaxResponses, size_t kOutputSize>
+class MessageOutput final : public FakeChannelOutput {
+ public:
+  MessageOutput(const internal::NanopbMethod& kMethod, bool server_streaming)
+      : FakeChannelOutput(packet_buffer_, server_streaming), method_(kMethod) {}
+
+  const Vector<Response>& responses() const { return responses_; }
+
+  Response& AllocateResponse() {
+    // If we run out of space, the back message is always the most recent.
+    responses_.emplace_back();
+    responses_.back() = {};
+    return responses_.back();
+  }
+
+ private:
+  void AppendResponse(ConstByteSpan response) override {
+    Response& response_struct = AllocateResponse();
+    PW_ASSERT(method_.serde().DecodeResponse(response, &response_struct));
+  }
+
+  void ClearResponses() override { responses_.clear(); }
+
+  const internal::NanopbMethod& method_;
+  Vector<Response, kMaxResponses> responses_;
+  std::array<std::byte, kOutputSize> packet_buffer_;
+};
+
+// Collects everything needed to invoke a particular RPC.
+template <typename Service,
+          auto kMethod,
+          uint32_t kMethodId,
+          size_t kMaxResponses,
+          size_t kOutputSize>
+struct NanopbInvocationContext : public InvocationContext<Service, kMethodId> {
+ public:
+  using Request = internal::Request<kMethod>;
+  using Response = internal::Response<kMethod>;
+
+  // Returns the responses that have been recorded. The maximum number of
+  // responses is responses().max_size(). responses().back() is always the most
+  // recent response, even if total_responses() > responses().max_size().
+  const Vector<Response>& responses() const { return output_.responses(); }
+
+  // Gives access to the RPC's response.
+  const Response& response() const {
+    PW_ASSERT(!responses().empty());
+    return responses().back();
+  }
+
+ protected:
+  template <typename... Args>
+  NanopbInvocationContext(Args&&... args)
+      : InvocationContext<Service, kMethodId>(
+            MethodLookup::GetNanopbMethod<Service, kMethodId>(),
+            output_,
+            std::forward<Args>(args)...),
+        output_(MethodLookup::GetNanopbMethod<Service, kMethodId>(),
+                MethodTraits<decltype(kMethod)>::kServerStreaming) {}
+
+  MessageOutput<Response, kMaxResponses, kOutputSize>& output() {
+    return output_;
+  }
+
+ private:
+  MessageOutput<Response, kMaxResponses, kOutputSize> output_;
+};
+
+// Method invocation context for a unary RPC. Returns the status in
+// server_call() and provides the response through the response() method.
+template <typename Service,
+          auto kMethod,
+          uint32_t kMethodId,
+          size_t kOutputSize>
+class UnaryContext : public NanopbInvocationContext<Service,
+                                                    kMethod,
+                                                    kMethodId,
+                                                    1,
+                                                    kOutputSize> {
+  using Base =
+      NanopbInvocationContext<Service, kMethod, kMethodId, 1, kOutputSize>;
+
+ public:
+  using Request = typename Base::Request;
+  using Response = typename Base::Response;
+
+  template <typename... Args>
+  UnaryContext(Args&&... args) : Base(std::forward<Args>(args)...) {}
+
+  // Invokes the RPC with the provided request. Returns the status.
+  Status call(const Request& request) {
+    Base::output().clear();
+    Response& response = Base::output().AllocateResponse();
+    return CallMethodImplFunction<kMethod>(
+        Base::server_call(), request, response);
+  }
+};
+
+// Method invocation context for a server streaming RPC.
+template <typename Service,
+          auto kMethod,
+          uint32_t kMethodId,
+          size_t kMaxResponses,
+          size_t kOutputSize>
+class ServerStreamingContext : public NanopbInvocationContext<Service,
+                                                              kMethod,
+                                                              kMethodId,
+                                                              kMaxResponses,
+                                                              kOutputSize> {
+ private:
+  using Base = NanopbInvocationContext<Service,
+                                       kMethod,
+                                       kMethodId,
+                                       kMaxResponses,
+                                       kOutputSize>;
+
+ public:
+  using Request = typename Base::Request;
+  using Response = typename Base::Response;
+
+  template <typename... Args>
+  ServerStreamingContext(Args&&... args) : Base(std::forward<Args>(args)...) {}
+
+  // Invokes the RPC with the provided request.
+  void call(const Request& request) {
+    Base::output().clear();
+    NanopbServerWriter<Response> writer(Base::server_call());
+    return CallMethodImplFunction<kMethod>(
+        Base::server_call(), request, writer);
+  }
+
+  // Returns a server writer which writes responses into the context's buffer.
+  // This should not be called alongside call(); use one or the other.
+  NanopbServerWriter<Response> writer() {
+    Base::output().clear();
+    return NanopbServerWriter<Response>(Base::server_call());
+  }
+};
+
+// Alias to select the type of the context object to use based on which type of
+// RPC it is for.
+template <typename Service,
+          auto kMethod,
+          uint32_t kMethodId,
+          size_t kMaxResponses,
+          size_t kOutputSize>
+using Context = std::tuple_element_t<
+    static_cast<size_t>(internal::MethodTraits<decltype(kMethod)>::kType),
+    std::tuple<UnaryContext<Service, kMethod, kMethodId, kOutputSize>,
+               ServerStreamingContext<Service,
+                                      kMethod,
+                                      kMethodId,
+                                      kMaxResponses,
+                                      kOutputSize>
+               // TODO(hepler): Support client and bidi streaming
+               >>;
+
+}  // namespace internal::test::nanopb
+
+template <typename Service,
+          auto kMethod,
+          uint32_t kMethodId,
+          size_t kMaxResponses,
+          size_t kOutputSizeBytes>
+class NanopbTestMethodContext
+    : public internal::test::nanopb::Context<Service,
+                                             kMethod,
+                                             kMethodId,
+                                             kMaxResponses,
+                                             kOutputSizeBytes> {
+ public:
+  // Forwards constructor arguments to the service class.
+  template <typename... ServiceArgs>
+  NanopbTestMethodContext(ServiceArgs&&... service_args)
+      : internal::test::nanopb::Context<Service,
+                                        kMethod,
+                                        kMethodId,
+                                        kMaxResponses,
+                                        kOutputSizeBytes>(
+            std::forward<ServiceArgs>(service_args)...) {}
+};
+
+}  // namespace pw::rpc
diff --git a/pw_rpc/nanopb/public/pw_rpc/nanopb_test_method_context.h b/pw_rpc/nanopb/public/pw_rpc/nanopb_test_method_context.h
index 0214b6a..0502c1f 100644
--- a/pw_rpc/nanopb/public/pw_rpc/nanopb_test_method_context.h
+++ b/pw_rpc/nanopb/public/pw_rpc/nanopb_test_method_context.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Pigweed Authors
+// Copyright 2021 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
@@ -13,260 +13,7 @@
 // the License.
 #pragma once
 
-#include <tuple>
-#include <utility>
-
-#include "pw_assert/assert.h"
-#include "pw_bytes/span.h"
-#include "pw_containers/vector.h"
-#include "pw_preprocessor/arguments.h"
-#include "pw_rpc/internal/hash.h"
-#include "pw_rpc/internal/method_lookup.h"
-#include "pw_rpc/internal/nanopb_method.h"
-#include "pw_rpc/internal/test_method_context.h"
-#include "pw_rpc_private/fake_channel_output.h"
-
-namespace pw::rpc {
-
-// Declares a context object that may be used to invoke an RPC. The context is
-// declared with the name of the implemented service and the method to invoke.
-// The RPC can then be invoked with the call method.
-//
-// For a unary RPC, context.call(request) returns the status, and the response
-// struct can be accessed via context.response().
-//
-//   PW_NANOPB_TEST_METHOD_CONTEXT(my::CoolService, TheMethod) context;
-//   EXPECT_EQ(OkStatus(), context.call({.some_arg = 123}));
-//   EXPECT_EQ(500, context.response().some_response_value);
-//
-// For a server streaming RPC, context.call(request) invokes the method. As in a
-// normal RPC, the method completes when the ServerWriter's Finish method is
-// called (or it goes out of scope).
-//
-//   PW_NANOPB_TEST_METHOD_CONTEXT(my::CoolService, TheStreamingMethod) context;
-//   context.call({.some_arg = 123});
-//
-//   EXPECT_TRUE(context.done());  // Check that the RPC completed
-//   EXPECT_EQ(OkStatus(), context.status());  // Check the status
-//
-//   EXPECT_EQ(3u, context.responses().size());
-//   EXPECT_EQ(123, context.responses()[0].value); // check individual responses
-//
-//   for (const MyResponse& response : context.responses()) {
-//     // iterate over the responses
-//   }
-//
-// PW_NANOPB_TEST_METHOD_CONTEXT forwards its constructor arguments to the
-// underlying serivce. For example:
-//
-//   PW_NANOPB_TEST_METHOD_CONTEXT(MyService, Go) context(service, args);
-//
-// PW_NANOPB_TEST_METHOD_CONTEXT takes two optional arguments:
-//
-//   size_t kMaxResponses: maximum responses to store; ignored unless streaming
-//   size_t kOutputSizeBytes: buffer size; must be large enough for a packet
-//
-// Example:
-//
-//   PW_NANOPB_TEST_METHOD_CONTEXT(MyService, BestMethod, 3, 256) context;
-//   ASSERT_EQ(3u, context.responses().max_size());
-//
-#define PW_NANOPB_TEST_METHOD_CONTEXT(service, method, ...)              \
-  ::pw::rpc::NanopbTestMethodContext<service,                            \
-                                     &service::method,                   \
-                                     ::pw::rpc::internal::Hash(#method), \
-                                     ##__VA_ARGS__>
-template <typename Service,
-          auto kMethod,
-          uint32_t kMethodId,
-          size_t kMaxResponses = 4,
-          size_t kOutputSizeBytes = 128>
-class NanopbTestMethodContext;
-
-// Internal classes that implement NanopbTestMethodContext.
-namespace internal::test::nanopb {
-
-// A ChannelOutput implementation that stores the outgoing payloads and status.
-template <typename Response, size_t kMaxResponses, size_t kOutputSize>
-class MessageOutput final : public FakeChannelOutput {
- public:
-  MessageOutput(const internal::NanopbMethod& kMethod, bool server_streaming)
-      : FakeChannelOutput(packet_buffer_, server_streaming), method_(kMethod) {}
-
-  const Vector<Response>& responses() const { return responses_; }
-
-  Response& AllocateResponse() {
-    // If we run out of space, the back message is always the most recent.
-    responses_.emplace_back();
-    responses_.back() = {};
-    return responses_.back();
-  }
-
- private:
-  void AppendResponse(ConstByteSpan response) override {
-    Response& response_struct = AllocateResponse();
-    PW_ASSERT(method_.serde().DecodeResponse(response, &response_struct));
-  }
-
-  void ClearResponses() override { responses_.clear(); }
-
-  const internal::NanopbMethod& method_;
-  Vector<Response, kMaxResponses> responses_;
-  std::array<std::byte, kOutputSize> packet_buffer_;
-};
-
-// Collects everything needed to invoke a particular RPC.
-template <typename Service,
-          auto kMethod,
-          uint32_t kMethodId,
-          size_t kMaxResponses,
-          size_t kOutputSize>
-struct NanopbInvocationContext : public InvocationContext<Service, kMethodId> {
- public:
-  using Request = internal::Request<kMethod>;
-  using Response = internal::Response<kMethod>;
-
-  // Returns the responses that have been recorded. The maximum number of
-  // responses is responses().max_size(). responses().back() is always the most
-  // recent response, even if total_responses() > responses().max_size().
-  const Vector<Response>& responses() const { return output_.responses(); }
-
-  // Gives access to the RPC's response.
-  const Response& response() const {
-    PW_ASSERT(!responses().empty());
-    return responses().back();
-  }
-
- protected:
-  template <typename... Args>
-  NanopbInvocationContext(Args&&... args)
-      : InvocationContext<Service, kMethodId>(
-            MethodLookup::GetNanopbMethod<Service, kMethodId>(),
-            output_,
-            std::forward<Args>(args)...),
-        output_(MethodLookup::GetNanopbMethod<Service, kMethodId>(),
-                MethodTraits<decltype(kMethod)>::kServerStreaming) {}
-
-  MessageOutput<Response, kMaxResponses, kOutputSize>& output() {
-    return output_;
-  }
-
- private:
-  MessageOutput<Response, kMaxResponses, kOutputSize> output_;
-};
-
-// Method invocation context for a unary RPC. Returns the status in
-// server_call() and provides the response through the response() method.
-template <typename Service,
-          auto kMethod,
-          uint32_t kMethodId,
-          size_t kOutputSize>
-class UnaryContext : public NanopbInvocationContext<Service,
-                                                    kMethod,
-                                                    kMethodId,
-                                                    1,
-                                                    kOutputSize> {
-  using Base =
-      NanopbInvocationContext<Service, kMethod, kMethodId, 1, kOutputSize>;
-
- public:
-  using Request = typename Base::Request;
-  using Response = typename Base::Response;
-
-  template <typename... Args>
-  UnaryContext(Args&&... args) : Base(std::forward<Args>(args)...) {}
-
-  // Invokes the RPC with the provided request. Returns the status.
-  Status call(const Request& request) {
-    Base::output().clear();
-    Response& response = Base::output().AllocateResponse();
-    return CallMethodImplFunction<kMethod>(
-        Base::server_call(), request, response);
-  }
-};
-
-// Method invocation context for a server streaming RPC.
-template <typename Service,
-          auto kMethod,
-          uint32_t kMethodId,
-          size_t kMaxResponses,
-          size_t kOutputSize>
-class ServerStreamingContext : public NanopbInvocationContext<Service,
-                                                              kMethod,
-                                                              kMethodId,
-                                                              kMaxResponses,
-                                                              kOutputSize> {
- private:
-  using Base = NanopbInvocationContext<Service,
-                                       kMethod,
-                                       kMethodId,
-                                       kMaxResponses,
-                                       kOutputSize>;
-
- public:
-  using Request = typename Base::Request;
-  using Response = typename Base::Response;
-
-  template <typename... Args>
-  ServerStreamingContext(Args&&... args) : Base(std::forward<Args>(args)...) {}
-
-  // Invokes the RPC with the provided request.
-  void call(const Request& request) {
-    Base::output().clear();
-    NanopbServerWriter<Response> writer(Base::server_call());
-    return CallMethodImplFunction<kMethod>(
-        Base::server_call(), request, writer);
-  }
-
-  // Returns a server writer which writes responses into the context's buffer.
-  // This should not be called alongside call(); use one or the other.
-  NanopbServerWriter<Response> writer() {
-    Base::output().clear();
-    return NanopbServerWriter<Response>(Base::server_call());
-  }
-};
-
-// Alias to select the type of the context object to use based on which type of
-// RPC it is for.
-template <typename Service,
-          auto kMethod,
-          uint32_t kMethodId,
-          size_t kMaxResponses,
-          size_t kOutputSize>
-using Context = std::tuple_element_t<
-    static_cast<size_t>(internal::MethodTraits<decltype(kMethod)>::kType),
-    std::tuple<UnaryContext<Service, kMethod, kMethodId, kOutputSize>,
-               ServerStreamingContext<Service,
-                                      kMethod,
-                                      kMethodId,
-                                      kMaxResponses,
-                                      kOutputSize>
-               // TODO(hepler): Support client and bidi streaming
-               >>;
-
-}  // namespace internal::test::nanopb
-
-template <typename Service,
-          auto kMethod,
-          uint32_t kMethodId,
-          size_t kMaxResponses,
-          size_t kOutputSizeBytes>
-class NanopbTestMethodContext
-    : public internal::test::nanopb::Context<Service,
-                                             kMethod,
-                                             kMethodId,
-                                             kMaxResponses,
-                                             kOutputSizeBytes> {
- public:
-  // Forwards constructor arguments to the service class.
-  template <typename... ServiceArgs>
-  NanopbTestMethodContext(ServiceArgs&&... service_args)
-      : internal::test::nanopb::Context<Service,
-                                        kMethod,
-                                        kMethodId,
-                                        kMaxResponses,
-                                        kOutputSizeBytes>(
-            std::forward<ServiceArgs>(service_args)...) {}
-};
-
-}  // namespace pw::rpc
+// pw_rpc/nanopb/test_method_context.h is now
+// pw_rpc/nanopb/test_method_context.h.
+// TODO(hepler): Remove this wrapper when users have migrated.
+#include "pw_rpc/nanopb/test_method_context.h"
diff --git a/pw_rpc/nanopb/server_reader_writer.cc b/pw_rpc/nanopb/server_reader_writer.cc
index f43063d..58efbc8 100644
--- a/pw_rpc/nanopb/server_reader_writer.cc
+++ b/pw_rpc/nanopb/server_reader_writer.cc
@@ -14,7 +14,7 @@
 
 #include "pw_rpc/nanopb/server_reader_writer.h"
 
-#include "pw_rpc/internal/nanopb_method.h"
+#include "pw_rpc/nanopb/internal/method.h"
 
 namespace pw::rpc::internal {
 
diff --git a/pw_rpc/py/pw_rpc/codegen_nanopb.py b/pw_rpc/py/pw_rpc/codegen_nanopb.py
index cf7dc73..7630293 100644
--- a/pw_rpc/py/pw_rpc/codegen_nanopb.py
+++ b/pw_rpc/py/pw_rpc/codegen_nanopb.py
@@ -200,8 +200,8 @@
 
 
 def includes(proto_file, unused_package: ProtoNode) -> Iterator[str]:
-    yield '#include "pw_rpc/internal/nanopb_method_union.h"'
-    yield '#include "pw_rpc/nanopb_client_call.h"'
+    yield '#include "pw_rpc/nanopb/internal/method_union.h"'
+    yield '#include "pw_rpc/nanopb/client_call.h"'
 
     # Include the corresponding nanopb header file for this proto file, in which
     # the file's messages and enums are generated. All other files imported from