From 7487aa4779193f55d4b377f80574a16b57287eeb Mon Sep 17 00:00:00 2001
From: "hinto.janai" <hinto.janai@protonmail.com>
Date: Mon, 2 Sep 2024 20:34:02 -0400
Subject: [PATCH] interface: extract out to `RpcService`

---
 binaries/cuprated/src/rpc/bin.rs       |  2 +-
 binaries/cuprated/src/rpc/handler.rs   |  2 +-
 binaries/cuprated/src/rpc/json.rs      |  2 +-
 binaries/cuprated/src/rpc/other.rs     |  2 +-
 rpc/interface/README.md                | 18 +++++----
 rpc/interface/src/lib.rs               | 10 +++--
 rpc/interface/src/route/bin.rs         |  2 +-
 rpc/interface/src/route/json_rpc.rs    |  2 +-
 rpc/interface/src/route/other.rs       |  2 +-
 rpc/interface/src/rpc_handler.rs       | 56 +++++++++-----------------
 rpc/interface/src/rpc_handler_dummy.rs |  5 +--
 rpc/interface/src/rpc_service.rs       | 49 ++++++++++++++++++++++
 12 files changed, 92 insertions(+), 60 deletions(-)
 create mode 100644 rpc/interface/src/rpc_service.rs

diff --git a/binaries/cuprated/src/rpc/bin.rs b/binaries/cuprated/src/rpc/bin.rs
index a03808d7..6a3a781f 100644
--- a/binaries/cuprated/src/rpc/bin.rs
+++ b/binaries/cuprated/src/rpc/bin.rs
@@ -1,4 +1,4 @@
-use cuprate_rpc_interface::{RpcError, RpcResponse};
+use cuprate_rpc_interface::RpcError;
 use cuprate_rpc_types::{
     bin::{
         BinRequest, BinResponse, GetBlocksByHeightRequest, GetBlocksByHeightResponse,
diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs
index 2e15a5df..b475f29a 100644
--- a/binaries/cuprated/src/rpc/handler.rs
+++ b/binaries/cuprated/src/rpc/handler.rs
@@ -15,7 +15,7 @@ use tower::Service;
 use cuprate_blockchain::service::BlockchainReadHandle;
 use cuprate_helper::asynch::InfallibleOneshotReceiver;
 use cuprate_json_rpc::Id;
-use cuprate_rpc_interface::{RpcError, RpcHandler, RpcRequest, RpcResponse};
+use cuprate_rpc_interface::{RpcError, RpcHandler};
 use cuprate_txpool::service::TxpoolReadHandle;
 
 use crate::rpc::{bin, json, other};
diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs
index 70a9e497..34c95342 100644
--- a/binaries/cuprated/src/rpc/json.rs
+++ b/binaries/cuprated/src/rpc/json.rs
@@ -1,6 +1,6 @@
 use std::sync::Arc;
 
-use cuprate_rpc_interface::{RpcError, RpcResponse};
+use cuprate_rpc_interface::RpcError;
 use cuprate_rpc_types::json::{
     AddAuxPowRequest, AddAuxPowResponse, BannedRequest, BannedResponse, CalcPowRequest,
     CalcPowResponse, FlushCacheRequest, FlushCacheResponse, FlushTransactionPoolRequest,
diff --git a/binaries/cuprated/src/rpc/other.rs b/binaries/cuprated/src/rpc/other.rs
index 6a84c650..49d8415a 100644
--- a/binaries/cuprated/src/rpc/other.rs
+++ b/binaries/cuprated/src/rpc/other.rs
@@ -1,4 +1,4 @@
-use cuprate_rpc_interface::{RpcError, RpcResponse};
+use cuprate_rpc_interface::RpcError;
 use cuprate_rpc_types::other::{
     GetAltBlocksHashesRequest, GetAltBlocksHashesResponse, GetHeightRequest, GetHeightResponse,
     GetLimitRequest, GetLimitResponse, GetNetStatsRequest, GetNetStatsResponse, GetOutsRequest,
diff --git a/rpc/interface/README.md b/rpc/interface/README.md
index 3a63ac46..2d3faa75 100644
--- a/rpc/interface/README.md
+++ b/rpc/interface/README.md
@@ -17,7 +17,7 @@ CLIENT ─► ROUTE ─► REQUEST ─► HANDLER ─► RESPONSE ─► CLIENT
 
 Everything coming _in_ from a client is handled by this crate.
 
-This is where your [`RpcHandler`] turns this [`RpcRequest`] into a [`RpcResponse`].
+This is where your [`RpcHandler`] turns this `Request` into a `Response`.
 
 You hand this `Response` back to `cuprate-rpc-interface` and it will take care of sending it back to the client.
 
@@ -33,7 +33,7 @@ This crate simply handles:
 - Defining handler function signatures
 - (De)serialization of requests/responses (JSON-RPC, binary, JSON)
 
-The actual server details are all handled by the [`axum`] and [`tower`] ecosystem.
+The actual server details are all handled by the [`axum`] and [`tower`] ecosystem.a
 
 The proper usage of this crate is to:
 1. Implement a [`RpcHandler`]
@@ -42,16 +42,18 @@ The proper usage of this crate is to:
 3. Do whatever with it
 
 # The [`RpcHandler`]
-This is your [`tower::Service`] that converts [`RpcRequest`]s into [`RpcResponse`]s,
+This is your [`tower::Service`] that converts `Request`s into `Response`s,
 i.e. the "inner handler".
 
-Said concretely, `RpcHandler` is a `tower::Service` where the associated types are from this crate:
-- [`RpcRequest`]
-- [`RpcResponse`]
+Said concretely, `RpcHandler` is 3 `tower::Service`s where the associated types are
+the 3 endpoint enums from [`cuprate_rpc_types`] and the error type from this crate:
+- [`JsonRpcRequest`](cuprate_rpc_types::json::JsonRpcRequest) & [`JsonRpcResponse`](cuprate_rpc_types::json::JsonRpcResponse)
+- [`BinRequest`](cuprate_rpc_types::bin::BinRequest) & [`BinResponse`](cuprate_rpc_types::bin::BinRequest)
+- [`OtherRequest`](cuprate_rpc_types::other::OtherRequest) & [`OtherResponse`](cuprate_rpc_types::other::OtherRequest)
 - [`RpcError`]
 
 `RpcHandler`'s [`Future`](std::future::Future) is generic, _although_,
-it must output `Result<RpcResponse, RpcError>`.
+it must output `Result<$RESPONSE, RpcError>`.
 
 The `RpcHandler` must also hold some state that is required
 for RPC server operation.
@@ -83,7 +85,7 @@ use cuprate_rpc_types::{
     json::{JsonRpcRequest, JsonRpcResponse, GetBlockCountResponse},
     other::{OtherRequest, OtherResponse},
 };
-use cuprate_rpc_interface::{RouterBuilder, RpcHandlerDummy, RpcRequest};
+use cuprate_rpc_interface::{RouterBuilder, RpcHandlerDummy, Request};
 
 // Send a `/get_height` request. This endpoint has no inputs.
 async fn get_height(port: u16) -> OtherResponse {
diff --git a/rpc/interface/src/lib.rs b/rpc/interface/src/lib.rs
index d4376979..f3e2988e 100644
--- a/rpc/interface/src/lib.rs
+++ b/rpc/interface/src/lib.rs
@@ -7,16 +7,18 @@ mod rpc_error;
 mod rpc_handler;
 #[cfg(feature = "dummy")]
 mod rpc_handler_dummy;
-mod rpc_request;
-mod rpc_response;
+// mod rpc_request;
+// mod rpc_response;
+mod rpc_service;
 
 pub use router_builder::RouterBuilder;
 pub use rpc_error::RpcError;
 pub use rpc_handler::RpcHandler;
 #[cfg(feature = "dummy")]
 pub use rpc_handler_dummy::RpcHandlerDummy;
-pub use rpc_request::RpcRequest;
-pub use rpc_response::RpcResponse;
+// pub use rpc_request::RpcRequest;
+// pub use rpc_response::RpcResponse;
+pub use rpc_service::RpcService;
 
 // false-positive: used in `README.md`'s doc-test.
 #[cfg(test)]
diff --git a/rpc/interface/src/route/bin.rs b/rpc/interface/src/route/bin.rs
index c636d9c0..45447caf 100644
--- a/rpc/interface/src/route/bin.rs
+++ b/rpc/interface/src/route/bin.rs
@@ -7,7 +7,7 @@ use tower::ServiceExt;
 use cuprate_epee_encoding::from_bytes;
 use cuprate_rpc_types::bin::{BinRequest, BinResponse, GetTransactionPoolHashesRequest};
 
-use crate::{rpc_handler::RpcHandler, rpc_request::RpcRequest, rpc_response::RpcResponse};
+use crate::rpc_handler::RpcHandler;
 
 //---------------------------------------------------------------------------------------------------- Routes
 /// This macro generates route functions that expect input.
diff --git a/rpc/interface/src/route/json_rpc.rs b/rpc/interface/src/route/json_rpc.rs
index db7749ec..bf3d937d 100644
--- a/rpc/interface/src/route/json_rpc.rs
+++ b/rpc/interface/src/route/json_rpc.rs
@@ -15,7 +15,7 @@ use cuprate_rpc_types::{
     RpcCallValue,
 };
 
-use crate::{rpc_handler::RpcHandler, rpc_request::RpcRequest, rpc_response::RpcResponse};
+use crate::rpc_handler::RpcHandler;
 
 //---------------------------------------------------------------------------------------------------- Routes
 /// The `/json_rpc` route function used in [`crate::RouterBuilder`].
diff --git a/rpc/interface/src/route/other.rs b/rpc/interface/src/route/other.rs
index 26413820..129ddd59 100644
--- a/rpc/interface/src/route/other.rs
+++ b/rpc/interface/src/route/other.rs
@@ -25,7 +25,7 @@ use cuprate_rpc_types::{
     RpcCall,
 };
 
-use crate::{rpc_handler::RpcHandler, rpc_request::RpcRequest, rpc_response::RpcResponse};
+use crate::rpc_handler::RpcHandler;
 
 //---------------------------------------------------------------------------------------------------- Routes
 /// This macro generates route functions that expect input.
diff --git a/rpc/interface/src/rpc_handler.rs b/rpc/interface/src/rpc_handler.rs
index b956586a..f4c9fb56 100644
--- a/rpc/interface/src/rpc_handler.rs
+++ b/rpc/interface/src/rpc_handler.rs
@@ -1,60 +1,42 @@
 //! RPC handler trait.
 
 //---------------------------------------------------------------------------------------------------- Use
-use std::future::Future;
-
 use cuprate_rpc_types::{
     bin::{BinRequest, BinResponse},
     json::{JsonRpcRequest, JsonRpcResponse},
     other::{OtherRequest, OtherResponse},
 };
-use tower::Service;
 
-use crate::{rpc_error::RpcError, rpc_request::RpcRequest, rpc_response::RpcResponse};
+use crate::RpcService;
 
 //---------------------------------------------------------------------------------------------------- RpcHandler
 /// An RPC handler.
 ///
-/// This trait represents a type that can turn [`RpcRequest`]s into [`RpcResponse`]s.
+/// This trait represents a type that can turn `Request`s into `Response`s.
 ///
-/// Implementors of this trait must be [`tower::Service`]s that use:
-/// - [`RpcRequest`] as the generic `Request` type
-/// - [`RpcResponse`] as the associated `Response` type
-/// - [`RpcError`] as the associated `Error` type
-/// - A generic [`Future`] that outputs `Result<RpcResponse, RpcError>`
+/// Implementors of this trait must be:
+/// - A [`tower::Service`]s that use [`JsonRpcRequest`] & [`JsonRpcResponse`]
+/// - A [`tower::Service`]s that use [`BinRequest`] & [`BinResponse`]
+/// - A [`tower::Service`]s that use [`OtherRequest`] & [`OtherResponse`]
+///
+/// In other words, an [`RpcHandler`] is a type that implements [`tower::Service`] 3 times,
+/// one for each endpoint enum type found in [`cuprate_rpc_types`].
+///
+/// The error type must always be [`RpcError`](crate::RpcError).
 ///
 /// See this crate's `RpcHandlerDummy` for an implementation example of this trait.
 ///
 /// # Panics
-/// Your [`RpcHandler`] must reply to [`RpcRequest`]s with the correct
-/// [`RpcResponse`] or else this crate will panic during routing functions.
+/// Your [`RpcHandler`] must reply to `Request`s with the correct
+/// `Response` or else this crate will panic during routing functions.
 ///
-/// For example, upon a [`RpcRequest::Binary`] must be replied with
-/// [`RpcRequest::Binary`]. If an [`RpcRequest::Other`] were returned instead,
-/// this crate would panic.
+/// For example, upon a [`JsonRpcRequest::GetBlockCount`] must be replied with
+/// [`JsonRpcResponse::GetBlockCount`]. If anything else is returned,
+/// this crate may panic.
 pub trait RpcHandler:
-    Clone
-    + Send
-    + Sync
-    + 'static
-    + Service<
-        JsonRpcRequest,
-        Response = JsonRpcResponse,
-        Error = RpcError,
-        Future: Future<Output = Result<JsonRpcResponse, RpcError>> + Send + Sync + 'static,
-    >
-    + Service<
-        OtherRequest,
-        Response = OtherResponse,
-        Error = RpcError,
-        Future: Future<Output = Result<OtherResponse, RpcError>> + Send + Sync + 'static,
-    >
-    + Service<
-        BinRequest,
-        Response = BinResponse,
-        Error = RpcError,
-        Future: Future<Output = Result<BinResponse, RpcError>> + Send + Sync + 'static,
-    >
+    RpcService<JsonRpcRequest, JsonRpcResponse>
+    + RpcService<BinRequest, BinResponse>
+    + RpcService<OtherRequest, OtherResponse>
 {
     /// Is this [`RpcHandler`] restricted?
     ///
diff --git a/rpc/interface/src/rpc_handler_dummy.rs b/rpc/interface/src/rpc_handler_dummy.rs
index b01106ba..06fa4608 100644
--- a/rpc/interface/src/rpc_handler_dummy.rs
+++ b/rpc/interface/src/rpc_handler_dummy.rs
@@ -15,10 +15,7 @@ use tower::Service;
 
 use cuprate_helper::asynch::InfallibleOneshotReceiver;
 
-use crate::{
-    rpc_error::RpcError, rpc_handler::RpcHandler, rpc_request::RpcRequest,
-    rpc_response::RpcResponse,
-};
+use crate::{rpc_error::RpcError, rpc_handler::RpcHandler};
 
 //---------------------------------------------------------------------------------------------------- RpcHandlerDummy
 /// An [`RpcHandler`] that always returns [`Default::default`].
diff --git a/rpc/interface/src/rpc_service.rs b/rpc/interface/src/rpc_service.rs
new file mode 100644
index 00000000..cd250035
--- /dev/null
+++ b/rpc/interface/src/rpc_service.rs
@@ -0,0 +1,49 @@
+//! RPC [`tower::Service`] trait.
+
+//---------------------------------------------------------------------------------------------------- Use
+use std::future::Future;
+
+use tower::Service;
+
+use crate::rpc_error::RpcError;
+
+//---------------------------------------------------------------------------------------------------- RpcService
+/// An RPC [`tower::Service`].
+///
+/// This trait solely exists to encapsulate the traits needed
+/// to handle RPC requests and respond with responses - **it is
+/// not meant to be used directly.**
+///
+/// The `Request` and `Response` are generic and
+/// are used in the [`tower::Service`] bounds.
+///
+/// The error type is always [`RpcError`].
+///
+/// See [`RpcHandler`](crate::RpcHandler) for more information.
+pub trait RpcService<Request, Response>:
+    Clone
+    + Send
+    + Sync
+    + 'static
+    + Service<
+        Request,
+        Response = Response,
+        Error = RpcError,
+        Future: Future<Output = Result<Response, RpcError>> + Send + Sync + 'static,
+    >
+{
+}
+
+impl<Request, Response, T> RpcService<Request, Response> for T where
+    Self: Clone
+        + Send
+        + Sync
+        + 'static
+        + Service<
+            Request,
+            Response = Response,
+            Error = RpcError,
+            Future: Future<Output = Result<Response, RpcError>> + Send + Sync + 'static,
+        >
+{
+}