mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-11-16 15:58:14 +00:00
traits
This commit is contained in:
parent
ea8f2e681c
commit
73c11a4cdf
15 changed files with 335 additions and 855 deletions
113
Cargo.lock
generated
113
Cargo.lock
generated
|
@ -106,6 +106,61 @@ version = "1.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
"itoa",
|
||||
"matchit",
|
||||
"memchr",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper 1.0.1",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-core"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"sync_wrapper 0.1.2",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.73"
|
||||
|
@ -758,8 +813,12 @@ dependencies = [
|
|||
name = "cuprate-rpc-interface"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"cuprate-epee-encoding",
|
||||
"cuprate-json-rpc",
|
||||
"cuprate-rpc-types",
|
||||
"serde",
|
||||
"tower",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1309,6 +1368,12 @@ version = "1.9.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.3.1"
|
||||
|
@ -1321,6 +1386,7 @@ dependencies = [
|
|||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"smallvec",
|
||||
|
@ -1630,6 +1696,12 @@ version = "0.4.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
|
||||
|
||||
[[package]]
|
||||
name = "md-5"
|
||||
version = "0.10.6"
|
||||
|
@ -1658,6 +1730,12 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.3"
|
||||
|
@ -2371,6 +2449,28 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_path_to_error"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
|
@ -2506,6 +2606,18 @@ dependencies = [
|
|||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sync_wrapper"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||
|
||||
[[package]]
|
||||
name = "sync_wrapper"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
|
||||
|
||||
[[package]]
|
||||
name = "synchronoise"
|
||||
version = "1.0.1"
|
||||
|
@ -2733,6 +2845,7 @@ version = "0.1.40"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
|
|
|
@ -13,7 +13,11 @@ default = []
|
|||
|
||||
[dependencies]
|
||||
cuprate-epee-encoding = { path = "../../net/epee-encoding" }
|
||||
cuprate-json-rpc = { path = "../json-rpc" }
|
||||
cuprate-rpc-types = { path = "../types" }
|
||||
|
||||
axum = { version = "0.7.5" }
|
||||
serde = { workspace = true }
|
||||
tower = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -1,89 +1,11 @@
|
|||
Monero RPC types.
|
||||
|
||||
# What
|
||||
This crate ports the types used in Monero's RPC interface, including:
|
||||
- JSON types
|
||||
- Binary (epee) types
|
||||
- Mixed types
|
||||
- Other commonly used RPC types
|
||||
|
||||
# Modules
|
||||
This crate's types are split in the following manner:
|
||||
|
||||
| Module | Purpose |
|
||||
|--------|---------|
|
||||
| The root module | Miscellaneous items, e.g. constants.
|
||||
| [`json`] | Contains JSON request/response (some mixed with binary) that all share the common `/json_rpc` endpoint. |
|
||||
| [`bin`] | Contains request/response types that are expected to be fully in binary (`cuprate_epee_encoding`) in `monerod` and `cuprated`'s RPC interface. These are called at a custom endpoint instead of `/json_rpc`, e.g. `/get_blocks.bin`. |
|
||||
| [`other`] | Contains request/response types that are JSON, but aren't called at `/json_rpc` (e.g. [`crate::other::GetHeightRequest`]). |
|
||||
| [`misc`] | Contains miscellaneous types, e.g. [`crate::misc::Status`]. Many of types here are found and used in request/response types, for example, [`crate::misc::BlockHeader`] is used in [`crate::json::GetLastBlockHeaderResponse`]. |
|
||||
| [`base`] | Contains base types flattened into many request/response types.
|
||||
|
||||
Each type in `{json,bin,other}` come in pairs and have identical names, but are suffixed with either `Request` or `Response`. e.g. [`GetBlockCountRequest`](crate::json::GetBlockCountRequest) & [`GetBlockCountResponse`](crate::json::GetBlockCountResponse).
|
||||
|
||||
# Documentation
|
||||
The documentation for types within `{json,bin,other}` are omitted, as they can be found in [Monero's RPC documentation](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html).
|
||||
|
||||
However, each type will document:
|
||||
- **Definition**: the exact type definition location in `monerod`
|
||||
- **Documentation**: the Monero RPC documentation link
|
||||
- **Request/response**: the other side of this type, either the request or response
|
||||
|
||||
# Naming
|
||||
The naming for types within `{json,bin,other}` follow the following scheme:
|
||||
1. Convert the endpoint or method name into `UpperCamelCase`
|
||||
1. Remove any suffix extension
|
||||
1. Add `Request/Response` suffix
|
||||
|
||||
For example:
|
||||
|
||||
| Endpoint/method | Crate location and name |
|
||||
|-----------------|-------------------------|
|
||||
| [`get_block_count`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_block_count) | [`json::GetBlockCountRequest`] & [`json::GetBlockCountResponse`]
|
||||
| [`/get_blocks.bin`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_blockbin) | [`bin::GetBlocksRequest`] & [`bin::GetBlocksResponse`]
|
||||
| [`/get_height`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_height) | [`other::GetHeightRequest`] & [`other::GetHeightResponse`]
|
||||
|
||||
# Mixed types
|
||||
Note that some types mix JSON & binary together, i.e., the message overall is JSON,
|
||||
however some fields contain binary values inside JSON strings, for example:
|
||||
|
||||
```json
|
||||
{
|
||||
"string": "",
|
||||
"float": 30.0,
|
||||
"integer": 30,
|
||||
"binary": "<serialized binary>"
|
||||
}
|
||||
```
|
||||
|
||||
`binary` here is (de)serialized as a normal [`String`]. In order to be clear on which fields contain binary data, the struct fields that have them will use [`crate::misc::BinaryString`] instead of [`String`].
|
||||
|
||||
These mixed types are:
|
||||
- [`crate::json::GetTransactionPoolBacklogResponse`]
|
||||
- [`crate::json::GetOutputDistributionResponse`]
|
||||
|
||||
TODO: we need to figure out a type that (de)serializes correctly, `String` errors with `serde_json`
|
||||
|
||||
# Fixed byte containers
|
||||
TODO
|
||||
|
||||
<!--
|
||||
|
||||
Some fields within requests/responses are containers, but fixed in size.
|
||||
|
||||
For example, [`crate::json::GetBlockTemplateResponse::prev_hash`] is always a 32-byte hash.
|
||||
|
||||
In these cases, stack allocated types like `cuprate_fixed_bytes::StrArray`
|
||||
will be used instead of a more typical [`String`] for optimization reasons.
|
||||
|
||||
-->
|
||||
# What
|
||||
|
||||
# Feature flags
|
||||
List of feature flags for `cuprate-rpc-types`.
|
||||
List of feature flags for `cuprate-rpc-interface`.
|
||||
|
||||
All are enabled by default.
|
||||
|
||||
| Feature flag | Does what |
|
||||
|--------------|-----------|
|
||||
| `serde` | Implements `serde` on all types
|
||||
| `epee` | Implements `cuprate_epee_encoding` on all types
|
||||
|--------------|-----------|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Status
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
/// TODO
|
||||
pub enum Error {}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,18 +1,69 @@
|
|||
//! Free functions.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Serde
|
||||
// These are functions used for conditionally (de)serialization.
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
use std::{future::Future, marker::PhantomData};
|
||||
|
||||
/// Returns `true` if the input `u` is equal to `0`.
|
||||
#[inline]
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)] // serde needs `&`
|
||||
pub(crate) const fn is_zero(u: &u64) -> bool {
|
||||
*u == 0
|
||||
}
|
||||
use axum::{routing::method_routing::get, Router};
|
||||
use tower::Service;
|
||||
|
||||
/// Returns `true` the input `u` is equal to `1`.
|
||||
#[inline]
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)] // serde needs `&`
|
||||
pub(crate) const fn is_one(u: &u64) -> bool {
|
||||
*u == 1
|
||||
use crate::{
|
||||
error::Error, request::Request, response::Response, route::json_rpc, rpc_handler::RpcHandler,
|
||||
RpcState,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Router
|
||||
/// TODO
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn create_router<H: RpcHandler>() -> Router<H::RpcState> {
|
||||
// List of `monerod` routes:
|
||||
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.h#L97-L189>
|
||||
Router::new()
|
||||
// JSON-RPC route.
|
||||
.route("/json_rpc", get(json_rpc))
|
||||
// Other JSON routes.
|
||||
.route("/get_height", todo!())
|
||||
.route("/getheight", todo!())
|
||||
.route("/get_transactions", todo!())
|
||||
.route("/gettransactions", todo!())
|
||||
.route("/get_alt_blocks_hashes", todo!())
|
||||
.route("/is_key_image_spent", todo!())
|
||||
.route("/send_raw_transaction", todo!())
|
||||
.route("/sendrawtransaction", todo!())
|
||||
.route("/start_mining", todo!())
|
||||
.route("/stop_mining", todo!())
|
||||
.route("/mining_status", todo!())
|
||||
.route("/save_bc", todo!())
|
||||
.route("/get_peer_list", todo!())
|
||||
.route("/get_public_nodes", todo!())
|
||||
.route("/set_log_hash_rate", todo!())
|
||||
.route("/set_log_level", todo!())
|
||||
.route("/set_log_categories", todo!())
|
||||
.route("/get_transaction_pool", todo!())
|
||||
.route("/get_transaction_pool_hashes", todo!())
|
||||
.route("/get_transaction_pool_stats", todo!())
|
||||
.route("/set_bootstrap_daemon", todo!())
|
||||
.route("/stop_daemon", todo!())
|
||||
.route("/get_info", todo!())
|
||||
.route("/getinfo", todo!())
|
||||
.route("/get_net_stats", todo!())
|
||||
.route("/get_limit", todo!())
|
||||
.route("/set_limit", todo!())
|
||||
.route("/out_peers", todo!())
|
||||
.route("/in_peers", todo!())
|
||||
.route("/get_outs", todo!())
|
||||
.route("/update", todo!())
|
||||
.route("/pop_blocks", todo!())
|
||||
// Binary routes.
|
||||
.route("/get_blocks.bin", todo!())
|
||||
.route("/getblocks.bin", todo!())
|
||||
.route("/get_blocks_by_height.bin", todo!())
|
||||
.route("/getblocks_by_height.bin", todo!())
|
||||
.route("/get_hashes.bin", todo!())
|
||||
.route("/gethashes.bin", todo!())
|
||||
.route("/get_o_indexes.bin", todo!())
|
||||
.route("/get_outs.bin", todo!())
|
||||
.route("/get_transaction_pool_hashes.bin", todo!())
|
||||
.route("/get_output_distribution.bin", todo!())
|
||||
// Unknown route.
|
||||
.route("/*", todo!())
|
||||
}
|
||||
|
|
|
@ -102,14 +102,24 @@
|
|||
)
|
||||
)]
|
||||
// TODO: remove me after finishing impl
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code, unreachable_code)]
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Mod
|
||||
mod constants;
|
||||
mod error;
|
||||
mod free;
|
||||
mod macros;
|
||||
mod method;
|
||||
mod request;
|
||||
mod response;
|
||||
mod route;
|
||||
mod state;
|
||||
mod rpc_handler;
|
||||
mod rpc_state;
|
||||
|
||||
pub use error::Error;
|
||||
pub use free::create_router;
|
||||
pub use method::Method;
|
||||
pub use request::Request;
|
||||
pub use response::Response;
|
||||
pub use rpc_handler::{ConcreteRpcHandler, RpcHandler};
|
||||
pub use rpc_state::{ConcreteRpcState, RpcState};
|
||||
|
|
|
@ -1,379 +1,3 @@
|
|||
//! Macros.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- 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}`
|
||||
/// - `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
|
||||
/// generate which docs.
|
||||
///
|
||||
/// See the [`crate::json`] module for example usage.
|
||||
///
|
||||
/// # Macro internals
|
||||
/// This macro uses:
|
||||
/// - [`__define_request`]
|
||||
/// - [`__define_response`]
|
||||
/// - [`__define_request_and_response_doc`]
|
||||
///
|
||||
/// # `__define_request`
|
||||
/// This macro has 2 branches. If the caller provides
|
||||
/// `Request {}`, i.e. no fields, it will generate:
|
||||
/// ```
|
||||
/// pub type Request = ();
|
||||
/// ```
|
||||
/// If they _did_ specify fields, it will generate:
|
||||
/// ```
|
||||
/// pub struct Request {/* fields */}
|
||||
/// ```
|
||||
/// This is because having a bunch of types that are all empty structs
|
||||
/// means they are not compatible and it makes it cumbersome for end-users.
|
||||
/// Really, they semantically are empty types, so `()` is used.
|
||||
///
|
||||
/// # `__define_response`
|
||||
/// This macro has 2 branches. If the caller provides `Response`
|
||||
/// it will generate a normal struct with no additional fields.
|
||||
///
|
||||
/// If the caller provides a base type from [`crate::base`], it will
|
||||
/// flatten that into the request type automatically.
|
||||
///
|
||||
/// E.g. `Response {/*...*/}` and `ResponseBase {/*...*/}`
|
||||
/// would trigger the different branches.
|
||||
macro_rules! define_request_and_response {
|
||||
(
|
||||
// The markdown tag for Monero daemon 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.
|
||||
// Attributes added here will apply to _both_
|
||||
// request and response types.
|
||||
$( #[$type_attr:meta] )*
|
||||
$type_name:ident,
|
||||
|
||||
// The request type (and any doc comments, derives, etc).
|
||||
$( #[$request_type_attr:meta] )*
|
||||
Request {
|
||||
// And any fields.
|
||||
$(
|
||||
$( #[$request_field_attr:meta] )* // Field attribute.
|
||||
$request_field:ident: $request_field_type:ty // field_name: field type
|
||||
$(as $request_field_type_as:ty)? // (optional) alternative type (de)serialization
|
||||
$(= $request_field_type_default:expr, $request_field_type_default_string:literal)?, // (optional) default value
|
||||
)*
|
||||
},
|
||||
|
||||
// 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
|
||||
$(as $response_field_type_as:ty)?
|
||||
$(= $response_field_type_default:expr, $response_field_type_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => { paste::paste! {
|
||||
$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,
|
||||
)]
|
||||
///
|
||||
$( #[$type_attr] )*
|
||||
///
|
||||
$( #[$request_type_attr] )*
|
||||
[<$type_name Request>] {
|
||||
$(
|
||||
$( #[$request_field_attr] )*
|
||||
$request_field: $request_field_type
|
||||
$(as $request_field_type_as)?
|
||||
$(= $request_field_type_default, $request_field_type_default_string)?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
$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,
|
||||
)]
|
||||
///
|
||||
$( #[$type_attr] )*
|
||||
///
|
||||
$( #[$response_type_attr] )*
|
||||
$response_base_type => [<$type_name Response>] {
|
||||
$(
|
||||
$( #[$response_field_attr] )*
|
||||
$response_field: $response_field_type
|
||||
$(as $response_field_type_as)?
|
||||
$(= $response_field_type_default, $response_field_type_default_string)?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
pub(crate) use define_request_and_response;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_request
|
||||
/// Define a request type.
|
||||
///
|
||||
/// This is only used in [`define_request_and_response`], see it for docs.
|
||||
///
|
||||
/// `__` is used to notate that this shouldn't be called directly.
|
||||
macro_rules! __define_request {
|
||||
//------------------------------------------------------------------------------
|
||||
// This branch will generate a type alias to `()` if only given `{}` as input.
|
||||
(
|
||||
// Any doc comments, derives, etc.
|
||||
$( #[$attr:meta] )*
|
||||
// The response type.
|
||||
$t:ident {}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
///
|
||||
/// This request has no inputs.
|
||||
pub type $t = ();
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// This branch of the macro expects fields within the `{}`,
|
||||
// and will generate a `struct`
|
||||
(
|
||||
// Any doc comments, derives, etc.
|
||||
$( #[$attr:meta] )*
|
||||
// The response type.
|
||||
$t:ident {
|
||||
// And any fields.
|
||||
$(
|
||||
$( #[$field_attr:meta] )* // field attributes
|
||||
// field_name: FieldType
|
||||
$field:ident: $field_type:ty
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
// The $field_default is an optional extra token that represents
|
||||
// a default value to pass to [`cuprate_epee_encoding::epee_object`],
|
||||
// see it for usage.
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
#[allow(dead_code, missing_docs)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $field_default)?,
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use __define_request;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_response
|
||||
/// Define a response type.
|
||||
///
|
||||
/// This is only used in [`define_request_and_response`], see it for docs.
|
||||
///
|
||||
/// `__` is used to notate that this shouldn't be called directly.
|
||||
macro_rules! __define_response {
|
||||
//------------------------------------------------------------------------------
|
||||
// This version of the macro expects the literal ident
|
||||
// `Response` => $response_type_name.
|
||||
//
|
||||
// It will create a `struct` that _doesn't_ use a base from [`crate::base`],
|
||||
// for example, [`crate::json::BannedResponse`] doesn't use a base, so it
|
||||
// uses this branch.
|
||||
(
|
||||
// Any doc comments, derives, etc.
|
||||
$( #[$attr:meta] )*
|
||||
// The response type.
|
||||
Response => $t:ident {
|
||||
// And any fields.
|
||||
// See [`__define_request`] for docs, this does the same thing.
|
||||
$(
|
||||
$( #[$field_attr:meta] )*
|
||||
$field:ident: $field_type:ty
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $field_default)?,
|
||||
)*
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// This version of the macro expects a `Request` base type from [`crate::bases`].
|
||||
(
|
||||
// Any doc comments, derives, etc.
|
||||
$( #[$attr:meta] )*
|
||||
// The response base type => actual name of the struct
|
||||
$base:ty => $t:ident {
|
||||
// And any fields.
|
||||
// See [`__define_request`] for docs, this does the same thing.
|
||||
$(
|
||||
$( #[$field_attr:meta] )*
|
||||
$field:ident: $field_type:ty
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||
pub base: $base,
|
||||
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $field_default)?,
|
||||
)*
|
||||
!flatten: base: $base,
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use __define_response;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_request_and_response_doc
|
||||
/// Generate documentation for the types generated
|
||||
/// by the [`__define_request_and_response`] macro.
|
||||
///
|
||||
/// See it for more info on inputs.
|
||||
///
|
||||
/// `__` is used to notate that this shouldn't be called directly.
|
||||
macro_rules! __define_request_and_response_doc {
|
||||
(
|
||||
// This labels the last `[request]` or `[response]`
|
||||
// hyperlink in documentation. Input is either:
|
||||
// - "request"
|
||||
// - "response"
|
||||
//
|
||||
// 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_type:ident,
|
||||
|
||||
$monero_daemon_rpc_doc_link:ident,
|
||||
$monero_code_commit:ident,
|
||||
$monero_code_filename:ident,
|
||||
$monero_code_filename_extension:ident,
|
||||
$monero_code_line_start:literal,
|
||||
$monero_code_line_end:literal,
|
||||
) => {
|
||||
concat!(
|
||||
"",
|
||||
"[Definition](",
|
||||
"https://github.com/monero-project/monero/blob/",
|
||||
stringify!($monero_code_commit),
|
||||
"/src/rpc/",
|
||||
stringify!($monero_code_filename),
|
||||
".",
|
||||
stringify!($monero_code_filename_extension),
|
||||
"#L",
|
||||
stringify!($monero_code_line_start),
|
||||
"-L",
|
||||
stringify!($monero_code_line_end),
|
||||
"), [documentation](",
|
||||
"https://www.getmonero.org/resources/developer-guides/daemon-rpc.html",
|
||||
"#",
|
||||
stringify!($monero_daemon_rpc_doc_link),
|
||||
"), [",
|
||||
$request_or_response,
|
||||
"](",
|
||||
stringify!($request_or_response_type),
|
||||
")."
|
||||
)
|
||||
};
|
||||
}
|
||||
pub(crate) use __define_request_and_response_doc;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Macro
|
||||
/// Output a string link to `monerod` source code.
|
||||
macro_rules! monero_definition_link {
|
||||
(
|
||||
$commit:ident, // Git commit hash
|
||||
$file_path:literal, // File path within `monerod`'s `src/`, e.g. `rpc/core_rpc_server_commands_defs.h`
|
||||
$start:literal$(..=$end:literal)? // File lines, e.g. `0..=123` or `0`
|
||||
) => {
|
||||
concat!(
|
||||
"[Definition](https://github.com/monero-project/monero/blob/",
|
||||
stringify!($commit),
|
||||
"/src/",
|
||||
$file_path,
|
||||
"#L",
|
||||
stringify!($start),
|
||||
$(
|
||||
"-L",
|
||||
stringify!($end),
|
||||
)?
|
||||
")."
|
||||
)
|
||||
};
|
||||
}
|
||||
pub(crate) use monero_definition_link;
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
|
|
31
rpc/interface/src/method.rs
Normal file
31
rpc/interface/src/method.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use cuprate_rpc_types::json::GetBlockRequest;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
/// TODO
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(tag = "method", content = "params")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Method {
|
||||
/// TODO
|
||||
GetBlock(GetBlockRequest),
|
||||
}
|
||||
|
||||
impl Method {
|
||||
/// TODO
|
||||
pub const fn is_restricted(&self) -> bool {
|
||||
match self {
|
||||
Self::GetBlock(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
// use super::*;
|
||||
}
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Status
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
/// TODO
|
||||
pub enum Request {}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
//---------------------------------------------------------------------------------------------------- Import
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Status
|
||||
/// TODO
|
||||
pub enum Response {}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -3,8 +3,25 @@
|
|||
//! All types are originally defined in [`rpc/core_rpc_server_commands_defs.h`](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h).
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use std::{future::Future, sync::Arc};
|
||||
|
||||
use axum::Json;
|
||||
use tower::Service;
|
||||
|
||||
use crate::{
|
||||
error::Error, method::Method, request::Request, response::Response, rpc_handler::RpcHandler,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Struct definitions
|
||||
/// TODO
|
||||
// pub(crate) async fn json_rpc<H: RpcHandler>(
|
||||
pub(crate) async fn json_rpc(
|
||||
// handler: Arc<H>,
|
||||
Json(request): Json<cuprate_json_rpc::Request<Method>>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// // This generates 2 structs:
|
||||
// //
|
||||
// // - `GetBlockTemplateRequest`
|
|
@ -1,5 +1,7 @@
|
|||
//! TODO
|
||||
|
||||
mod bin;
|
||||
mod json;
|
||||
mod json_rpc;
|
||||
mod other;
|
||||
|
||||
pub(crate) use json_rpc::json_rpc;
|
||||
|
|
49
rpc/interface/src/rpc_handler.rs
Normal file
49
rpc/interface/src/rpc_handler.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
use std::{future::Future, marker::PhantomData, sync::Arc};
|
||||
|
||||
use tower::Service;
|
||||
|
||||
use crate::{
|
||||
error::Error, request::Request, response::Response, rpc_state::ConcreteRpcState, RpcState,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
/// TODO
|
||||
pub trait RpcHandler: Send + Sync + 'static {
|
||||
/// TODO
|
||||
type RpcState: RpcState;
|
||||
|
||||
/// TODO
|
||||
type Handler: Send + Sync + 'static + Service<Request>;
|
||||
// where
|
||||
// <Self::Handler as Service<Request>>::Response: Into<Response>,
|
||||
// <Self::Handler as Service<Request>>::Error: Into<Error>,
|
||||
// <Self::Handler as Service<Request>>::Future: Future<Output = Result<Response, Error>>;
|
||||
|
||||
/// TODO
|
||||
fn state(&self) -> Self::RpcState;
|
||||
}
|
||||
|
||||
/// TODO
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct ConcreteRpcHandler<Handler> {
|
||||
state: ConcreteRpcState,
|
||||
_handler: PhantomData<Handler>,
|
||||
}
|
||||
|
||||
impl<H> RpcHandler for ConcreteRpcHandler<H>
|
||||
where
|
||||
H: Send + Sync + 'static + Service<Request>,
|
||||
<H as Service<Request>>::Response: Into<Response>,
|
||||
<H as Service<Request>>::Error: Into<Error>,
|
||||
<H as Service<Request>>::Future: Future<Output = Result<Response, Error>>,
|
||||
{
|
||||
type RpcState = ConcreteRpcState;
|
||||
type Handler = H;
|
||||
|
||||
fn state(&self) -> Self::RpcState {
|
||||
self.state
|
||||
}
|
||||
}
|
30
rpc/interface/src/rpc_state.rs
Normal file
30
rpc/interface/src/rpc_state.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
use std::{future::Future, marker::PhantomData, sync::Arc};
|
||||
|
||||
use tower::Service;
|
||||
|
||||
use crate::{error::Error, request::Request, response::Response};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
/// TODO
|
||||
pub trait RpcState
|
||||
where
|
||||
Self: Clone + Send + Sync + 'static,
|
||||
{
|
||||
/// TODO
|
||||
fn restricted(&self) -> bool;
|
||||
}
|
||||
|
||||
/// TODO
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct ConcreteRpcState {
|
||||
restricted: bool,
|
||||
}
|
||||
|
||||
impl RpcState for ConcreteRpcState {
|
||||
fn restricted(&self) -> bool {
|
||||
self.restricted
|
||||
}
|
||||
}
|
|
@ -1,379 +0,0 @@
|
|||
//! Macros.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- 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}`
|
||||
/// - `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
|
||||
/// generate which docs.
|
||||
///
|
||||
/// See the [`crate::json`] module for example usage.
|
||||
///
|
||||
/// # Macro internals
|
||||
/// This macro uses:
|
||||
/// - [`__define_request`]
|
||||
/// - [`__define_response`]
|
||||
/// - [`__define_request_and_response_doc`]
|
||||
///
|
||||
/// # `__define_request`
|
||||
/// This macro has 2 branches. If the caller provides
|
||||
/// `Request {}`, i.e. no fields, it will generate:
|
||||
/// ```
|
||||
/// pub type Request = ();
|
||||
/// ```
|
||||
/// If they _did_ specify fields, it will generate:
|
||||
/// ```
|
||||
/// pub struct Request {/* fields */}
|
||||
/// ```
|
||||
/// This is because having a bunch of types that are all empty structs
|
||||
/// means they are not compatible and it makes it cumbersome for end-users.
|
||||
/// Really, they semantically are empty types, so `()` is used.
|
||||
///
|
||||
/// # `__define_response`
|
||||
/// This macro has 2 branches. If the caller provides `Response`
|
||||
/// it will generate a normal struct with no additional fields.
|
||||
///
|
||||
/// If the caller provides a base type from [`crate::base`], it will
|
||||
/// flatten that into the request type automatically.
|
||||
///
|
||||
/// E.g. `Response {/*...*/}` and `ResponseBase {/*...*/}`
|
||||
/// would trigger the different branches.
|
||||
macro_rules! define_request_and_response {
|
||||
(
|
||||
// The markdown tag for Monero daemon 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.
|
||||
// Attributes added here will apply to _both_
|
||||
// request and response types.
|
||||
$( #[$type_attr:meta] )*
|
||||
$type_name:ident,
|
||||
|
||||
// The request type (and any doc comments, derives, etc).
|
||||
$( #[$request_type_attr:meta] )*
|
||||
Request {
|
||||
// And any fields.
|
||||
$(
|
||||
$( #[$request_field_attr:meta] )* // Field attribute.
|
||||
$request_field:ident: $request_field_type:ty // field_name: field type
|
||||
$(as $request_field_type_as:ty)? // (optional) alternative type (de)serialization
|
||||
$(= $request_field_type_default:expr, $request_field_type_default_string:literal)?, // (optional) default value
|
||||
)*
|
||||
},
|
||||
|
||||
// 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
|
||||
$(as $response_field_type_as:ty)?
|
||||
$(= $response_field_type_default:expr, $response_field_type_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => { paste::paste! {
|
||||
$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,
|
||||
)]
|
||||
///
|
||||
$( #[$type_attr] )*
|
||||
///
|
||||
$( #[$request_type_attr] )*
|
||||
[<$type_name Request>] {
|
||||
$(
|
||||
$( #[$request_field_attr] )*
|
||||
$request_field: $request_field_type
|
||||
$(as $request_field_type_as)?
|
||||
$(= $request_field_type_default, $request_field_type_default_string)?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
$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,
|
||||
)]
|
||||
///
|
||||
$( #[$type_attr] )*
|
||||
///
|
||||
$( #[$response_type_attr] )*
|
||||
$response_base_type => [<$type_name Response>] {
|
||||
$(
|
||||
$( #[$response_field_attr] )*
|
||||
$response_field: $response_field_type
|
||||
$(as $response_field_type_as)?
|
||||
$(= $response_field_type_default, $response_field_type_default_string)?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
pub(crate) use define_request_and_response;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_request
|
||||
/// Define a request type.
|
||||
///
|
||||
/// This is only used in [`define_request_and_response`], see it for docs.
|
||||
///
|
||||
/// `__` is used to notate that this shouldn't be called directly.
|
||||
macro_rules! __define_request {
|
||||
//------------------------------------------------------------------------------
|
||||
// This branch will generate a type alias to `()` if only given `{}` as input.
|
||||
(
|
||||
// Any doc comments, derives, etc.
|
||||
$( #[$attr:meta] )*
|
||||
// The response type.
|
||||
$t:ident {}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
///
|
||||
/// This request has no inputs.
|
||||
pub type $t = ();
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// This branch of the macro expects fields within the `{}`,
|
||||
// and will generate a `struct`
|
||||
(
|
||||
// Any doc comments, derives, etc.
|
||||
$( #[$attr:meta] )*
|
||||
// The response type.
|
||||
$t:ident {
|
||||
// And any fields.
|
||||
$(
|
||||
$( #[$field_attr:meta] )* // field attributes
|
||||
// field_name: FieldType
|
||||
$field:ident: $field_type:ty
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
// The $field_default is an optional extra token that represents
|
||||
// a default value to pass to [`cuprate_epee_encoding::epee_object`],
|
||||
// see it for usage.
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
#[allow(dead_code, missing_docs)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $field_default)?,
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use __define_request;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_response
|
||||
/// Define a response type.
|
||||
///
|
||||
/// This is only used in [`define_request_and_response`], see it for docs.
|
||||
///
|
||||
/// `__` is used to notate that this shouldn't be called directly.
|
||||
macro_rules! __define_response {
|
||||
//------------------------------------------------------------------------------
|
||||
// This version of the macro expects the literal ident
|
||||
// `Response` => $response_type_name.
|
||||
//
|
||||
// It will create a `struct` that _doesn't_ use a base from [`crate::base`],
|
||||
// for example, [`crate::json::BannedResponse`] doesn't use a base, so it
|
||||
// uses this branch.
|
||||
(
|
||||
// Any doc comments, derives, etc.
|
||||
$( #[$attr:meta] )*
|
||||
// The response type.
|
||||
Response => $t:ident {
|
||||
// And any fields.
|
||||
// See [`__define_request`] for docs, this does the same thing.
|
||||
$(
|
||||
$( #[$field_attr:meta] )*
|
||||
$field:ident: $field_type:ty
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $field_default)?,
|
||||
)*
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// This version of the macro expects a `Request` base type from [`crate::bases`].
|
||||
(
|
||||
// Any doc comments, derives, etc.
|
||||
$( #[$attr:meta] )*
|
||||
// The response base type => actual name of the struct
|
||||
$base:ty => $t:ident {
|
||||
// And any fields.
|
||||
// See [`__define_request`] for docs, this does the same thing.
|
||||
$(
|
||||
$( #[$field_attr:meta] )*
|
||||
$field:ident: $field_type:ty
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||
pub base: $base,
|
||||
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $field_default)?,
|
||||
)*
|
||||
!flatten: base: $base,
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use __define_response;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_request_and_response_doc
|
||||
/// Generate documentation for the types generated
|
||||
/// by the [`__define_request_and_response`] macro.
|
||||
///
|
||||
/// See it for more info on inputs.
|
||||
///
|
||||
/// `__` is used to notate that this shouldn't be called directly.
|
||||
macro_rules! __define_request_and_response_doc {
|
||||
(
|
||||
// This labels the last `[request]` or `[response]`
|
||||
// hyperlink in documentation. Input is either:
|
||||
// - "request"
|
||||
// - "response"
|
||||
//
|
||||
// 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_type:ident,
|
||||
|
||||
$monero_daemon_rpc_doc_link:ident,
|
||||
$monero_code_commit:ident,
|
||||
$monero_code_filename:ident,
|
||||
$monero_code_filename_extension:ident,
|
||||
$monero_code_line_start:literal,
|
||||
$monero_code_line_end:literal,
|
||||
) => {
|
||||
concat!(
|
||||
"",
|
||||
"[Definition](",
|
||||
"https://github.com/monero-project/monero/blob/",
|
||||
stringify!($monero_code_commit),
|
||||
"/src/rpc/",
|
||||
stringify!($monero_code_filename),
|
||||
".",
|
||||
stringify!($monero_code_filename_extension),
|
||||
"#L",
|
||||
stringify!($monero_code_line_start),
|
||||
"-L",
|
||||
stringify!($monero_code_line_end),
|
||||
"), [documentation](",
|
||||
"https://www.getmonero.org/resources/developer-guides/daemon-rpc.html",
|
||||
"#",
|
||||
stringify!($monero_daemon_rpc_doc_link),
|
||||
"), [",
|
||||
$request_or_response,
|
||||
"](",
|
||||
stringify!($request_or_response_type),
|
||||
")."
|
||||
)
|
||||
};
|
||||
}
|
||||
pub(crate) use __define_request_and_response_doc;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Macro
|
||||
/// Output a string link to `monerod` source code.
|
||||
macro_rules! monero_definition_link {
|
||||
(
|
||||
$commit:ident, // Git commit hash
|
||||
$file_path:literal, // File path within `monerod`'s `src/`, e.g. `rpc/core_rpc_server_commands_defs.h`
|
||||
$start:literal$(..=$end:literal)? // File lines, e.g. `0..=123` or `0`
|
||||
) => {
|
||||
concat!(
|
||||
"[Definition](https://github.com/monero-project/monero/blob/",
|
||||
stringify!($commit),
|
||||
"/src/",
|
||||
$file_path,
|
||||
"#L",
|
||||
stringify!($start),
|
||||
$(
|
||||
"-L",
|
||||
stringify!($end),
|
||||
)?
|
||||
")."
|
||||
)
|
||||
};
|
||||
}
|
||||
pub(crate) use monero_definition_link;
|
Loading…
Reference in a new issue