1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
//! Macros to delegate TransportRequest and FromProof to an enum wrapper.
//!
//! Two enum wrappers are created using [delegate_enum!](crate::delegate_enum!):
//!
//! * request
//! * response
//!
//! Each of these enums has a variant for each request/response pair. Name of variant in request enum is the same as
//! the name of variant in response.
/// Delegate the execution of a transport request to the appropriate variant of an enum wrapper.
///
/// Given two enums, request and response, that wrap multiple requests/responses for one object type, this macro
/// implements [TransportRequest](crate::platform::dapi::transport::TransportRequest) for the request enum and
/// delegates the execution of the transport request to the appropriate variant.
///
/// Each variant in request enum must have a corresponding variant in response enum.
/// Variant names in request and response enums must match.
/// Variants must take exactly one argument that implements
/// [TransportRequest](crate::platform::dapi::transport::TransportRequest) (for request) and
/// [TransportResponse](crate::platform::dapi::transport::TransportResponse) (for response), where for a given variant,
/// response must be the response type of the request variant.
///
/// Macro [delegate_enum!](crate::delegate_enum!) can be used to generate these enums and implement required
/// traits.
#[macro_export]
macro_rules! delegate_transport_request_variant {
($request:ty, $response:ty, $($variant:ident),+) => {
impl $crate::platform::dapi::transport::TransportRequest for $request {
type Client = $crate::platform::dapi::transport::PlatformGrpcClient;
type Response = $response;
const SETTINGS_OVERRIDES: $crate::platform::dapi::RequestSettings = $crate::platform::dapi::RequestSettings::default();
/// TODO: Not sure how to do that
fn method_name(&self) -> &'static str {
""
}
fn execute_transport<'c>(
self,
client: &'c mut Self::Client,
settings: &$crate::platform::dapi::transport::AppliedRequestSettings,
) -> $crate::platform::dapi::transport::BoxFuture<'c, Result<Self::Response, <Self::Client as $crate::platform::dapi::transport::TransportClient>::Error>> {
use futures::FutureExt;
use $request::*;
let settings =settings.clone();
// We need to build new async box because we have to map response to the $response type
match self {$(
$variant(request) => async move {
request
.execute_transport(client, &settings)
.await
.map(Into::into)
}
.boxed(),
)*}
}
}
}
}
/// Delegate the execution of a [FromProof](drive_proof_verifier::FromProof) trait to an enum supporting multiple variants.
///
/// In order to support multiple request/response types for one object (like, GetIdentityRequest and
/// GetIdentityByFirstPublicKeyHashRequest for Identity), we need to wrap them in an enum and
/// delegate the execution of the transport request to the appropriate variant.
///
/// See [delegate_enum!](crate::delegate_enum!) for more details.
#[macro_export]
macro_rules! delegate_from_proof_variant {
($request:ty, $response:ty, $object:ty, $(($variant:ident, $req: ty, $resp: ty)),+) => {
impl drive_proof_verifier::FromProof<$request> for $object {
type Request = $request;
type Response = $response;
fn maybe_from_proof_with_metadata<'a, I: Into<Self::Request>, O: Into<Self::Response>>(
request: I,
response: O,
network: dpp::dashcore::Network,
version: &dpp::version::PlatformVersion,
provider: &'a dyn drive_proof_verifier::ContextProvider,
) -> Result<(Option<Self>, ResponseMetadata, dapi_grpc::platform::v0::Proof), drive_proof_verifier::Error>
where
Self: Sized + 'a,
{
use $request as req;
use $response as resp;
let request: Self::Request = request.into();
let response: Self::Response = response.into();
match request {$(
req::$variant(request) => {
if let resp::$variant(response) = response {
<Self as drive_proof_verifier::FromProof<$req>>::maybe_from_proof_with_metadata(
request, response, network, version, provider,
)
} else {
Err(drive_proof_verifier::Error::ResponseDecodeError {
error: format!(
"expected {}, got {}",
"GetIdentityResponse",
$crate::platform::delegate::type_name(&response),
),
})
}
}
)*
}
}
}
};
}
#[macro_export]
/// Define enums that will wrap multiple requests/responses for one object.
///
/// In order to support multiple request/response types for one object (like, GetIdentityRequest and
/// GetIdentityByPublicKeyHashRequest for Identity), we need to wrap them in an enum and
/// delegate [TransportRequest](crate::platform::dapi::transport::TransportRequest)
/// and [FromProof](drive_proof_verifier::FromProof) to the appropriate variant.
///
/// This macro creates enums for requests (`$request`) and responses (`$response`) and variants (`$variant`) for
/// each request (`$req`) /response (`$req`) pair. Variant name in request and response enums are the same.
///
/// It also calls [delegate_transport_request_variant!](crate::delegate_transport_request_variant!) and
/// [delegate_from_proof_variant!](crate::delegate_from_proof_variant!) to delegate
/// [TransportRequest](crate::platform::dapi::transport::TransportRequest)
/// and [FromProof](drive_proof_verifier::FromProof)
/// traits to the appropriate variant.
macro_rules! delegate_enum {
($request:ident, $response:ident, $object:ty, $(($variant:ident, $req: ty, $resp: ty)),+) => {
/// Wrapper around multiple requests for one object type.
#[derive(Debug, Clone, derive_more::From, dapi_grpc_macros::Mockable)]
#[cfg_attr(feature="mocks", derive(serde::Serialize, serde::Deserialize))]
#[allow(missing_docs)]
pub enum $request {
$(
$variant($req),
)+
}
/// Wrapper around multiple responses for one object type.
#[derive(Debug, Clone, Default, derive_more::From, dapi_grpc_macros::Mockable)]
#[cfg_attr(feature="mocks", derive(serde::Serialize, serde::Deserialize))]
#[allow(missing_docs)]
pub enum $response {
#[default]
/// Unknown or unsupported request type.
///
/// Used as default variant for the enum in mocks.
///
/// Can cause panic.
Unknown,
$(
$variant($resp),
)+
}
$crate::delegate_transport_request_variant! {
$request,
$response,
$($variant),+
}
$crate::delegate_from_proof_variant! {
$request,
$response,
$object,
$(($variant,$req,$resp)),+
}
};
}
/// Return type name of a variable as a String
pub(crate) fn type_name<T>(_v: &T) -> String {
std::any::type_name::<T>().to_string()
}