mirror of
https://github.com/Start9Labs/rpc-toolkit.git
synced 2026-03-26 02:11:56 +00:00
custom_cli
This commit is contained in:
@@ -493,7 +493,14 @@ fn rpc_handler(
|
|||||||
method: &str,
|
method: &str,
|
||||||
args: Params#param_ty_generics,
|
args: Params#param_ty_generics,
|
||||||
) -> Result<::rpc_toolkit::command_helpers::prelude::Value, ::rpc_toolkit::command_helpers::prelude::RpcError> {
|
) -> Result<::rpc_toolkit::command_helpers::prelude::Value, ::rpc_toolkit::command_helpers::prelude::RpcError> {
|
||||||
Ok(::rpc_toolkit::command_helpers::prelude::to_value(#invocation)?)
|
if method.is_empty() {
|
||||||
|
Ok(::rpc_toolkit::command_helpers::prelude::to_value(#invocation)?)
|
||||||
|
} else {
|
||||||
|
Err(::rpc_toolkit::command_helpers::prelude::RpcError {
|
||||||
|
data: Some(method.into()),
|
||||||
|
..::rpc_toolkit::command_helpers::prelude::yajrc::METHOD_NOT_FOUND_ERROR
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -818,44 +825,91 @@ fn cli_handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Options::Leaf(opt) => {
|
Options::Leaf(opt) => {
|
||||||
let invocation = if opt.is_async {
|
if let ExecutionContext::CustomCli {
|
||||||
|
ref cli, is_async, ..
|
||||||
|
} = opt.exec_ctx
|
||||||
|
{
|
||||||
|
let fn_path = cli;
|
||||||
|
let invocation = if is_async {
|
||||||
|
quote! {
|
||||||
|
rt_ref.block_on(#fn_path(#(#param),*))?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
#fn_path(#(#param),*)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let display_res = if let Some(display_fn) = &opt.display {
|
||||||
|
quote! {
|
||||||
|
#display_fn(#invocation, matches)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
::rpc_toolkit::command_helpers::prelude::default_display(#invocation, matches)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let rt_action = if is_async {
|
||||||
|
create_rt
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
drop(rt);
|
||||||
|
}
|
||||||
|
};
|
||||||
quote! {
|
quote! {
|
||||||
rt_ref.block_on(#fn_path(#(#param),*))?
|
pub fn cli_handler#generics(
|
||||||
}
|
ctx: #ctx_ty,
|
||||||
} else {
|
mut rt: Option<::rpc_toolkit::command_helpers::prelude::Runtime>,
|
||||||
quote! {
|
matches: &::rpc_toolkit::command_helpers::prelude::ArgMatches<'_>,
|
||||||
#fn_path(#(#param),*)?
|
_method: ::rpc_toolkit::command_helpers::prelude::Cow<'_, str>,
|
||||||
}
|
parent_params: ParentParams
|
||||||
};
|
) -> Result<(), ::rpc_toolkit::command_helpers::prelude::RpcError> {
|
||||||
let display_res = if let Some(display_fn) = &opt.display {
|
#param_struct_def
|
||||||
quote! {
|
|
||||||
#display_fn(#invocation, matches)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quote! {
|
|
||||||
::rpc_toolkit::command_helpers::prelude::default_display(#invocation, matches)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let rt_action = if opt.is_async {
|
|
||||||
create_rt
|
|
||||||
} else {
|
|
||||||
quote! {
|
|
||||||
drop(rt);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
quote! {
|
|
||||||
pub fn cli_handler#generics(
|
|
||||||
ctx: #ctx_ty,
|
|
||||||
mut rt: Option<::rpc_toolkit::command_helpers::prelude::Runtime>,
|
|
||||||
matches: &::rpc_toolkit::command_helpers::prelude::ArgMatches<'_>,
|
|
||||||
_method: ::rpc_toolkit::command_helpers::prelude::Cow<'_, str>,
|
|
||||||
parent_params: ParentParams
|
|
||||||
) -> Result<(), ::rpc_toolkit::command_helpers::prelude::RpcError> {
|
|
||||||
#param_struct_def
|
|
||||||
|
|
||||||
#rt_action
|
#rt_action
|
||||||
|
|
||||||
Ok(#display_res)
|
Ok(#display_res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let invocation = if opt.is_async {
|
||||||
|
quote! {
|
||||||
|
rt_ref.block_on(#fn_path(#(#param),*))?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
#fn_path(#(#param),*)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let display_res = if let Some(display_fn) = &opt.display {
|
||||||
|
quote! {
|
||||||
|
#display_fn(#invocation, matches)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
::rpc_toolkit::command_helpers::prelude::default_display(#invocation, matches)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let rt_action = if opt.is_async {
|
||||||
|
create_rt
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
drop(rt);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
pub fn cli_handler#generics(
|
||||||
|
ctx: #ctx_ty,
|
||||||
|
mut rt: Option<::rpc_toolkit::command_helpers::prelude::Runtime>,
|
||||||
|
matches: &::rpc_toolkit::command_helpers::prelude::ArgMatches<'_>,
|
||||||
|
_method: ::rpc_toolkit::command_helpers::prelude::Cow<'_, str>,
|
||||||
|
parent_params: ParentParams
|
||||||
|
) -> Result<(), ::rpc_toolkit::command_helpers::prelude::RpcError> {
|
||||||
|
#param_struct_def
|
||||||
|
|
||||||
|
#rt_action
|
||||||
|
|
||||||
|
Ok(#display_res)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ pub enum ExecutionContext {
|
|||||||
CliOnly(Path),
|
CliOnly(Path),
|
||||||
RpcOnly(Path),
|
RpcOnly(Path),
|
||||||
Local(Path),
|
Local(Path),
|
||||||
|
CustomCli {
|
||||||
|
custom: Path,
|
||||||
|
cli: Path,
|
||||||
|
is_async: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
impl Default for ExecutionContext {
|
impl Default for ExecutionContext {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
|||||||
@@ -126,6 +126,73 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result<Options> {
|
|||||||
"`display` cannot be assigned to",
|
"`display` cannot be assigned to",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("custom_cli") => {
|
||||||
|
if list.nested.len() == 1 {
|
||||||
|
match &opt.common().exec_ctx {
|
||||||
|
ExecutionContext::Standard => match &list.nested[0] {
|
||||||
|
NestedMeta::Meta(Meta::Path(custom_cli_impl)) => {
|
||||||
|
opt.common().exec_ctx = ExecutionContext::CustomCli {
|
||||||
|
custom: list.path,
|
||||||
|
cli: custom_cli_impl.clone(),
|
||||||
|
is_async: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NestedMeta::Meta(Meta::List(custom_cli_impl)) if custom_cli_impl.nested.len() == 1 => {
|
||||||
|
let is_async = match custom_cli_impl.nested.first().unwrap() {
|
||||||
|
NestedMeta::Meta(Meta::Path(p)) if p.is_ident("async") => false,
|
||||||
|
arg => return Err(Error::new(arg.span(), "unknown argument")),
|
||||||
|
};
|
||||||
|
opt.common().exec_ctx = ExecutionContext::CustomCli {
|
||||||
|
custom: list.path,
|
||||||
|
cli: custom_cli_impl.path.clone(),
|
||||||
|
is_async,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
a => {
|
||||||
|
return Err(Error::new(
|
||||||
|
a.span(),
|
||||||
|
"`custom_cli` implementation must be a path, or a list with 1 argument",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ExecutionContext::CliOnly(_) => {
|
||||||
|
return Err(Error::new(list.span(), "duplicate argument: `cli_only`"))
|
||||||
|
}
|
||||||
|
ExecutionContext::RpcOnly(_) => {
|
||||||
|
return Err(Error::new(
|
||||||
|
list.span(),
|
||||||
|
"`cli_only` and `rpc_only` are mutually exclusive",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
ExecutionContext::Local(_) => {
|
||||||
|
return Err(Error::new(
|
||||||
|
list.span(),
|
||||||
|
"`cli_only` and `local` are mutually exclusive",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
ExecutionContext::CustomCli { .. } => {
|
||||||
|
return Err(Error::new(
|
||||||
|
list.span(),
|
||||||
|
"`cli_only` and `custom_cli` are mutually exclusive",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(Error::new(
|
||||||
|
list.nested.span(),
|
||||||
|
"`custom_cli` can only have one implementation",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NestedMeta::Meta(Meta::Path(p)) if p.is_ident("custom_cli") => {
|
||||||
|
return Err(Error::new(p.span(), "`custom_cli` requires an argument"));
|
||||||
|
}
|
||||||
|
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("custom_cli") => {
|
||||||
|
return Err(Error::new(
|
||||||
|
nv.path.span(),
|
||||||
|
"`custom_cli` cannot be assigned to",
|
||||||
|
));
|
||||||
|
}
|
||||||
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("aliases") => {
|
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("aliases") => {
|
||||||
if !opt.common().aliases.is_empty() {
|
if !opt.common().aliases.is_empty() {
|
||||||
return Err(Error::new(list.span(), "duplicate argument `alias`"));
|
return Err(Error::new(list.span(), "duplicate argument `alias`"));
|
||||||
@@ -170,6 +237,12 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result<Options> {
|
|||||||
"`cli_only` and `local` are mutually exclusive",
|
"`cli_only` and `local` are mutually exclusive",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
ExecutionContext::CustomCli { .. } => {
|
||||||
|
return Err(Error::new(
|
||||||
|
p.span(),
|
||||||
|
"`cli_only` and `custom_cli` are mutually exclusive",
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("cli_only") => {
|
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("cli_only") => {
|
||||||
@@ -204,6 +277,12 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result<Options> {
|
|||||||
"`rpc_only` and `local` are mutually exclusive",
|
"`rpc_only` and `local` are mutually exclusive",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
ExecutionContext::CustomCli { .. } => {
|
||||||
|
return Err(Error::new(
|
||||||
|
p.span(),
|
||||||
|
"`rpc_only` and `custom_cli` are mutually exclusive",
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("rpc_only") => {
|
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("rpc_only") => {
|
||||||
@@ -238,6 +317,12 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result<Options> {
|
|||||||
"`local` and `cli_only` are mutually exclusive",
|
"`local` and `cli_only` are mutually exclusive",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
ExecutionContext::CustomCli { .. } => {
|
||||||
|
return Err(Error::new(
|
||||||
|
p.span(),
|
||||||
|
"`local` and `custom_cli` are mutually exclusive",
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("local") => {
|
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("local") => {
|
||||||
|
|||||||
Reference in New Issue
Block a user