From 2d54d2a19a0ce59acb17cdb53f16086d5ec638d0 Mon Sep 17 00:00:00 2001
From: "hinto.janai" <hinto.janai@protonmail.com>
Date: Tue, 2 Jul 2024 21:21:33 -0400
Subject: [PATCH] macros: split type generator macro up

---
 rpc/types/src/macros.rs | 260 +++++++++++++++++++++-------------------
 1 file changed, 135 insertions(+), 125 deletions(-)

diff --git a/rpc/types/src/macros.rs b/rpc/types/src/macros.rs
index 1c598a36..80054db7 100644
--- a/rpc/types/src/macros.rs
+++ b/rpc/types/src/macros.rs
@@ -1,14 +1,12 @@
 //! Macros.
 
-//---------------------------------------------------------------------------------------------------- Struct definition
-/// A template for generating 2 `struct`s with a bunch of information filled out.
-///
-/// These are the RPC request and response `struct`s.
+//---------------------------------------------------------------------------------------------------- define_request_and_response
+/// A template for generating the RPC request and response `struct`s.
 ///
 /// These `struct`s automatically implement:
 /// - `Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash`
 /// - `serde::{Serialize, Deserialize}`
-/// - `epee_encoding::EpeeObject`
+/// - `cuprate_epee_encoding::EpeeObject`
 ///
 /// It's best to see the output of this macro via the documentation
 /// of the generated structs via `cargo doc`s to see which parts
@@ -22,8 +20,8 @@
 /// 2. An `Request` type with fields
 ///
 /// The first branch is the same as the second with the exception
-/// that if the caller of this macro provides no fields, it will
-/// generate:
+/// that if the caller of this macro provides no `Request` type,
+/// it will generate:
 /// ```
 /// pub type Request = ();
 /// ```
@@ -44,84 +42,6 @@
 /// branch as well when making changes. The only de-duplicated part is
 /// the doc generation with [`define_request_and_response_doc`].
 macro_rules! define_request_and_response {
-    //------------------------------------------------------------------------------
-    // This version of the macro expects a `Request` type with no fields, i.e. `Request {}`.
-    (
-        // The markdown tag for Monero RPC documentation. Not necessarily the endpoint.
-        $monero_daemon_rpc_doc_link:ident,
-
-        // The commit hash and  `$file.$extension` in which this type is defined in
-        // the Monero codebase in the `rpc/` directory, followed by the specific lines.
-        $monero_code_commit:ident =>
-        $monero_code_filename:ident.
-        $monero_code_filename_extension:ident =>
-        $monero_code_line_start:literal..=
-        $monero_code_line_end:literal,
-
-        // The base `struct` name.
-        $type_name:ident,
-
-        // The response type (and any doc comments, derives, etc).
-        $( #[$response_type_attr:meta] )*
-        $response_base_type:ty {
-            // And any fields.
-            $(
-                $( #[$response_field_attr:meta] )*
-                $response_field:ident: $response_field_type:ty,
-            )*
-        }
-    ) => { paste::paste! {
-        #[doc = $crate::macros::define_request_and_response_doc!(
-            "response",
-            $monero_daemon_rpc_doc_link,
-            $monero_code_commit,
-            $monero_code_filename,
-            $monero_code_filename_extension,
-            $monero_code_line_start,
-            $monero_code_line_end,
-            [<$type_name Request>],
-        )]
-        ///
-        /// This request has no inputs.
-        pub type [<$type_name Request>] = ();
-
-        #[allow(dead_code)]
-        #[allow(missing_docs)]
-        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-        #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
-        $( #[$response_type_attr] )*
-        #[doc = $crate::macros::define_request_and_response_doc!(
-            "request",
-            $monero_daemon_rpc_doc_link,
-            $monero_code_commit,
-            $monero_code_filename,
-            $monero_code_filename_extension,
-            $monero_code_line_start,
-            $monero_code_line_end,
-            [<$type_name Response>],
-        )]
-        pub struct [<$type_name Response>] {
-            #[cfg_attr(feature = "serde", serde(flatten))]
-            pub base: $response_base_type,
-
-            $(
-                $( #[$response_field_attr] )*
-                pub $response_field: $response_field_type,
-            )*
-        }
-
-        #[cfg(feature = "epee")]
-        ::cuprate_epee_encoding::epee_object! {
-            [<$type_name Response>],
-            $(
-                $response_field: $response_field_type,
-            )*
-            !flatten: base: $response_base_type,
-        }
-    }};
-
-    //------------------------------------------------------------------------------
-    // This version of the macro expects a `Request` type with fields.
     (
         // The markdown tag for Monero RPC documentation. Not necessarily the endpoint.
         $monero_daemon_rpc_doc_link:ident,
@@ -139,7 +59,7 @@ macro_rules! define_request_and_response {
 
         // The request type (and any doc comments, derives, etc).
         $( #[$request_type_attr:meta] )*
-        $request_base_type:ty {
+        Request {
             // And any fields.
             $(
                 $( #[$request_field_attr:meta] )*
@@ -157,25 +77,83 @@ macro_rules! define_request_and_response {
             )*
         }
     ) => { paste::paste! {
-        #[allow(dead_code)]
-        #[allow(missing_docs)]
+        $crate::macros::define_request! {
+            #[doc = $crate::macros::define_request_and_response_doc!(
+                "response" => [<$type_name Response>],
+                $monero_daemon_rpc_doc_link,
+                $monero_code_commit,
+                $monero_code_filename,
+                $monero_code_filename_extension,
+                $monero_code_line_start,
+                $monero_code_line_end,
+            )]
+            $( #[$request_type_attr] )*
+            [<$type_name Request>] {
+                $(
+                    $( #[$request_field_attr] )*
+                    $request_field: $request_field_type,
+                )*
+            }
+        }
+
+        $crate::macros::define_response! {
+            #[allow(dead_code)]
+            #[allow(missing_docs)]
+            #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+            #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+            #[doc = $crate::macros::define_request_and_response_doc!(
+                "request" => [<$type_name Request>],
+                $monero_daemon_rpc_doc_link,
+                $monero_code_commit,
+                $monero_code_filename,
+                $monero_code_filename_extension,
+                $monero_code_line_start,
+                $monero_code_line_end,
+            )]
+            $( #[$response_type_attr] )*
+            $response_base_type => [<$type_name Response>] {
+                $(
+                    $( #[$response_field_attr] )*
+                    $response_field: $response_field_type,
+                )*
+            }
+        }
+    }};
+}
+pub(crate) use define_request_and_response;
+
+//---------------------------------------------------------------------------------------------------- define_request
+/// TODO
+macro_rules! define_request {
+    (
+        // The response type (and any doc comments, derives, etc).
+        $( #[$request_type_attr:meta] )*
+        $request_type_name:ident {}
+    ) => {
+        $( #[$request_type_attr] )*
+        ///
+        /// This request has no inputs.
+        pub type $request_type_name = ();
+    };
+
+    //------------------------------------------------------------------------------
+    // This version of the macro expects a `Request` base type.
+    (
+        // The response type (and any doc comments, derives, etc).
+        $( #[$request_type_attr:meta] )*
+        $request_type_name:ident {
+            // And any fields.
+            $(
+                $( #[$request_field_attr:meta] )*
+                $request_field:ident: $request_field_type:ty,
+            )*
+        }
+    ) => {
+        #[allow(dead_code, missing_docs)]
         #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
         #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
         $( #[$request_type_attr] )*
-        #[doc = $crate::macros::define_request_and_response_doc!(
-            "response",
-            $monero_daemon_rpc_doc_link,
-            $monero_code_commit,
-            $monero_code_filename,
-            $monero_code_filename_extension,
-            $monero_code_line_start,
-            $monero_code_line_end,
-            [<$type_name Request>],
-        )]
-        pub struct [<$type_name Request>] {
-            #[cfg_attr(feature = "serde", serde(flatten))]
-            pub base: $request_base_type,
-
+        pub struct $request_type_name {
             $(
                 $( #[$request_field_attr] )*
                 pub $request_field: $request_field_type,
@@ -184,29 +162,61 @@ macro_rules! define_request_and_response {
 
         #[cfg(feature = "epee")]
         ::cuprate_epee_encoding::epee_object! {
-            [<$type_name Request>],
+            $request_type_name,
             $(
                 $request_field: $request_field_type,
             )*
-            !flatten: base: $request_base_type,
+        }
+    };
+}
+pub(crate) use define_request;
+
+//---------------------------------------------------------------------------------------------------- define_response
+/// TODO
+macro_rules! define_response {
+    (
+        // The response type (and any doc comments, derives, etc).
+        $( #[$response_type_attr:meta] )*
+        Response => $response_type_name:ident {
+            // And any fields.
+            $(
+                $( #[$response_field_attr:meta] )*
+                $response_field:ident: $response_field_type:ty,
+            )*
+        }
+    ) => {
+        $( #[$response_type_attr] )*
+        pub struct $response_type_name {
+            $(
+                $( #[$response_field_attr] )*
+                pub $response_field: $response_field_type,
+            )*
         }
 
-        #[allow(dead_code)]
-        #[allow(missing_docs)]
-        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-        #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+        #[cfg(feature = "epee")]
+        ::cuprate_epee_encoding::epee_object! {
+            $response_type_name,
+            $(
+                $response_field: $response_field_type,
+            )*
+        }
+    };
+
+    //------------------------------------------------------------------------------
+    // This version of the macro expects a `Request` base type.
+    (
+        // The response type (and any doc comments, derives, etc).
+        $( #[$response_type_attr:meta] )*
+        $response_base_type:ty => $response_type_name:ident {
+            // And any fields.
+            $(
+                $( #[$response_field_attr:meta] )*
+                $response_field:ident: $response_field_type:ty,
+            )*
+        }
+    ) => {
         $( #[$response_type_attr] )*
-        #[doc = $crate::macros::define_request_and_response_doc!(
-            "request",
-            $monero_daemon_rpc_doc_link,
-            $monero_code_commit,
-            $monero_code_filename,
-            $monero_code_filename_extension,
-            $monero_code_line_start,
-            $monero_code_line_end,
-            [<$type_name Response>],
-        )]
-        pub struct [<$type_name Response>] {
+        pub struct $response_type_name {
             #[cfg_attr(feature = "serde", serde(flatten))]
             pub base: $response_base_type,
 
@@ -218,16 +228,17 @@ macro_rules! define_request_and_response {
 
         #[cfg(feature = "epee")]
         ::cuprate_epee_encoding::epee_object! {
-            [<$type_name Response>],
+            $response_type_name,
             $(
                 $response_field: $response_field_type,
             )*
             !flatten: base: $response_base_type,
         }
-    }};
+    };
 }
-pub(crate) use define_request_and_response;
+pub(crate) use define_response;
 
+//---------------------------------------------------------------------------------------------------- define_request_and_response_doc
 /// Generate documentation for the types generated
 /// by the [`define_request_and_response`] macro.
 ///
@@ -242,7 +253,7 @@ macro_rules! define_request_and_response_doc {
         // Remember this is linking to the _other_ type,
         // so if defining a `Request` type, input should
         // be "response".
-        $request_or_response:literal,
+        $request_or_response:literal => $request_or_response_type:ident,
 
         $monero_daemon_rpc_doc_link:ident,
         $monero_code_commit:ident,
@@ -250,7 +261,6 @@ macro_rules! define_request_and_response_doc {
         $monero_code_filename_extension:ident,
         $monero_code_line_start:literal,
         $monero_code_line_end:literal,
-        $type_name:ident,
     ) => {
         concat!(
             "",
@@ -272,7 +282,7 @@ macro_rules! define_request_and_response_doc {
             "), [",
             $request_or_response,
             "](",
-            stringify!($type_name),
+            stringify!($request_or_response_type),
             ")."
         )
     };