mirror of
https://github.com/Start9Labs/rpc-toolkit.git
synced 2026-03-26 02:11:56 +00:00
wip
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1033,6 +1033,7 @@ dependencies = [
|
|||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper 1.0.1",
|
"hyper 1.0.1",
|
||||||
"imbl-value",
|
"imbl-value",
|
||||||
|
"itertools",
|
||||||
"lazy_format",
|
"lazy_format",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"openssl",
|
"openssl",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ futures = "0.3"
|
|||||||
http = "1"
|
http = "1"
|
||||||
http-body-util = "0.1"
|
http-body-util = "0.1"
|
||||||
hyper = { version = "1", features = ["server", "http1", "http2", "client"] }
|
hyper = { version = "1", features = ["server", "http1", "http2", "client"] }
|
||||||
|
itertools = "0.12"
|
||||||
imbl-value = "0.1"
|
imbl-value = "0.1"
|
||||||
lazy_format = "2"
|
lazy_format = "2"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
|||||||
@@ -165,11 +165,11 @@ pub async fn call_remote_socket(
|
|||||||
.result
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CallRemoteHandler<RemoteContext, RemoteHandler> {
|
pub struct CallRemoteHandler<Context, RemoteHandler> {
|
||||||
_phantom: PhantomData<RemoteContext>,
|
_phantom: PhantomData<Context>,
|
||||||
handler: RemoteHandler,
|
handler: RemoteHandler,
|
||||||
}
|
}
|
||||||
impl<RemoteContext, RemoteHandler> CallRemoteHandler<RemoteContext, RemoteHandler> {
|
impl<Context, RemoteHandler> CallRemoteHandler<Context, RemoteHandler> {
|
||||||
pub fn new(handler: RemoteHandler) -> Self {
|
pub fn new(handler: RemoteHandler) -> Self {
|
||||||
Self {
|
Self {
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
@@ -177,9 +177,7 @@ impl<RemoteContext, RemoteHandler> CallRemoteHandler<RemoteContext, RemoteHandle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<RemoteContext, RemoteHandler: Clone> Clone
|
impl<Context, RemoteHandler: Clone> Clone for CallRemoteHandler<Context, RemoteHandler> {
|
||||||
for CallRemoteHandler<RemoteContext, RemoteHandler>
|
|
||||||
{
|
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
@@ -187,17 +185,14 @@ impl<RemoteContext, RemoteHandler: Clone> Clone
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<RemoteContext, RemoteHandler> std::fmt::Debug
|
impl<Context, RemoteHandler> std::fmt::Debug for CallRemoteHandler<Context, RemoteHandler> {
|
||||||
for CallRemoteHandler<RemoteContext, RemoteHandler>
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_tuple("CallRemoteHandler").finish()
|
f.debug_tuple("CallRemoteHandler").finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<RemoteContext, RemoteHandler> HandlerTypes for CallRemoteHandler<RemoteContext, RemoteHandler>
|
impl<Context, RemoteHandler> HandlerTypes for CallRemoteHandler<Context, RemoteHandler>
|
||||||
where
|
where
|
||||||
RemoteContext: IntoContext,
|
|
||||||
RemoteHandler: HandlerTypes,
|
RemoteHandler: HandlerTypes,
|
||||||
RemoteHandler::Params: Serialize,
|
RemoteHandler::Params: Serialize,
|
||||||
RemoteHandler::InheritedParams: Serialize,
|
RemoteHandler::InheritedParams: Serialize,
|
||||||
@@ -210,16 +205,15 @@ where
|
|||||||
type Err = RemoteHandler::Err;
|
type Err = RemoteHandler::Err;
|
||||||
}
|
}
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl<Context: CallRemote, RemoteContext, RemoteHandler> Handler<Context>
|
impl<Context: CallRemote, RemoteHandler> Handler for CallRemoteHandler<Context, RemoteHandler>
|
||||||
for CallRemoteHandler<RemoteContext, RemoteHandler>
|
|
||||||
where
|
where
|
||||||
RemoteContext: IntoContext,
|
RemoteHandler: Handler,
|
||||||
RemoteHandler: Handler<RemoteContext>,
|
|
||||||
RemoteHandler::Params: Serialize,
|
RemoteHandler::Params: Serialize,
|
||||||
RemoteHandler::InheritedParams: Serialize,
|
RemoteHandler::InheritedParams: Serialize,
|
||||||
RemoteHandler::Ok: DeserializeOwned,
|
RemoteHandler::Ok: DeserializeOwned,
|
||||||
RemoteHandler::Err: From<RpcError>,
|
RemoteHandler::Err: From<RpcError>,
|
||||||
{
|
{
|
||||||
|
type Context = Context;
|
||||||
async fn handle_async(
|
async fn handle_async(
|
||||||
&self,
|
&self,
|
||||||
handle_args: HandleArgs<Context, Self>,
|
handle_args: HandleArgs<Context, Self>,
|
||||||
@@ -245,17 +239,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #[async_trait::async_trait]
|
impl<Context: CallRemote, RemoteHandler> CliBindings for CallRemoteHandler<Context, RemoteHandler>
|
||||||
impl<Context: CallRemote, RemoteContext, RemoteHandler> CliBindings<Context>
|
|
||||||
for CallRemoteHandler<RemoteContext, RemoteHandler>
|
|
||||||
where
|
where
|
||||||
RemoteContext: IntoContext,
|
RemoteHandler: Handler + CliBindings<Context = Context>,
|
||||||
RemoteHandler: Handler<RemoteContext> + CliBindings<Context>,
|
|
||||||
RemoteHandler::Params: Serialize,
|
RemoteHandler::Params: Serialize,
|
||||||
RemoteHandler::InheritedParams: Serialize,
|
RemoteHandler::InheritedParams: Serialize,
|
||||||
RemoteHandler::Ok: DeserializeOwned,
|
RemoteHandler::Ok: DeserializeOwned,
|
||||||
RemoteHandler::Err: From<RpcError>,
|
RemoteHandler::Err: From<RpcError>,
|
||||||
{
|
{
|
||||||
|
type Context = Context;
|
||||||
fn cli_command(&self, ctx_ty: TypeId) -> clap::Command {
|
fn cli_command(&self, ctx_ty: TypeId) -> clap::Command {
|
||||||
self.handler.cli_command(ctx_ty)
|
self.handler.cli_command(ctx_ty)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use std::any::{Any, TypeId};
|
use std::any::{Any, TypeId};
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
|
use imbl_value::imbl::OrdSet;
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
|
|
||||||
use crate::Handler;
|
|
||||||
|
|
||||||
pub trait Context: Any + Send + Sync + 'static {
|
pub trait Context: Any + Send + Sync + 'static {
|
||||||
fn inner_type_id(&self) -> TypeId {
|
fn inner_type_id(&self) -> TypeId {
|
||||||
<Self as Any>::type_id(&self)
|
<Self as Any>::type_id(&self)
|
||||||
@@ -17,7 +15,7 @@ pub trait Context: Any + Send + Sync + 'static {
|
|||||||
#[allow(private_bounds)]
|
#[allow(private_bounds)]
|
||||||
pub trait IntoContext: sealed::Sealed + Any + Send + Sync + Sized + 'static {
|
pub trait IntoContext: sealed::Sealed + Any + Send + Sync + Sized + 'static {
|
||||||
fn runtime(&self) -> Handle;
|
fn runtime(&self) -> Handle;
|
||||||
fn type_ids_for<H: Handler<Self> + ?Sized>(handler: &H) -> Option<BTreeSet<TypeId>>;
|
fn type_ids() -> Option<OrdSet<TypeId>>;
|
||||||
fn inner_type_id(&self) -> TypeId;
|
fn inner_type_id(&self) -> TypeId;
|
||||||
fn upcast(self) -> AnyContext;
|
fn upcast(self) -> AnyContext;
|
||||||
fn downcast(value: AnyContext) -> Result<Self, AnyContext>;
|
fn downcast(value: AnyContext) -> Result<Self, AnyContext>;
|
||||||
@@ -27,8 +25,8 @@ impl<C: Context + Sized> IntoContext for C {
|
|||||||
fn runtime(&self) -> Handle {
|
fn runtime(&self) -> Handle {
|
||||||
<C as Context>::runtime(&self)
|
<C as Context>::runtime(&self)
|
||||||
}
|
}
|
||||||
fn type_ids_for<H: Handler<Self> + ?Sized>(_: &H) -> Option<BTreeSet<TypeId>> {
|
fn type_ids() -> Option<OrdSet<TypeId>> {
|
||||||
let mut set = BTreeSet::new();
|
let mut set = OrdSet::new();
|
||||||
set.insert(TypeId::of::<C>());
|
set.insert(TypeId::of::<C>());
|
||||||
Some(set)
|
Some(set)
|
||||||
}
|
}
|
||||||
@@ -51,38 +49,38 @@ pub enum EitherContext<C1, C2> {
|
|||||||
C1(C1),
|
C1(C1),
|
||||||
C2(C2),
|
C2(C2),
|
||||||
}
|
}
|
||||||
impl<C1: Context, C2: Context> IntoContext for EitherContext<C1, C2> {
|
impl<C1: IntoContext, C2: IntoContext> IntoContext for EitherContext<C1, C2> {
|
||||||
fn runtime(&self) -> Handle {
|
fn runtime(&self) -> Handle {
|
||||||
match self {
|
match self {
|
||||||
Self::C1(a) => a.runtime(),
|
Self::C1(a) => a.runtime(),
|
||||||
Self::C2(a) => a.runtime(),
|
Self::C2(a) => a.runtime(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn type_ids_for<H: Handler<Self> + ?Sized>(_: &H) -> Option<BTreeSet<TypeId>> {
|
fn type_ids() -> Option<OrdSet<TypeId>> {
|
||||||
let mut set = BTreeSet::new();
|
let mut set = OrdSet::new();
|
||||||
set.insert(TypeId::of::<C1>());
|
set.extend(C1::type_ids()?);
|
||||||
set.insert(TypeId::of::<C2>());
|
set.extend(C2::type_ids()?);
|
||||||
Some(set)
|
Some(set)
|
||||||
}
|
}
|
||||||
fn inner_type_id(&self) -> TypeId {
|
fn inner_type_id(&self) -> TypeId {
|
||||||
match self {
|
match self {
|
||||||
EitherContext::C1(c) => c.type_id(),
|
EitherContext::C1(c) => c.inner_type_id(),
|
||||||
EitherContext::C2(c) => c.type_id(),
|
EitherContext::C2(c) => c.inner_type_id(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn downcast(value: AnyContext) -> Result<Self, AnyContext> {
|
fn downcast(value: AnyContext) -> Result<Self, AnyContext> {
|
||||||
if value.inner_type_id() == TypeId::of::<C1>() {
|
match C1::downcast(value) {
|
||||||
Ok(EitherContext::C1(C1::downcast(value)?))
|
Ok(a) => Ok(EitherContext::C1(a)),
|
||||||
} else if value.inner_type_id() == TypeId::of::<C2>() {
|
Err(value) => match C2::downcast(value) {
|
||||||
Ok(EitherContext::C2(C2::downcast(value)?))
|
Ok(a) => Ok(EitherContext::C2(a)),
|
||||||
} else {
|
Err(value) => Err(value),
|
||||||
Err(value)
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn upcast(self) -> AnyContext {
|
fn upcast(self) -> AnyContext {
|
||||||
match self {
|
match self {
|
||||||
Self::C1(c) => AnyContext::new(c),
|
Self::C1(c) => c.upcast(),
|
||||||
Self::C2(c) => AnyContext::new(c),
|
Self::C2(c) => c.upcast(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +100,7 @@ impl IntoContext for AnyContext {
|
|||||||
fn runtime(&self) -> Handle {
|
fn runtime(&self) -> Handle {
|
||||||
self.0.runtime()
|
self.0.runtime()
|
||||||
}
|
}
|
||||||
fn type_ids_for<H: Handler<Self> + ?Sized>(_: &H) -> Option<BTreeSet<TypeId>> {
|
fn type_ids() -> Option<OrdSet<TypeId>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn inner_type_id(&self) -> TypeId {
|
fn inner_type_id(&self) -> TypeId {
|
||||||
@@ -119,6 +117,6 @@ impl IntoContext for AnyContext {
|
|||||||
mod sealed {
|
mod sealed {
|
||||||
pub(crate) trait Sealed {}
|
pub(crate) trait Sealed {}
|
||||||
impl<C: super::Context> Sealed for C {}
|
impl<C: super::Context> Sealed for C {}
|
||||||
impl<C1: super::Context, C2: super::Context> Sealed for super::EitherContext<C1, C2> {}
|
impl<C1: super::IntoContext, C2: super::IntoContext> Sealed for super::EitherContext<C1, C2> {}
|
||||||
impl Sealed for super::AnyContext {}
|
impl Sealed for super::AnyContext {}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
485
rpc-toolkit/src/handler/adapters.rs
Normal file
485
rpc-toolkit/src/handler/adapters.rs
Normal file
@@ -0,0 +1,485 @@
|
|||||||
|
use std::any::TypeId;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::task::Context;
|
||||||
|
|
||||||
|
use clap::{CommandFactory, FromArgMatches};
|
||||||
|
use imbl_value::imbl::{OrdMap, OrdSet};
|
||||||
|
use imbl_value::Value;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde::Serialize;
|
||||||
|
use yajrc::RpcError;
|
||||||
|
|
||||||
|
use crate::util::{internal_error, parse_error, Flat};
|
||||||
|
use crate::{
|
||||||
|
intersect_type_ids, iter_from_ctx_and_handler, AnyHandler, CallRemote, CliBindings, DynHandler,
|
||||||
|
HandleArgs, Handler, HandlerTypes, IntoContext, IntoHandlers, NoParams, PrintCliResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait HandlerExt: HandlerTypes + Sized {
|
||||||
|
fn no_cli(self) -> NoCli<Self>;
|
||||||
|
fn with_custom_display<P>(self, display: P) -> CustomDisplay<P, Self>
|
||||||
|
where
|
||||||
|
P: PrintCliResult<
|
||||||
|
Params = Self::Params,
|
||||||
|
InheritedParams = Self::InheritedParams,
|
||||||
|
Ok = Self::Ok,
|
||||||
|
Err = Self::Err,
|
||||||
|
>;
|
||||||
|
fn with_custom_display_fn<Context: IntoContext, F>(
|
||||||
|
self,
|
||||||
|
display: F,
|
||||||
|
) -> CustomDisplayFn<Context, F, Self>
|
||||||
|
where
|
||||||
|
F: Fn(HandleArgs<Context, Self>, Self::Ok) -> Result<(), Self::Err>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: HandlerTypes + Sized> HandlerExt for T {
|
||||||
|
fn no_cli(self) -> NoCli<Self> {
|
||||||
|
NoCli(self)
|
||||||
|
}
|
||||||
|
fn with_custom_display<P>(self, display: P) -> CustomDisplay<P, Self>
|
||||||
|
where
|
||||||
|
P: PrintCliResult<
|
||||||
|
Params = Self::Params,
|
||||||
|
InheritedParams = Self::InheritedParams,
|
||||||
|
Ok = Self::Ok,
|
||||||
|
Err = Self::Err,
|
||||||
|
>,
|
||||||
|
{
|
||||||
|
CustomDisplay {
|
||||||
|
print: display,
|
||||||
|
handler: self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn with_custom_display_fn<Context: IntoContext, F>(
|
||||||
|
self,
|
||||||
|
display: F,
|
||||||
|
) -> CustomDisplayFn<Context, F, Self>
|
||||||
|
where
|
||||||
|
F: Fn(HandleArgs<Context, Self>, Self::Ok) -> Result<(), Self::Err>,
|
||||||
|
{
|
||||||
|
CustomDisplayFn {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
print: display,
|
||||||
|
handler: self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct NoCli<H>(pub H);
|
||||||
|
impl<H: HandlerTypes> HandlerTypes for NoCli<H> {
|
||||||
|
type Params = H::Params;
|
||||||
|
type InheritedParams = H::InheritedParams;
|
||||||
|
type Ok = H::Ok;
|
||||||
|
type Err = H::Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct CustomDisplay<P, H> {
|
||||||
|
print: P,
|
||||||
|
handler: H,
|
||||||
|
}
|
||||||
|
impl<P, H> HandlerTypes for CustomDisplay<P, H>
|
||||||
|
where
|
||||||
|
H: HandlerTypes,
|
||||||
|
{
|
||||||
|
type Params = H::Params;
|
||||||
|
type InheritedParams = H::InheritedParams;
|
||||||
|
type Ok = H::Ok;
|
||||||
|
type Err = H::Err;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<P, H> Handler for CustomDisplay<P, H>
|
||||||
|
where
|
||||||
|
H: Handler,
|
||||||
|
P: Send + Sync + Clone + Debug + 'static,
|
||||||
|
{
|
||||||
|
type Context = H::Context;
|
||||||
|
fn handle_sync(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
self.handler.handle_sync(HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
self.handler
|
||||||
|
.handle_async(HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
fn metadata(
|
||||||
|
&self,
|
||||||
|
method: VecDeque<&'static str>,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> OrdMap<&'static str, Value> {
|
||||||
|
self.handler.metadata(method, ctx_ty)
|
||||||
|
}
|
||||||
|
fn contexts(&self) -> Option<OrdSet<TypeId>> {
|
||||||
|
self.handler.contexts()
|
||||||
|
}
|
||||||
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
self.handler.method_from_dots(method, ctx_ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<P, H> CliBindings for CustomDisplay<P, H>
|
||||||
|
where
|
||||||
|
H: HandlerTypes,
|
||||||
|
H::Params: FromArgMatches + CommandFactory + Serialize,
|
||||||
|
P: PrintCliResult<
|
||||||
|
Params = H::Params,
|
||||||
|
InheritedParams = H::InheritedParams,
|
||||||
|
Ok = H::Ok,
|
||||||
|
Err = H::Err,
|
||||||
|
> + Send
|
||||||
|
+ Sync
|
||||||
|
+ Clone
|
||||||
|
+ Debug
|
||||||
|
+ 'static,
|
||||||
|
{
|
||||||
|
type Context = P::Context;
|
||||||
|
fn cli_command(&self, ctx_ty: TypeId) -> clap::Command {
|
||||||
|
H::Params::command()
|
||||||
|
}
|
||||||
|
fn cli_parse(
|
||||||
|
&self,
|
||||||
|
matches: &clap::ArgMatches,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
||||||
|
Self::Params::from_arg_matches(matches).and_then(|a| {
|
||||||
|
Ok((
|
||||||
|
VecDeque::new(),
|
||||||
|
imbl_value::to_value(&a)
|
||||||
|
.map_err(|e| clap::Error::raw(clap::error::ErrorKind::ValueValidation, e))?,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn cli_display(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Self::Context, Self>,
|
||||||
|
result: Self::Ok,
|
||||||
|
) -> Result<(), Self::Err> {
|
||||||
|
self.print.print(
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
},
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<P, H> IntoHandlers for CustomDisplay<P, H>
|
||||||
|
where
|
||||||
|
Self: HandlerTypes + Handler + CliBindings,
|
||||||
|
<Self as HandlerTypes>::Params: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::InheritedParams: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::Ok: Serialize + DeserializeOwned,
|
||||||
|
RpcError: From<<Self as HandlerTypes>::Err>,
|
||||||
|
{
|
||||||
|
fn into_handlers(self) -> impl IntoIterator<Item = (Option<TypeId>, crate::DynHandler)> {
|
||||||
|
iter_from_ctx_and_handler(
|
||||||
|
intersect_type_ids(self.contexts(), <Self as CliBindings>::Context::type_ids()),
|
||||||
|
DynHandler::WithCli(Arc::new(AnyHandler::new(self))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CustomDisplayFn<Context, F, H> {
|
||||||
|
_phantom: PhantomData<Context>,
|
||||||
|
print: F,
|
||||||
|
handler: H,
|
||||||
|
}
|
||||||
|
impl<Context, F: Clone, H: Clone> Clone for CustomDisplayFn<Context, F, H> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
print: self.print.clone(),
|
||||||
|
handler: self.handler.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Context, F: Debug, H: Debug> Debug for CustomDisplayFn<Context, F, H> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("CustomDisplayFn")
|
||||||
|
.field("print", &self.print)
|
||||||
|
.field("handler", &self.handler)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Context, F, H> HandlerTypes for CustomDisplayFn<Context, F, H>
|
||||||
|
where
|
||||||
|
H: HandlerTypes,
|
||||||
|
{
|
||||||
|
type Params = H::Params;
|
||||||
|
type InheritedParams = H::InheritedParams;
|
||||||
|
type Ok = H::Ok;
|
||||||
|
type Err = H::Err;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, H> Handler for CustomDisplayFn<Context, F, H>
|
||||||
|
where
|
||||||
|
Context: Send + Sync + 'static,
|
||||||
|
H: Handler,
|
||||||
|
F: Send + Sync + Clone + Debug + 'static,
|
||||||
|
{
|
||||||
|
type Context = H::Context;
|
||||||
|
fn handle_sync(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
self.handler.handle_sync(HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
self.handler
|
||||||
|
.handle_async(HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
fn metadata(
|
||||||
|
&self,
|
||||||
|
method: VecDeque<&'static str>,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> OrdMap<&'static str, Value> {
|
||||||
|
self.handler.metadata(method, ctx_ty)
|
||||||
|
}
|
||||||
|
fn contexts(&self) -> Option<OrdSet<TypeId>> {
|
||||||
|
self.handler.contexts()
|
||||||
|
}
|
||||||
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
self.handler.method_from_dots(method, ctx_ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Context, F, H> CliBindings for CustomDisplayFn<Context, F, H>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
H: CliBindings,
|
||||||
|
F: Fn(HandleArgs<Context, H>, H::Ok) -> Result<(), H::Err>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ Clone
|
||||||
|
+ Debug
|
||||||
|
+ 'static,
|
||||||
|
{
|
||||||
|
type Context = Context;
|
||||||
|
fn cli_command(&self, ctx_ty: TypeId) -> clap::Command {
|
||||||
|
self.handler.cli_command(ctx_ty)
|
||||||
|
}
|
||||||
|
fn cli_parse(
|
||||||
|
&self,
|
||||||
|
matches: &clap::ArgMatches,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
||||||
|
self.handler.cli_parse(matches, ctx_ty)
|
||||||
|
}
|
||||||
|
fn cli_display(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Context, Self>,
|
||||||
|
result: Self::Ok,
|
||||||
|
) -> Result<(), Self::Err> {
|
||||||
|
(self.print)(
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
},
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub struct RemoteCli<CliContext, RemoteContext, H> {
|
||||||
|
// _phantom: PhantomData<(CliContext, RemoteContext)>,
|
||||||
|
// handler: H,
|
||||||
|
// }
|
||||||
|
// impl<CliContext, RemoteContext, H: Clone> Clone for RemoteCli<CliContext, RemoteContext, H> {
|
||||||
|
// fn clone(&self) -> Self {
|
||||||
|
// Self {
|
||||||
|
// _phantom: PhantomData,
|
||||||
|
// handler: self.handler.clone(),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl<CliContext, RemoteContext, H: Debug> Debug for RemoteCli<CliContext, RemoteContext, H> {
|
||||||
|
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
// f.debug_tuple("RemoteCli").field(&self.handler).finish()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl<CliContext, RemoteContext, H> HandlerTypes for RemoteCli<CliContext, RemoteContext, H>
|
||||||
|
// where
|
||||||
|
// H: HandlerTypes,
|
||||||
|
// {
|
||||||
|
// type Params = H::Params;
|
||||||
|
// type InheritedParams = H::InheritedParams;
|
||||||
|
// type Ok = H::Ok;
|
||||||
|
// type Err = H::Err;
|
||||||
|
// }
|
||||||
|
// #[async_trait::async_trait]
|
||||||
|
// impl<CliContext, RemoteContext, H> Handler<EitherContext<CliContext, RemoteContext>>
|
||||||
|
// for RemoteCli<CliContext, RemoteContext, H>
|
||||||
|
// where
|
||||||
|
// CliContext: CallRemote,
|
||||||
|
// H: Handler<RemoteContext>,
|
||||||
|
// {
|
||||||
|
// async fn handle_async(
|
||||||
|
// &self,
|
||||||
|
// HandleArgs {
|
||||||
|
// context,
|
||||||
|
// parent_method,
|
||||||
|
// method,
|
||||||
|
// params,
|
||||||
|
// inherited_params,
|
||||||
|
// raw_params,
|
||||||
|
// }: HandleArgs<CliContext, Self>,
|
||||||
|
// ) -> Result<Self::Ok, Self::Err> {
|
||||||
|
// let full_method = parent_method.into_iter().chain(method).collect::<Vec<_>>();
|
||||||
|
// match context
|
||||||
|
// .call_remote(
|
||||||
|
// &full_method.join("."),
|
||||||
|
// imbl_value::to_value(&Flat(params, inherited_params)).map_err(parse_error)?,
|
||||||
|
// )
|
||||||
|
// .await
|
||||||
|
// {
|
||||||
|
// Ok(a) => imbl_value::from_value(a)
|
||||||
|
// .map_err(internal_error)
|
||||||
|
// .map_err(Self::Err::from),
|
||||||
|
// Err(e) => Err(Self::Err::from(e)),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fn metadata(
|
||||||
|
// &self,
|
||||||
|
// method: VecDeque<&'static str>,
|
||||||
|
// ctx_ty: TypeId,
|
||||||
|
// ) -> OrdMap<&'static str, Value> {
|
||||||
|
// self.handler.metadata(method, ctx_ty)
|
||||||
|
// }
|
||||||
|
// fn contexts(&self) -> Option<OrdSet<TypeId>> {
|
||||||
|
// todo!()
|
||||||
|
// }
|
||||||
|
// fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
// self.handler.method_from_dots(method, ctx_ty)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl<Context, H> CliBindings<Context> for RemoteCli<Context, H>
|
||||||
|
// where
|
||||||
|
// Context: crate::Context,
|
||||||
|
// H: CliBindings<Context>,
|
||||||
|
// {
|
||||||
|
// fn cli_command(&self, ctx_ty: TypeId) -> clap::Command {
|
||||||
|
// self.handler.cli_command(ctx_ty)
|
||||||
|
// }
|
||||||
|
// fn cli_parse(
|
||||||
|
// &self,
|
||||||
|
// matches: &clap::ArgMatches,
|
||||||
|
// ctx_ty: TypeId,
|
||||||
|
// ) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
||||||
|
// self.handler.cli_parse(matches, ctx_ty)
|
||||||
|
// }
|
||||||
|
// fn cli_display(
|
||||||
|
// &self,
|
||||||
|
// HandleArgs {
|
||||||
|
// context,
|
||||||
|
// parent_method,
|
||||||
|
// method,
|
||||||
|
// params,
|
||||||
|
// inherited_params,
|
||||||
|
// raw_params,
|
||||||
|
// }: HandleArgs<Context, Self>,
|
||||||
|
// result: Self::Ok,
|
||||||
|
// ) -> Result<(), Self::Err> {
|
||||||
|
// self.handler.cli_display(
|
||||||
|
// HandleArgs {
|
||||||
|
// context,
|
||||||
|
// parent_method,
|
||||||
|
// method,
|
||||||
|
// params,
|
||||||
|
// inherited_params,
|
||||||
|
// raw_params,
|
||||||
|
// },
|
||||||
|
// result,
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
601
rpc-toolkit/src/handler/from_fn.rs
Normal file
601
rpc-toolkit/src/handler/from_fn.rs
Normal file
@@ -0,0 +1,601 @@
|
|||||||
|
use std::any::TypeId;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use clap::{ArgMatches, Command, CommandFactory, FromArgMatches};
|
||||||
|
use futures::Future;
|
||||||
|
use imbl_value::imbl::OrdMap;
|
||||||
|
use imbl_value::Value;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde::Serialize;
|
||||||
|
use yajrc::RpcError;
|
||||||
|
|
||||||
|
use crate::marker::LeafHandler;
|
||||||
|
use crate::{
|
||||||
|
intersect_type_ids, iter_from_ctx_and_handler, AnyContext, AnyHandler, CliBindings, DynHandler,
|
||||||
|
HandleArgs, Handler, HandlerTypes, IntoContext, IntoHandlers, NoCli, NoParams, PrintCliResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct FromFn<F, T, E, Args> {
|
||||||
|
_phantom: PhantomData<(T, E, Args)>,
|
||||||
|
function: F,
|
||||||
|
blocking: bool,
|
||||||
|
metadata: OrdMap<&'static str, Value>,
|
||||||
|
}
|
||||||
|
impl<F, T, E, Args> FromFn<F, T, E, Args> {
|
||||||
|
pub fn with_metadata(mut self, key: &'static str, value: Value) -> Self {
|
||||||
|
self.metadata.insert(key, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<F: Clone, T, E, Args> Clone for FromFn<F, T, E, Args> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
function: self.function.clone(),
|
||||||
|
blocking: self.blocking,
|
||||||
|
metadata: self.metadata.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<F, T, E, Args> std::fmt::Debug for FromFn<F, T, E, Args> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("FromFn")
|
||||||
|
.field("blocking", &self.blocking)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<F, T, E, Args> LeafHandler for FromFn<F, T, E, Args> {}
|
||||||
|
impl<F, T, E, Args> PrintCliResult for FromFn<F, T, E, Args>
|
||||||
|
where
|
||||||
|
Self: HandlerTypes,
|
||||||
|
<Self as HandlerTypes>::Ok: Display,
|
||||||
|
{
|
||||||
|
type Context = AnyContext;
|
||||||
|
fn print(&self, _: HandleArgs<Self::Context, Self>, result: Self::Ok) -> Result<(), Self::Err> {
|
||||||
|
Ok(println!("{result}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<F, T, E, Args> IntoHandlers for FromFn<F, T, E, Args>
|
||||||
|
where
|
||||||
|
Self: HandlerTypes + Handler + CliBindings,
|
||||||
|
<Self as HandlerTypes>::Params: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::InheritedParams: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::Ok: Serialize + DeserializeOwned,
|
||||||
|
RpcError: From<<Self as HandlerTypes>::Err>,
|
||||||
|
{
|
||||||
|
fn into_handlers(self) -> impl IntoIterator<Item = (Option<TypeId>, crate::DynHandler)> {
|
||||||
|
iter_from_ctx_and_handler(
|
||||||
|
intersect_type_ids(self.contexts(), <Self as CliBindings>::Context::type_ids()),
|
||||||
|
DynHandler::WithCli(Arc::new(AnyHandler::new(self))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<F, T, E, Args> IntoHandlers for NoCli<FromFn<F, T, E, Args>>
|
||||||
|
where
|
||||||
|
Self: HandlerTypes + Handler,
|
||||||
|
<Self as HandlerTypes>::Params: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::InheritedParams: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::Ok: Serialize + DeserializeOwned,
|
||||||
|
RpcError: From<<Self as HandlerTypes>::Err>,
|
||||||
|
{
|
||||||
|
fn into_handlers(self) -> impl IntoIterator<Item = (Option<TypeId>, crate::DynHandler)> {
|
||||||
|
iter_from_ctx_and_handler(
|
||||||
|
self.contexts(),
|
||||||
|
DynHandler::WithoutCli(Arc::new(AnyHandler::new(self))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_fn<F, T, E, Args>(function: F) -> FromFn<F, T, E, Args> {
|
||||||
|
FromFn {
|
||||||
|
function,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
blocking: false,
|
||||||
|
metadata: OrdMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_fn_blocking<F, T, E, Args>(function: F) -> FromFn<F, T, E, Args> {
|
||||||
|
FromFn {
|
||||||
|
function,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
blocking: true,
|
||||||
|
metadata: OrdMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FromFnAsync<F, Fut, T, E, Args> {
|
||||||
|
_phantom: PhantomData<(Fut, T, E, Args)>,
|
||||||
|
function: F,
|
||||||
|
metadata: OrdMap<&'static str, Value>,
|
||||||
|
}
|
||||||
|
impl<F: Clone, Fut, T, E, Args> Clone for FromFnAsync<F, Fut, T, E, Args> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
function: self.function.clone(),
|
||||||
|
metadata: self.metadata.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<F, Fut, T, E, Args> std::fmt::Debug for FromFnAsync<F, Fut, T, E, Args> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("FromFnAsync").finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<F, Fut, T, E, Args> PrintCliResult for FromFnAsync<F, Fut, T, E, Args>
|
||||||
|
where
|
||||||
|
Self: HandlerTypes,
|
||||||
|
<Self as HandlerTypes>::Ok: Display,
|
||||||
|
{
|
||||||
|
type Context = AnyContext;
|
||||||
|
fn print(&self, _: HandleArgs<Self::Context, Self>, result: Self::Ok) -> Result<(), Self::Err> {
|
||||||
|
Ok(println!("{result}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<F, Fut, T, E, Args> IntoHandlers for FromFnAsync<F, Fut, T, E, Args>
|
||||||
|
where
|
||||||
|
Self: HandlerTypes + Handler + CliBindings,
|
||||||
|
<Self as HandlerTypes>::Params: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::InheritedParams: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::Ok: Serialize + DeserializeOwned,
|
||||||
|
RpcError: From<<Self as HandlerTypes>::Err>,
|
||||||
|
{
|
||||||
|
fn into_handlers(self) -> impl IntoIterator<Item = (Option<TypeId>, crate::DynHandler)> {
|
||||||
|
iter_from_ctx_and_handler(
|
||||||
|
intersect_type_ids(self.contexts(), <Self as CliBindings>::Context::type_ids()),
|
||||||
|
DynHandler::WithCli(Arc::new(AnyHandler::new(self))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<F, Fut, T, E, Args> IntoHandlers for NoCli<FromFnAsync<F, Fut, T, E, Args>>
|
||||||
|
where
|
||||||
|
Self: HandlerTypes + Handler,
|
||||||
|
<Self as HandlerTypes>::Params: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::InheritedParams: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::Ok: Serialize + DeserializeOwned,
|
||||||
|
RpcError: From<<Self as HandlerTypes>::Err>,
|
||||||
|
{
|
||||||
|
fn into_handlers(self) -> impl IntoIterator<Item = (Option<TypeId>, crate::DynHandler)> {
|
||||||
|
iter_from_ctx_and_handler(
|
||||||
|
self.contexts(),
|
||||||
|
DynHandler::WithoutCli(Arc::new(AnyHandler::new(self))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_fn_async<F, Fut, T, E, Args>(function: F) -> FromFnAsync<F, Fut, T, E, Args> {
|
||||||
|
FromFnAsync {
|
||||||
|
function,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
metadata: OrdMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, T, E> HandlerTypes for FromFn<F, T, E, ()>
|
||||||
|
where
|
||||||
|
F: Fn() -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Params = NoParams;
|
||||||
|
type InheritedParams = NoParams;
|
||||||
|
type Ok = T;
|
||||||
|
type Err = E;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<F, T, E> Handler for FromFn<F, T, E, ()>
|
||||||
|
where
|
||||||
|
F: Fn() -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Context = AnyContext;
|
||||||
|
fn handle_sync(&self, _: HandleArgs<Self::Context, Self>) -> Result<Self::Ok, Self::Err> {
|
||||||
|
(self.function)()
|
||||||
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
if self.blocking {
|
||||||
|
self.handle_async_with_sync_blocking(handle_args).await
|
||||||
|
} else {
|
||||||
|
self.handle_async_with_sync(handle_args).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn metadata(&self, _: VecDeque<&'static str>, _: TypeId) -> OrdMap<&'static str, Value> {
|
||||||
|
self.metadata.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<F, Fut, T, E> HandlerTypes for FromFnAsync<F, Fut, T, E, ()>
|
||||||
|
where
|
||||||
|
F: Fn() -> Fut + Send + Sync + Clone + 'static,
|
||||||
|
Fut: Future<Output = Result<T, E>> + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Params = NoParams;
|
||||||
|
type InheritedParams = NoParams;
|
||||||
|
type Ok = T;
|
||||||
|
type Err = E;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<F, Fut, T, E> Handler for FromFnAsync<F, Fut, T, E, ()>
|
||||||
|
where
|
||||||
|
F: Fn() -> Fut + Send + Sync + Clone + 'static,
|
||||||
|
Fut: Future<Output = Result<T, E>> + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Context = AnyContext;
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
_: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
(self.function)().await
|
||||||
|
}
|
||||||
|
fn metadata(&self, _: VecDeque<&'static str>, _: TypeId) -> OrdMap<&'static str, Value> {
|
||||||
|
self.metadata.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Context, F, T, E> HandlerTypes for FromFn<F, T, E, (Context,)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context) -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Params = NoParams;
|
||||||
|
type InheritedParams = NoParams;
|
||||||
|
type Ok = T;
|
||||||
|
type Err = E;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, T, E> Handler for FromFn<F, T, E, (Context,)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context) -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Context = Context;
|
||||||
|
fn handle_sync(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
(self.function)(handle_args.context)
|
||||||
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
if self.blocking {
|
||||||
|
self.handle_async_with_sync_blocking(handle_args).await
|
||||||
|
} else {
|
||||||
|
self.handle_async_with_sync(handle_args).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn metadata(&self, _: VecDeque<&'static str>, _: TypeId) -> OrdMap<&'static str, Value> {
|
||||||
|
self.metadata.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Context, F, Fut, T, E> HandlerTypes for FromFnAsync<F, Fut, T, E, (Context,)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context) -> Fut + Send + Sync + Clone + 'static,
|
||||||
|
Fut: Future<Output = Result<T, E>> + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Params = NoParams;
|
||||||
|
type InheritedParams = NoParams;
|
||||||
|
type Ok = T;
|
||||||
|
type Err = E;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, Fut, T, E> Handler for FromFnAsync<F, Fut, T, E, (Context,)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context) -> Fut + Send + Sync + Clone + 'static,
|
||||||
|
Fut: Future<Output = Result<T, E>> + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Context = Context;
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
(self.function)(handle_args.context).await
|
||||||
|
}
|
||||||
|
fn metadata(&self, _: VecDeque<&'static str>, _: TypeId) -> OrdMap<&'static str, Value> {
|
||||||
|
self.metadata.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Context, F, T, E, Params> HandlerTypes for FromFn<F, T, E, (Context, Params)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context, Params) -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Params = Params;
|
||||||
|
type InheritedParams = NoParams;
|
||||||
|
type Ok = T;
|
||||||
|
type Err = E;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, T, E, Params> Handler for FromFn<F, T, E, (Context, Params)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context, Params) -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Context = Context;
|
||||||
|
fn handle_sync(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
let HandleArgs {
|
||||||
|
context, params, ..
|
||||||
|
} = handle_args;
|
||||||
|
(self.function)(context, params)
|
||||||
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
if self.blocking {
|
||||||
|
self.handle_async_with_sync_blocking(handle_args).await
|
||||||
|
} else {
|
||||||
|
self.handle_async_with_sync(handle_args).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn metadata(&self, _: VecDeque<&'static str>, _: TypeId) -> OrdMap<&'static str, Value> {
|
||||||
|
self.metadata.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Context, F, Fut, T, E, Params> HandlerTypes for FromFnAsync<F, Fut, T, E, (Context, Params)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context, Params) -> Fut + Send + Sync + Clone + 'static,
|
||||||
|
Fut: Future<Output = Result<T, E>> + Send + Sync + 'static,
|
||||||
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Params = Params;
|
||||||
|
type InheritedParams = NoParams;
|
||||||
|
type Ok = T;
|
||||||
|
type Err = E;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, Fut, T, E, Params> Handler for FromFnAsync<F, Fut, T, E, (Context, Params)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context, Params) -> Fut + Send + Sync + Clone + 'static,
|
||||||
|
Fut: Future<Output = Result<T, E>> + Send + Sync + 'static,
|
||||||
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Context = Context;
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
let HandleArgs {
|
||||||
|
context, params, ..
|
||||||
|
} = handle_args;
|
||||||
|
(self.function)(context, params).await
|
||||||
|
}
|
||||||
|
fn metadata(&self, _: VecDeque<&'static str>, _: TypeId) -> OrdMap<&'static str, Value> {
|
||||||
|
self.metadata.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Context, F, T, E, Params, InheritedParams> HandlerTypes
|
||||||
|
for FromFn<F, T, E, (Context, Params, InheritedParams)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context, Params, InheritedParams) -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
InheritedParams: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Params = Params;
|
||||||
|
type InheritedParams = InheritedParams;
|
||||||
|
type Ok = T;
|
||||||
|
type Err = E;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, T, E, Params, InheritedParams> Handler
|
||||||
|
for FromFn<F, T, E, (Context, Params, InheritedParams)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context, Params, InheritedParams) -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
InheritedParams: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Context = Context;
|
||||||
|
fn handle_sync(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
let HandleArgs {
|
||||||
|
context,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
..
|
||||||
|
} = handle_args;
|
||||||
|
(self.function)(context, params, inherited_params)
|
||||||
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
if self.blocking {
|
||||||
|
self.handle_async_with_sync_blocking(handle_args).await
|
||||||
|
} else {
|
||||||
|
self.handle_async_with_sync(handle_args).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn metadata(&self, _: VecDeque<&'static str>, _: TypeId) -> OrdMap<&'static str, Value> {
|
||||||
|
self.metadata.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Context, F, Fut, T, E, Params, InheritedParams> HandlerTypes
|
||||||
|
for FromFnAsync<F, Fut, T, E, (Context, Params, InheritedParams)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context, Params, InheritedParams) -> Fut + Send + Sync + Clone + 'static,
|
||||||
|
Fut: Future<Output = Result<T, E>> + Send + Sync + 'static,
|
||||||
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
InheritedParams: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Params = Params;
|
||||||
|
type InheritedParams = InheritedParams;
|
||||||
|
type Ok = T;
|
||||||
|
type Err = E;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, Fut, T, E, Params, InheritedParams> Handler
|
||||||
|
for FromFnAsync<F, Fut, T, E, (Context, Params, InheritedParams)>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
F: Fn(Context, Params, InheritedParams) -> Fut + Send + Sync + Clone + 'static,
|
||||||
|
Fut: Future<Output = Result<T, E>> + Send + Sync + 'static,
|
||||||
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
InheritedParams: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Context = Context;
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
let HandleArgs {
|
||||||
|
context,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
..
|
||||||
|
} = handle_args;
|
||||||
|
(self.function)(context, params, inherited_params).await
|
||||||
|
}
|
||||||
|
fn metadata(&self, _: VecDeque<&'static str>, _: TypeId) -> OrdMap<&'static str, Value> {
|
||||||
|
self.metadata.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, T, E, Args> CliBindings for FromFn<F, T, E, Args>
|
||||||
|
where
|
||||||
|
Self: HandlerTypes,
|
||||||
|
Self::Params: FromArgMatches + CommandFactory + Serialize,
|
||||||
|
Self: PrintCliResult,
|
||||||
|
{
|
||||||
|
type Context = <Self as PrintCliResult>::Context;
|
||||||
|
fn cli_command(&self, _: TypeId) -> Command {
|
||||||
|
Self::Params::command()
|
||||||
|
}
|
||||||
|
fn cli_parse(
|
||||||
|
&self,
|
||||||
|
matches: &ArgMatches,
|
||||||
|
_: TypeId,
|
||||||
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
||||||
|
Self::Params::from_arg_matches(matches).and_then(|a| {
|
||||||
|
Ok((
|
||||||
|
VecDeque::new(),
|
||||||
|
imbl_value::to_value(&a)
|
||||||
|
.map_err(|e| clap::Error::raw(clap::error::ErrorKind::ValueValidation, e))?,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn cli_display(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Self::Context, Self>,
|
||||||
|
result: Self::Ok,
|
||||||
|
) -> Result<(), Self::Err> {
|
||||||
|
self.print(
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
},
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, Fut, T, E, Args> CliBindings for FromFnAsync<F, Fut, T, E, Args>
|
||||||
|
where
|
||||||
|
Self: HandlerTypes,
|
||||||
|
Self::Params: FromArgMatches + CommandFactory + Serialize,
|
||||||
|
Self: PrintCliResult,
|
||||||
|
{
|
||||||
|
type Context = <Self as PrintCliResult>::Context;
|
||||||
|
fn cli_command(&self, _: TypeId) -> Command {
|
||||||
|
Self::Params::command()
|
||||||
|
}
|
||||||
|
fn cli_parse(
|
||||||
|
&self,
|
||||||
|
matches: &ArgMatches,
|
||||||
|
_: TypeId,
|
||||||
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
||||||
|
Self::Params::from_arg_matches(matches).and_then(|a| {
|
||||||
|
Ok((
|
||||||
|
VecDeque::new(),
|
||||||
|
imbl_value::to_value(&a)
|
||||||
|
.map_err(|e| clap::Error::raw(clap::error::ErrorKind::ValueValidation, e))?,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn cli_display(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Self::Context, Self>,
|
||||||
|
result: Self::Ok,
|
||||||
|
) -> Result<(), Self::Err> {
|
||||||
|
self.print(
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
},
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
1
rpc-toolkit/src/handler/marker.rs
Normal file
1
rpc-toolkit/src/handler/marker.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub trait LeafHandler {}
|
||||||
317
rpc-toolkit/src/handler/mod.rs
Normal file
317
rpc-toolkit/src/handler/mod.rs
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
use std::any::TypeId;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use clap::{ArgMatches, Command, Parser};
|
||||||
|
use imbl_value::imbl::{OrdMap, OrdSet};
|
||||||
|
use imbl_value::Value;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use yajrc::RpcError;
|
||||||
|
|
||||||
|
use crate::context::{AnyContext, IntoContext};
|
||||||
|
use crate::util::{internal_error, invalid_params};
|
||||||
|
|
||||||
|
pub mod adapters;
|
||||||
|
pub mod from_fn;
|
||||||
|
pub mod marker;
|
||||||
|
pub mod parent;
|
||||||
|
|
||||||
|
pub use adapters::*;
|
||||||
|
pub use from_fn::*;
|
||||||
|
pub use parent::*;
|
||||||
|
|
||||||
|
pub(crate) struct HandleAnyArgs {
|
||||||
|
pub(crate) context: AnyContext,
|
||||||
|
pub(crate) parent_method: VecDeque<&'static str>,
|
||||||
|
pub(crate) method: VecDeque<&'static str>,
|
||||||
|
pub(crate) params: Value,
|
||||||
|
}
|
||||||
|
impl HandleAnyArgs {
|
||||||
|
fn downcast<Context: IntoContext, H>(self) -> Result<HandleArgs<Context, H>, imbl_value::Error>
|
||||||
|
where
|
||||||
|
H: HandlerTypes,
|
||||||
|
H::Params: DeserializeOwned,
|
||||||
|
H::InheritedParams: DeserializeOwned,
|
||||||
|
{
|
||||||
|
let Self {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
} = self;
|
||||||
|
Ok(HandleArgs {
|
||||||
|
context: Context::downcast(context).map_err(|_| imbl_value::Error {
|
||||||
|
kind: imbl_value::ErrorKind::Deserialization,
|
||||||
|
source: serde::ser::Error::custom("context does not match expected"),
|
||||||
|
})?,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params: imbl_value::from_value(params.clone())?,
|
||||||
|
inherited_params: imbl_value::from_value(params.clone())?,
|
||||||
|
raw_params: params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
pub(crate) trait HandleAny: std::fmt::Debug + Send + Sync {
|
||||||
|
fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError>;
|
||||||
|
async fn handle_async(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError>;
|
||||||
|
fn metadata(
|
||||||
|
&self,
|
||||||
|
method: VecDeque<&'static str>,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> OrdMap<&'static str, Value>;
|
||||||
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>>;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<T: HandleAny> HandleAny for Arc<T> {
|
||||||
|
fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
||||||
|
self.deref().handle_sync(handle_args)
|
||||||
|
}
|
||||||
|
async fn handle_async(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
||||||
|
self.deref().handle_async(handle_args).await
|
||||||
|
}
|
||||||
|
fn metadata(
|
||||||
|
&self,
|
||||||
|
method: VecDeque<&'static str>,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> OrdMap<&'static str, Value> {
|
||||||
|
self.deref().metadata(method, ctx_ty)
|
||||||
|
}
|
||||||
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
self.deref().method_from_dots(method, ctx_ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait CliBindingsAny {
|
||||||
|
fn cli_command(&self, ctx_ty: TypeId) -> Command;
|
||||||
|
fn cli_parse(
|
||||||
|
&self,
|
||||||
|
matches: &ArgMatches,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error>;
|
||||||
|
fn cli_display(&self, handle_args: HandleAnyArgs, result: Value) -> Result<(), RpcError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CliBindings: HandlerTypes {
|
||||||
|
type Context: IntoContext;
|
||||||
|
fn cli_command(&self, ctx_ty: TypeId) -> Command;
|
||||||
|
fn cli_parse(
|
||||||
|
&self,
|
||||||
|
matches: &ArgMatches,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error>;
|
||||||
|
fn cli_display(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
result: Self::Ok,
|
||||||
|
) -> Result<(), Self::Err>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait PrintCliResult: HandlerTypes {
|
||||||
|
type Context: IntoContext;
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
result: Self::Ok,
|
||||||
|
) -> Result<(), Self::Err>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait HandleAnyWithCli: HandleAny + CliBindingsAny {}
|
||||||
|
impl<T: HandleAny + CliBindingsAny> HandleAnyWithCli for T {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(private_interfaces)]
|
||||||
|
pub enum DynHandler {
|
||||||
|
WithoutCli(Arc<dyn HandleAny>),
|
||||||
|
WithCli(Arc<dyn HandleAnyWithCli>),
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl HandleAny for DynHandler {
|
||||||
|
fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
||||||
|
match self {
|
||||||
|
DynHandler::WithoutCli(h) => h.handle_sync(handle_args),
|
||||||
|
DynHandler::WithCli(h) => h.handle_sync(handle_args),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async fn handle_async(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
||||||
|
match self {
|
||||||
|
DynHandler::WithoutCli(h) => h.handle_async(handle_args).await,
|
||||||
|
DynHandler::WithCli(h) => h.handle_async(handle_args).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn metadata(
|
||||||
|
&self,
|
||||||
|
method: VecDeque<&'static str>,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> OrdMap<&'static str, Value> {
|
||||||
|
match self {
|
||||||
|
DynHandler::WithoutCli(h) => h.metadata(method, ctx_ty),
|
||||||
|
DynHandler::WithCli(h) => h.metadata(method, ctx_ty),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
match self {
|
||||||
|
DynHandler::WithoutCli(h) => h.method_from_dots(method, ctx_ty),
|
||||||
|
DynHandler::WithCli(h) => h.method_from_dots(method, ctx_ty),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct HandleArgs<Context: IntoContext, H: HandlerTypes + ?Sized> {
|
||||||
|
pub context: Context,
|
||||||
|
pub parent_method: VecDeque<&'static str>,
|
||||||
|
pub method: VecDeque<&'static str>,
|
||||||
|
pub params: H::Params,
|
||||||
|
pub inherited_params: H::InheritedParams,
|
||||||
|
pub raw_params: Value,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait HandlerTypes {
|
||||||
|
type Params: Send + Sync;
|
||||||
|
type InheritedParams: Send + Sync;
|
||||||
|
type Ok: Send + Sync;
|
||||||
|
type Err: Send + Sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
pub trait Handler: HandlerTypes + std::fmt::Debug + Clone + Send + Sync + 'static {
|
||||||
|
type Context: IntoContext;
|
||||||
|
fn handle_sync(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
handle_args
|
||||||
|
.context
|
||||||
|
.runtime()
|
||||||
|
.block_on(self.handle_async(handle_args))
|
||||||
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err>;
|
||||||
|
async fn handle_async_with_sync(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
self.handle_sync(handle_args)
|
||||||
|
}
|
||||||
|
async fn handle_async_with_sync_blocking(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
let s = self.clone();
|
||||||
|
handle_args
|
||||||
|
.context
|
||||||
|
.runtime()
|
||||||
|
.spawn_blocking(move || s.handle_sync(handle_args))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn metadata(
|
||||||
|
&self,
|
||||||
|
method: VecDeque<&'static str>,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> OrdMap<&'static str, Value> {
|
||||||
|
OrdMap::new()
|
||||||
|
}
|
||||||
|
fn contexts(&self) -> Option<OrdSet<TypeId>> {
|
||||||
|
Self::Context::type_ids()
|
||||||
|
}
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
if method.is_empty() {
|
||||||
|
Some(VecDeque::new())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct AnyHandler<H>(H);
|
||||||
|
impl<H> AnyHandler<H> {
|
||||||
|
pub(crate) fn new(handler: H) -> Self {
|
||||||
|
Self(handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<H: std::fmt::Debug> std::fmt::Debug for AnyHandler<H> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_tuple("AnyHandler").field(&self.0).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<H: Handler> HandleAny for AnyHandler<H>
|
||||||
|
where
|
||||||
|
H::Params: DeserializeOwned,
|
||||||
|
H::InheritedParams: DeserializeOwned,
|
||||||
|
H::Ok: Serialize,
|
||||||
|
RpcError: From<H::Err>,
|
||||||
|
{
|
||||||
|
fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
||||||
|
imbl_value::to_value(
|
||||||
|
&self
|
||||||
|
.0
|
||||||
|
.handle_sync(handle_args.downcast().map_err(invalid_params)?)?,
|
||||||
|
)
|
||||||
|
.map_err(internal_error)
|
||||||
|
}
|
||||||
|
async fn handle_async(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
||||||
|
imbl_value::to_value(
|
||||||
|
&self
|
||||||
|
.0
|
||||||
|
.handle_async(handle_args.downcast().map_err(invalid_params)?)
|
||||||
|
.await?,
|
||||||
|
)
|
||||||
|
.map_err(internal_error)
|
||||||
|
}
|
||||||
|
fn metadata(
|
||||||
|
&self,
|
||||||
|
method: VecDeque<&'static str>,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> OrdMap<&'static str, Value> {
|
||||||
|
self.0.metadata(method, ctx_ty)
|
||||||
|
}
|
||||||
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
self.0.method_from_dots(method, ctx_ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: CliBindings> CliBindingsAny for AnyHandler<H>
|
||||||
|
where
|
||||||
|
H: CliBindings,
|
||||||
|
H::Params: DeserializeOwned,
|
||||||
|
H::InheritedParams: DeserializeOwned,
|
||||||
|
H::Ok: Serialize + DeserializeOwned,
|
||||||
|
RpcError: From<H::Err>,
|
||||||
|
{
|
||||||
|
fn cli_command(&self, ctx_ty: TypeId) -> Command {
|
||||||
|
self.0.cli_command(ctx_ty)
|
||||||
|
}
|
||||||
|
fn cli_parse(
|
||||||
|
&self,
|
||||||
|
matches: &ArgMatches,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
||||||
|
self.0.cli_parse(matches, ctx_ty)
|
||||||
|
}
|
||||||
|
fn cli_display(&self, handle_args: HandleAnyArgs, result: Value) -> Result<(), RpcError> {
|
||||||
|
self.0
|
||||||
|
.cli_display(
|
||||||
|
handle_args.downcast().map_err(invalid_params)?,
|
||||||
|
imbl_value::from_value(result).map_err(internal_error)?,
|
||||||
|
)
|
||||||
|
.map_err(RpcError::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)]
|
||||||
|
pub struct NoParams {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)]
|
||||||
|
pub enum Never {}
|
||||||
520
rpc-toolkit/src/handler/parent.rs
Normal file
520
rpc-toolkit/src/handler/parent.rs
Normal file
@@ -0,0 +1,520 @@
|
|||||||
|
use std::any::TypeId;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use clap::{ArgMatches, Command, CommandFactory, FromArgMatches};
|
||||||
|
use imbl_value::imbl::{OrdMap, OrdSet};
|
||||||
|
use imbl_value::Value;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde::Serialize;
|
||||||
|
use yajrc::RpcError;
|
||||||
|
|
||||||
|
use crate::util::{combine, Flat};
|
||||||
|
use crate::{
|
||||||
|
AnyContext, AnyHandler, CliBindings, DynHandler, HandleAny, HandleAnyArgs, HandleArgs, Handler,
|
||||||
|
HandlerTypes, IntoContext, NoCli, NoParams,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait IntoHandlers: HandlerTypes {
|
||||||
|
fn into_handlers(self) -> impl IntoIterator<Item = (Option<TypeId>, DynHandler)>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: Handler + CliBindings> IntoHandlers for H {
|
||||||
|
fn into_handlers(self) -> impl IntoIterator<Item = (Option<TypeId>, DynHandler)> {
|
||||||
|
iter_from_ctx_and_handler(
|
||||||
|
intersect_type_ids(self.contexts(), <Self as CliBindings>::Context::type_ids()),
|
||||||
|
DynHandler::WithCli(Arc::new(AnyHandler::new(self))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn iter_from_ctx_and_handler(
|
||||||
|
ctx: Option<OrdSet<TypeId>>,
|
||||||
|
handler: DynHandler,
|
||||||
|
) -> impl IntoIterator<Item = (Option<TypeId>, DynHandler)> {
|
||||||
|
if let Some(ctx) = ctx {
|
||||||
|
itertools::Either::Left(ctx.into_iter().map(Some))
|
||||||
|
} else {
|
||||||
|
itertools::Either::Right(std::iter::once(None))
|
||||||
|
}
|
||||||
|
.map(move |ctx| (ctx, handler.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn intersect_type_ids(
|
||||||
|
a: Option<OrdSet<TypeId>>,
|
||||||
|
b: Option<OrdSet<TypeId>>,
|
||||||
|
) -> Option<OrdSet<TypeId>> {
|
||||||
|
match (a, b) {
|
||||||
|
(None, None) => None,
|
||||||
|
(Some(a), None) => Some(a),
|
||||||
|
(None, Some(b)) => Some(b),
|
||||||
|
(Some(a), Some(b)) => Some(a.intersection(b)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub(crate) struct Name(pub(crate) Option<&'static str>);
|
||||||
|
impl<'a> std::borrow::Borrow<Option<&'a str>> for Name {
|
||||||
|
fn borrow(&self) -> &Option<&'a str> {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct SubcommandMap(pub(crate) OrdMap<Name, OrdMap<Option<TypeId>, DynHandler>>);
|
||||||
|
impl SubcommandMap {
|
||||||
|
fn insert(
|
||||||
|
&mut self,
|
||||||
|
name: Option<&'static str>,
|
||||||
|
handlers: impl IntoIterator<Item = (Option<TypeId>, DynHandler)>,
|
||||||
|
) {
|
||||||
|
let mut for_name = self.0.remove(&name).unwrap_or_default();
|
||||||
|
for (ctx_ty, handler) in handlers {
|
||||||
|
for_name.insert(ctx_ty, handler);
|
||||||
|
}
|
||||||
|
self.0.insert(Name(name), for_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get<'a>(&'a self, ctx_ty: TypeId, name: Option<&str>) -> Option<(Name, &'a DynHandler)> {
|
||||||
|
if let Some((name, for_name)) = self.0.get_key_value(&name) {
|
||||||
|
if let Some(for_ctx) = for_name.get(&Some(ctx_ty)) {
|
||||||
|
Some((*name, for_ctx))
|
||||||
|
} else {
|
||||||
|
for_name.get(&None).map(|h| (*name, h))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ParentHandler<Params = NoParams, InheritedParams = NoParams> {
|
||||||
|
_phantom: PhantomData<(Params, InheritedParams)>,
|
||||||
|
pub(crate) subcommands: SubcommandMap,
|
||||||
|
metadata: OrdMap<&'static str, Value>,
|
||||||
|
}
|
||||||
|
impl<Params, InheritedParams> ParentHandler<Params, InheritedParams> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
subcommands: SubcommandMap(OrdMap::new()),
|
||||||
|
metadata: OrdMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn with_metadata(mut self, key: &'static str, value: Value) -> Self {
|
||||||
|
self.metadata.insert(key, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Params, InheritedParams> Clone for ParentHandler<Params, InheritedParams> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
subcommands: self.subcommands.clone(),
|
||||||
|
metadata: self.metadata.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Params, InheritedParams> std::fmt::Debug for ParentHandler<Params, InheritedParams> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_tuple("ParentHandler")
|
||||||
|
.field(&self.subcommands)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InheritanceHandler<Params, InheritedParams, H, F> {
|
||||||
|
_phantom: PhantomData<(Params, InheritedParams)>,
|
||||||
|
handler: H,
|
||||||
|
inherit: F,
|
||||||
|
}
|
||||||
|
impl<Params, InheritedParams, H: Clone, F: Clone> Clone
|
||||||
|
for InheritanceHandler<Params, InheritedParams, H, F>
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
handler: self.handler.clone(),
|
||||||
|
inherit: self.inherit.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Params, InheritedParams, H: std::fmt::Debug, F> std::fmt::Debug
|
||||||
|
for InheritanceHandler<Params, InheritedParams, H, F>
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_tuple("InheritanceHandler")
|
||||||
|
.field(&self.handler)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Params, InheritedParams, H, F> HandlerTypes
|
||||||
|
for InheritanceHandler<Params, InheritedParams, H, F>
|
||||||
|
where
|
||||||
|
H: HandlerTypes,
|
||||||
|
Params: Send + Sync,
|
||||||
|
InheritedParams: Send + Sync,
|
||||||
|
{
|
||||||
|
type Params = H::Params;
|
||||||
|
type InheritedParams = Flat<Params, InheritedParams>;
|
||||||
|
type Ok = H::Ok;
|
||||||
|
type Err = H::Err;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Params, InheritedParams, H, F> Handler for InheritanceHandler<Params, InheritedParams, H, F>
|
||||||
|
where
|
||||||
|
Params: Send + Sync + 'static,
|
||||||
|
InheritedParams: Send + Sync + 'static,
|
||||||
|
H: Handler,
|
||||||
|
F: Fn(Params, InheritedParams) -> H::InheritedParams + Send + Sync + Clone + 'static,
|
||||||
|
{
|
||||||
|
type Context = H::Context;
|
||||||
|
fn handle_sync(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
self.handler.handle_sync(HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params: (self.inherit)(inherited_params.0, inherited_params.1),
|
||||||
|
raw_params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Self::Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
self.handler.handle_sync(HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params: (self.inherit)(inherited_params.0, inherited_params.1),
|
||||||
|
raw_params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn metadata(
|
||||||
|
&self,
|
||||||
|
method: VecDeque<&'static str>,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> OrdMap<&'static str, Value> {
|
||||||
|
self.handler.metadata(method, ctx_ty)
|
||||||
|
}
|
||||||
|
fn contexts(&self) -> Option<OrdSet<TypeId>> {
|
||||||
|
self.handler.contexts()
|
||||||
|
}
|
||||||
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
self.handler.method_from_dots(method, ctx_ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Params, InheritedParams, H, F> CliBindings
|
||||||
|
for InheritanceHandler<Params, InheritedParams, H, F>
|
||||||
|
where
|
||||||
|
Params: Send + Sync + 'static,
|
||||||
|
InheritedParams: Send + Sync + 'static,
|
||||||
|
H: CliBindings,
|
||||||
|
F: Fn(Params, InheritedParams) -> H::InheritedParams + Send + Sync + Clone + 'static,
|
||||||
|
{
|
||||||
|
type Context = H::Context;
|
||||||
|
fn cli_command(&self, ctx_ty: TypeId) -> Command {
|
||||||
|
self.handler.cli_command(ctx_ty)
|
||||||
|
}
|
||||||
|
fn cli_parse(
|
||||||
|
&self,
|
||||||
|
matches: &ArgMatches,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
||||||
|
self.handler.cli_parse(matches, ctx_ty)
|
||||||
|
}
|
||||||
|
fn cli_display(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Self::Context, Self>,
|
||||||
|
result: Self::Ok,
|
||||||
|
) -> Result<(), Self::Err> {
|
||||||
|
self.handler.cli_display(
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params: (self.inherit)(inherited_params.0, inherited_params.1),
|
||||||
|
raw_params,
|
||||||
|
},
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Params, InheritedParams> ParentHandler<Params, InheritedParams> {
|
||||||
|
fn get_contexts(&self) -> Option<OrdSet<TypeId>> {
|
||||||
|
let mut set = OrdSet::new();
|
||||||
|
for ctx_ty in self.subcommands.0.values().flat_map(|c| c.keys()) {
|
||||||
|
set.insert((*ctx_ty)?);
|
||||||
|
}
|
||||||
|
Some(set)
|
||||||
|
}
|
||||||
|
pub fn subcommand<H>(mut self, name: &'static str, handler: H) -> Self
|
||||||
|
where
|
||||||
|
H: IntoHandlers<InheritedParams = Flat<Params, InheritedParams>>,
|
||||||
|
{
|
||||||
|
self.subcommands
|
||||||
|
.insert(name.into(), handler.into_handlers());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn root_handler<H>(mut self, handler: H) -> Self
|
||||||
|
where
|
||||||
|
H: IntoHandlers<Params = NoParams, InheritedParams = Flat<Params, InheritedParams>>,
|
||||||
|
{
|
||||||
|
self.subcommands.insert(None, handler.into_handlers());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Params, InheritedParams> HandlerTypes for ParentHandler<Params, InheritedParams>
|
||||||
|
where
|
||||||
|
Params: Send + Sync,
|
||||||
|
InheritedParams: Send + Sync,
|
||||||
|
{
|
||||||
|
type Params = Params;
|
||||||
|
type InheritedParams = InheritedParams;
|
||||||
|
type Ok = Value;
|
||||||
|
type Err = RpcError;
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Params, InheritedParams> Handler for ParentHandler<Params, InheritedParams>
|
||||||
|
where
|
||||||
|
Params: Serialize + Send + Sync + 'static,
|
||||||
|
InheritedParams: Serialize + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Context = AnyContext;
|
||||||
|
fn handle_sync(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
mut parent_method,
|
||||||
|
mut method,
|
||||||
|
raw_params,
|
||||||
|
..
|
||||||
|
}: HandleArgs<AnyContext, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
let cmd = method.pop_front();
|
||||||
|
if let Some(cmd) = cmd {
|
||||||
|
parent_method.push_back(cmd);
|
||||||
|
}
|
||||||
|
if let Some((_, sub_handler)) = &self.subcommands.get(context.inner_type_id(), cmd) {
|
||||||
|
sub_handler.handle_sync(HandleAnyArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params: raw_params,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
mut parent_method,
|
||||||
|
mut method,
|
||||||
|
raw_params,
|
||||||
|
..
|
||||||
|
}: HandleArgs<AnyContext, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
let cmd = method.pop_front();
|
||||||
|
if let Some(cmd) = cmd {
|
||||||
|
parent_method.push_back(cmd);
|
||||||
|
}
|
||||||
|
if let Some((_, sub_handler)) = self.subcommands.get(context.inner_type_id(), cmd) {
|
||||||
|
sub_handler
|
||||||
|
.handle_async(HandleAnyArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params: raw_params,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
} else {
|
||||||
|
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn metadata(
|
||||||
|
&self,
|
||||||
|
mut method: VecDeque<&'static str>,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> OrdMap<&'static str, Value> {
|
||||||
|
let metadata = self.metadata.clone();
|
||||||
|
if let Some((_, handler)) = self.subcommands.get(ctx_ty, method.pop_front()) {
|
||||||
|
handler.metadata(method, ctx_ty).union(metadata)
|
||||||
|
} else {
|
||||||
|
metadata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn contexts(&self) -> Option<OrdSet<TypeId>> {
|
||||||
|
self.get_contexts()
|
||||||
|
}
|
||||||
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
let (head, tail) = if method.is_empty() {
|
||||||
|
(None, None)
|
||||||
|
} else {
|
||||||
|
method
|
||||||
|
.split_once(".")
|
||||||
|
.map(|(head, tail)| (Some(head), Some(tail)))
|
||||||
|
.unwrap_or((Some(method), None))
|
||||||
|
};
|
||||||
|
let (Name(name), h) = self.subcommands.get(ctx_ty, head)?;
|
||||||
|
let mut res = VecDeque::new();
|
||||||
|
if let Some(name) = name {
|
||||||
|
res.push_back(name);
|
||||||
|
}
|
||||||
|
if let Some(tail) = tail {
|
||||||
|
res.append(&mut h.method_from_dots(tail, ctx_ty)?);
|
||||||
|
}
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Params, InheritedParams> CliBindings for ParentHandler<Params, InheritedParams>
|
||||||
|
where
|
||||||
|
Params: FromArgMatches + CommandFactory + Serialize + Send + Sync + 'static,
|
||||||
|
InheritedParams: Serialize + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Context = AnyContext;
|
||||||
|
fn cli_command(&self, ctx_ty: TypeId) -> Command {
|
||||||
|
let mut base = Params::command().subcommand_required(true);
|
||||||
|
for (name, handlers) in &self.subcommands.0 {
|
||||||
|
match (
|
||||||
|
name,
|
||||||
|
if let Some(handler) = handlers.get(&Some(ctx_ty)) {
|
||||||
|
Some(handler)
|
||||||
|
} else if let Some(handler) = handlers.get(&None) {
|
||||||
|
Some(handler)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
(Name(Some(name)), Some(DynHandler::WithCli(handler))) => {
|
||||||
|
base = base.subcommand(handler.cli_command(ctx_ty).name(name));
|
||||||
|
}
|
||||||
|
(Name(None), Some(DynHandler::WithCli(_))) => {
|
||||||
|
base = base.subcommand_required(false);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base
|
||||||
|
}
|
||||||
|
fn cli_parse(
|
||||||
|
&self,
|
||||||
|
matches: &ArgMatches,
|
||||||
|
ctx_ty: TypeId,
|
||||||
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
||||||
|
let root_params = imbl_value::to_value(&Params::from_arg_matches(matches)?)
|
||||||
|
.map_err(|e| clap::Error::raw(clap::error::ErrorKind::ValueValidation, e))?;
|
||||||
|
let (name, matches) = match matches.subcommand() {
|
||||||
|
Some((name, matches)) => (Some(name), matches),
|
||||||
|
None => (None, matches),
|
||||||
|
};
|
||||||
|
if let Some((Name(Some(name)), DynHandler::WithCli(handler))) =
|
||||||
|
self.subcommands.get(ctx_ty, name)
|
||||||
|
{
|
||||||
|
let (mut method, params) = handler.cli_parse(matches, ctx_ty)?;
|
||||||
|
method.push_front(name);
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
method,
|
||||||
|
combine(root_params, params)
|
||||||
|
.map_err(|e| clap::Error::raw(clap::error::ErrorKind::ArgumentConflict, e))?,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok((VecDeque::new(), root_params))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn cli_display(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
mut parent_method,
|
||||||
|
mut method,
|
||||||
|
raw_params,
|
||||||
|
..
|
||||||
|
}: HandleArgs<AnyContext, Self>,
|
||||||
|
result: Self::Ok,
|
||||||
|
) -> Result<(), Self::Err> {
|
||||||
|
let cmd = method.pop_front();
|
||||||
|
if let Some(cmd) = cmd {
|
||||||
|
parent_method.push_back(cmd);
|
||||||
|
}
|
||||||
|
if let Some((_, DynHandler::WithCli(sub_handler))) =
|
||||||
|
self.subcommands.get(context.inner_type_id(), cmd)
|
||||||
|
{
|
||||||
|
sub_handler.cli_display(
|
||||||
|
HandleAnyArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params: raw_params,
|
||||||
|
},
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Params, InheritedParams> IntoHandlers for ParentHandler<Params, InheritedParams>
|
||||||
|
where
|
||||||
|
Self: HandlerTypes + Handler + CliBindings,
|
||||||
|
<Self as HandlerTypes>::Params: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::InheritedParams: DeserializeOwned,
|
||||||
|
<Self as HandlerTypes>::Ok: Serialize + DeserializeOwned,
|
||||||
|
RpcError: From<<Self as HandlerTypes>::Err>,
|
||||||
|
{
|
||||||
|
fn into_handlers(self) -> impl IntoIterator<Item = (Option<TypeId>, DynHandler)> {
|
||||||
|
iter_from_ctx_and_handler(
|
||||||
|
self.contexts(),
|
||||||
|
DynHandler::WithoutCli(Arc::new(AnyHandler::new(self))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Params, InheritedParams> IntoHandlers for NoCli<ParentHandler<Params, InheritedParams>>
|
||||||
|
where
|
||||||
|
ParentHandler<Params, InheritedParams>: HandlerTypes + Handler,
|
||||||
|
<ParentHandler<Params, InheritedParams> as HandlerTypes>::Params: DeserializeOwned,
|
||||||
|
<ParentHandler<Params, InheritedParams> as HandlerTypes>::InheritedParams: DeserializeOwned,
|
||||||
|
<ParentHandler<Params, InheritedParams> as HandlerTypes>::Ok: Serialize + DeserializeOwned,
|
||||||
|
RpcError: From<<ParentHandler<Params, InheritedParams> as HandlerTypes>::Err>,
|
||||||
|
{
|
||||||
|
fn into_handlers(self) -> impl IntoIterator<Item = (Option<TypeId>, DynHandler)> {
|
||||||
|
iter_from_ctx_and_handler(
|
||||||
|
self.0.contexts(),
|
||||||
|
DynHandler::WithoutCli(Arc::new(AnyHandler::new(self.0))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ use imbl_value::Value;
|
|||||||
use yajrc::{RpcError, RpcMethod};
|
use yajrc::{RpcError, RpcMethod};
|
||||||
|
|
||||||
use crate::util::{invalid_request, JobRunner};
|
use crate::util::{invalid_request, JobRunner};
|
||||||
use crate::{AnyHandler, HandleAny, HandleAnyArgs, IntoContext, ParentHandler};
|
use crate::{AnyContext, AnyHandler, HandleAny, HandleAnyArgs, IntoContext, ParentHandler};
|
||||||
|
|
||||||
type GenericRpcMethod = yajrc::GenericRpcMethod<String, Value, Value>;
|
type GenericRpcMethod = yajrc::GenericRpcMethod<String, Value, Value>;
|
||||||
type RpcRequest = yajrc::RpcRequest<GenericRpcMethod>;
|
type RpcRequest = yajrc::RpcRequest<GenericRpcMethod>;
|
||||||
@@ -23,7 +23,7 @@ pub use socket::*;
|
|||||||
|
|
||||||
pub struct Server<Context: crate::Context> {
|
pub struct Server<Context: crate::Context> {
|
||||||
make_ctx: Arc<dyn Fn() -> BoxFuture<'static, Result<Context, RpcError>> + Send + Sync>,
|
make_ctx: Arc<dyn Fn() -> BoxFuture<'static, Result<Context, RpcError>> + Send + Sync>,
|
||||||
root_handler: Arc<AnyHandler<Context, ParentHandler>>,
|
root_handler: Arc<AnyHandler<ParentHandler>>,
|
||||||
}
|
}
|
||||||
impl<Context: crate::Context> Clone for Server<Context> {
|
impl<Context: crate::Context> Clone for Server<Context> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ fn make_api() -> ParentHandler {
|
|||||||
donde: String,
|
donde: String,
|
||||||
}
|
}
|
||||||
ParentHandler::new()
|
ParentHandler::new()
|
||||||
.subcommand_remote_cli::<CliContext, _, _>(
|
.subcommand(
|
||||||
"echo",
|
"echo",
|
||||||
from_fn_async(
|
from_fn_async(
|
||||||
|c: ServerContext, EchoParams { next }: EchoParams| async move {
|
|c: ServerContext, EchoParams { next }: EchoParams| async move {
|
||||||
@@ -129,7 +129,8 @@ fn make_api() -> ParentHandler {
|
|||||||
Value::String(Arc::new(next)),
|
Value::String(Arc::new(next)),
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
),
|
)
|
||||||
|
.with_remote_cli::<CliContext>(),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
"hello",
|
"hello",
|
||||||
|
|||||||
Reference in New Issue
Block a user