mirror of
https://github.com/Start9Labs/rpc-toolkit.git
synced 2026-03-26 02:11:56 +00:00
connect apis
This commit is contained in:
@@ -1,232 +1,82 @@
|
|||||||
use std::{ffi::OsString, marker::PhantomData};
|
use std::any::TypeId;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use clap::{ArgMatches, CommandFactory, FromArgMatches};
|
use clap::{CommandFactory, FromArgMatches};
|
||||||
use futures::{future::BoxFuture, never::Never};
|
|
||||||
use futures::{Future, FutureExt};
|
|
||||||
use imbl_value::Value;
|
use imbl_value::Value;
|
||||||
use reqwest::{Client, Method};
|
use reqwest::{Client, Method};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::marker::PhantomData;
|
|
||||||
use tokio::io::{AsyncBufReadExt, AsyncRead, AsyncWrite, AsyncWriteExt, BufReader};
|
use tokio::io::{AsyncBufReadExt, AsyncRead, AsyncWrite, AsyncWriteExt, BufReader};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use yajrc::{Id, RpcError};
|
use yajrc::{Id, RpcError};
|
||||||
|
|
||||||
use crate::{command::ParentCommand, CliBindings, EmptyHandler, HandleArgs, Handler, NoParams};
|
use crate::util::{internal_error, parse_error, Flat};
|
||||||
// use crate::command::{AsyncCommand, DynCommand, LeafCommand, ParentInfo};
|
use crate::{
|
||||||
use crate::util::{combine, internal_error, invalid_params, parse_error};
|
AnyHandler, CliBindingsAny, DynHandler, HandleAny, HandleAnyArgs, HandleArgs, Handler,
|
||||||
// use crate::{CliBindings, SyncCommand};
|
IntoContext, Name, ParentHandler,
|
||||||
|
};
|
||||||
|
|
||||||
type GenericRpcMethod<'a> = yajrc::GenericRpcMethod<&'a str, Value, Value>;
|
type GenericRpcMethod<'a> = yajrc::GenericRpcMethod<&'a str, Value, Value>;
|
||||||
type RpcRequest<'a> = yajrc::RpcRequest<GenericRpcMethod<'a>>;
|
type RpcRequest<'a> = yajrc::RpcRequest<GenericRpcMethod<'a>>;
|
||||||
type RpcResponse<'a> = yajrc::RpcResponse<GenericRpcMethod<'static>>;
|
type RpcResponse<'a> = yajrc::RpcResponse<GenericRpcMethod<'static>>;
|
||||||
|
|
||||||
// impl<Context: crate::Context> DynCommand<Context> {
|
pub struct CliApp<Context: crate::Context + Clone, Config: CommandFactory + FromArgMatches> {
|
||||||
// fn cli_app(&self) -> Option<clap::Command> {
|
_phantom: PhantomData<(Context, Config)>,
|
||||||
// if let Some(cli) = &self.cli {
|
make_ctx: Box<dyn FnOnce(Config) -> Result<Context, RpcError> + Send + Sync>,
|
||||||
// Some(
|
root_handler: ParentHandler,
|
||||||
// cli.cmd
|
}
|
||||||
// .clone()
|
impl<Context: crate::Context + Clone, Config: CommandFactory + FromArgMatches>
|
||||||
// .name(self.name)
|
CliApp<Context, Config>
|
||||||
// .subcommands(self.subcommands.iter().filter_map(|c| c.cli_app())),
|
|
||||||
// )
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// fn cmd_from_cli_matches(
|
|
||||||
// &self,
|
|
||||||
// matches: &ArgMatches,
|
|
||||||
// parent: ParentInfo<Value>,
|
|
||||||
// ) -> Result<(Vec<&'static str>, Value, &DynCommand<Context>), RpcError> {
|
|
||||||
// let params = combine(
|
|
||||||
// parent.params,
|
|
||||||
// (self
|
|
||||||
// .cli
|
|
||||||
// .as_ref()
|
|
||||||
// .ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?
|
|
||||||
// .parser)(matches)?,
|
|
||||||
// )?;
|
|
||||||
// if let Some((cmd, matches)) = matches.subcommand() {
|
|
||||||
// let mut method = parent.method;
|
|
||||||
// method.push(self.name);
|
|
||||||
// self.subcommands
|
|
||||||
// .iter()
|
|
||||||
// .find(|c| c.name == cmd)
|
|
||||||
// .ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?
|
|
||||||
// .cmd_from_cli_matches(matches, ParentInfo { method, params })
|
|
||||||
// } else {
|
|
||||||
// Ok((parent.method, params, self))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
struct RootCliHandler<Context: crate::Context, Config: CommandFactory + FromArgMatches>(
|
|
||||||
PhantomData<(Context, Config)>,
|
|
||||||
);
|
|
||||||
impl<Context: crate::Context, Config: CommandFactory + FromArgMatches> Handler<Context>
|
|
||||||
for RootCliHandler<Context, Config>
|
|
||||||
{
|
{
|
||||||
type Params = NoParams;
|
pub fn new<MakeCtx: FnOnce(Config) -> Result<Context, RpcError> + Send + Sync + 'static>(
|
||||||
type InheritedParams = NoParams;
|
make_ctx: MakeCtx,
|
||||||
type Ok = Never;
|
root_handler: ParentHandler,
|
||||||
type Err = RpcError;
|
|
||||||
fn handle_sync(&self, _: HandleArgs<Context, Self>) -> Result<Self::Ok, Self::Err> {
|
|
||||||
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<Context: crate::Context, Config: CommandFactory + FromArgMatches> CliBindings
|
|
||||||
for RootCliHandler<Context, Config>
|
|
||||||
{
|
|
||||||
fn cli_command(&self) -> clap::Command {
|
|
||||||
Config::command()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cli_parse(
|
|
||||||
&self,
|
|
||||||
matches: &ArgMatches,
|
|
||||||
) -> Result<(std::collections::VecDeque<&'static str>, Value), clap::Error> {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cli_display(
|
|
||||||
&self,
|
|
||||||
handle_args: HandleArgs<Context, Self>,
|
|
||||||
result: Self::Ok,
|
|
||||||
) -> Result<(), Self::Err> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CliApp<Context: crate::Context, Config: CommandFactory + FromArgMatches>(
|
|
||||||
ParentCommand<Context, EmptyHandler<Config>>,
|
|
||||||
);
|
|
||||||
impl<Context: crate::Context> CliApp<Context> {
|
|
||||||
pub fn new(commands: Vec<DynCommand<Context>>) -> Self {
|
|
||||||
Self {
|
|
||||||
cli: CliBindings::from_parent::<Cmd>(),
|
|
||||||
commands,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn cmd_from_cli_matches(
|
|
||||||
&self,
|
|
||||||
matches: &ArgMatches,
|
|
||||||
) -> Result<(Vec<&'static str>, Value, &DynCommand<Context>), RpcError> {
|
|
||||||
if let Some((cmd, matches)) = matches.subcommand() {
|
|
||||||
Ok(self
|
|
||||||
.commands
|
|
||||||
.iter()
|
|
||||||
.find(|c| c.name == cmd)
|
|
||||||
.ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?
|
|
||||||
.cmd_from_cli_matches(
|
|
||||||
matches,
|
|
||||||
ParentInfo {
|
|
||||||
method: Vec::new(),
|
|
||||||
params: Value::Object(Default::default()),
|
|
||||||
},
|
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CliAppAsync<Context: crate::Context> {
|
|
||||||
app: CliApp<Context>,
|
|
||||||
make_ctx: Box<dyn FnOnce(Value) -> BoxFuture<'static, Result<Context, RpcError>> + Send>,
|
|
||||||
}
|
|
||||||
impl<Context: crate::Context> CliAppAsync<Context> {
|
|
||||||
pub fn new<
|
|
||||||
Cmd: FromArgMatches + CommandFactory + Serialize + DeserializeOwned + Send,
|
|
||||||
F: FnOnce(Cmd) -> Fut + Send + 'static,
|
|
||||||
Fut: Future<Output = Result<Context, RpcError>> + Send,
|
|
||||||
>(
|
|
||||||
make_ctx: F,
|
|
||||||
commands: Vec<DynCommand<Context>>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
app: CliApp::new::<Cmd>(commands),
|
_phantom: PhantomData,
|
||||||
make_ctx: Box::new(|args| {
|
make_ctx: Box::new(make_ctx),
|
||||||
async { make_ctx(imbl_value::from_value(args).map_err(parse_error)?).await }.boxed()
|
root_handler,
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
pub fn run(self, args: impl IntoIterator<Item = OsString>) -> Result<(), RpcError> {
|
||||||
impl<Context: crate::Context + Clone> CliAppAsync<Context> {
|
let ctx_ty = TypeId::of::<Context>();
|
||||||
pub async fn run(self, args: Vec<OsString>) -> Result<(), RpcError> {
|
let mut cmd = Config::command();
|
||||||
let cmd = self
|
for (name, handlers) in &self.root_handler.subcommands.0 {
|
||||||
.app
|
if let (Name(Some(name)), Some(DynHandler::WithCli(handler))) = (
|
||||||
.cli
|
name,
|
||||||
.cmd
|
if let Some(handler) = handlers.get(&Some(ctx_ty)) {
|
||||||
.clone()
|
Some(handler)
|
||||||
.subcommands(self.app.commands.iter().filter_map(|c| c.cli_app()));
|
} else if let Some(handler) = handlers.get(&None) {
|
||||||
|
Some(handler)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
cmd = cmd.subcommand(handler.cli_command(ctx_ty).name(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
let matches = cmd.get_matches_from(args);
|
let matches = cmd.get_matches_from(args);
|
||||||
let make_ctx_args = (self.app.cli.parser)(&matches)?;
|
let config = Config::from_arg_matches(&matches)?;
|
||||||
let ctx = (self.make_ctx)(make_ctx_args).await?;
|
let ctx = (self.make_ctx)(config)?;
|
||||||
let (parent_method, params, cmd) = self.app.cmd_from_cli_matches(&matches)?;
|
let root_handler = AnyHandler::new(self.root_handler);
|
||||||
let display = &cmd
|
let (method, params) = root_handler.cli_parse(&matches, ctx_ty)?;
|
||||||
.cli
|
let res = root_handler.handle_sync(HandleAnyArgs {
|
||||||
.as_ref()
|
context: ctx.clone().upcast(),
|
||||||
.ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?
|
parent_method: Vec::new(),
|
||||||
.display;
|
method: method.clone(),
|
||||||
let res = (cmd
|
params: params.clone(),
|
||||||
.implementation
|
})?;
|
||||||
.as_ref()
|
root_handler.cli_display(
|
||||||
.ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?
|
HandleAnyArgs {
|
||||||
.async_impl)(ctx.clone(), parent_method.clone(), params.clone())
|
context: ctx.upcast(),
|
||||||
.await?;
|
parent_method: Vec::new(),
|
||||||
if let Some(display) = display {
|
method,
|
||||||
display(ctx, parent_method, params, res).map_err(parse_error)
|
params,
|
||||||
} else {
|
},
|
||||||
Ok(())
|
res,
|
||||||
}
|
)?;
|
||||||
}
|
Ok(())
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CliAppSync<Context: crate::Context> {
|
|
||||||
app: CliApp<Context>,
|
|
||||||
make_ctx: Box<dyn FnOnce(Value) -> Result<Context, RpcError> + Send>,
|
|
||||||
}
|
|
||||||
impl<Context: crate::Context> CliAppSync<Context> {
|
|
||||||
pub fn new<
|
|
||||||
Cmd: FromArgMatches + CommandFactory + Serialize + DeserializeOwned + Send,
|
|
||||||
F: FnOnce(Cmd) -> Result<Context, RpcError> + Send + 'static,
|
|
||||||
>(
|
|
||||||
make_ctx: F,
|
|
||||||
commands: Vec<DynCommand<Context>>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
app: CliApp::new::<Cmd>(commands),
|
|
||||||
make_ctx: Box::new(|args| make_ctx(imbl_value::from_value(args).map_err(parse_error)?)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<Context: crate::Context + Clone> CliAppSync<Context> {
|
|
||||||
pub async fn run(self, args: Vec<OsString>) -> Result<(), RpcError> {
|
|
||||||
let cmd = self
|
|
||||||
.app
|
|
||||||
.cli
|
|
||||||
.cmd
|
|
||||||
.clone()
|
|
||||||
.subcommands(self.app.commands.iter().filter_map(|c| c.cli_app()));
|
|
||||||
let matches = cmd.get_matches_from(args);
|
|
||||||
let make_ctx_args = (self.app.cli.parser)(&matches)?;
|
|
||||||
let ctx = (self.make_ctx)(make_ctx_args)?;
|
|
||||||
let (parent_method, params, cmd) = self.app.cmd_from_cli_matches(&matches)?;
|
|
||||||
let display = &cmd
|
|
||||||
.cli
|
|
||||||
.as_ref()
|
|
||||||
.ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?
|
|
||||||
.display;
|
|
||||||
let res = (cmd
|
|
||||||
.implementation
|
|
||||||
.as_ref()
|
|
||||||
.ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?
|
|
||||||
.sync_impl)(ctx.clone(), parent_method.clone(), params.clone())?;
|
|
||||||
if let Some(display) = display {
|
|
||||||
display(ctx, parent_method, params, res).map_err(parse_error)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +135,15 @@ pub trait CliContextHttp: crate::Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<T> CliContext for T
|
||||||
|
where
|
||||||
|
T: CliContextHttp,
|
||||||
|
{
|
||||||
|
async fn call_remote(&self, method: &str, params: Value) -> Result<Value, RpcError> {
|
||||||
|
<Self as CliContextHttp>::call_remote(&self, method, params).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
pub trait CliContextSocket: crate::Context {
|
pub trait CliContextSocket: crate::Context {
|
||||||
@@ -318,66 +177,55 @@ pub trait CliContextSocket: crate::Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RemoteCommand<Context: CliContext>: LeafCommand<Context> {}
|
#[derive(Debug, Default)]
|
||||||
|
pub struct CallRemote<RemoteContext, RemoteHandler>(PhantomData<(RemoteContext, RemoteHandler)>);
|
||||||
|
impl<RemoteContext, RemoteHandler> CallRemote<RemoteContext, RemoteHandler> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<RemoteContext, RemoteHandler> Clone for CallRemote<RemoteContext, RemoteHandler> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self(PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl<T, Context> AsyncCommand<Context> for T
|
impl<Context: CliContext, RemoteContext, RemoteHandler> Handler<Context>
|
||||||
|
for CallRemote<RemoteContext, RemoteHandler>
|
||||||
where
|
where
|
||||||
T: RemoteCommand<Context> + Send + Serialize,
|
RemoteContext: IntoContext,
|
||||||
T::Parent: Serialize,
|
RemoteHandler: Handler<RemoteContext>,
|
||||||
T::Ok: DeserializeOwned,
|
RemoteHandler::Params: Serialize,
|
||||||
T::Err: From<RpcError>,
|
RemoteHandler::InheritedParams: Serialize,
|
||||||
Context: CliContext + Send + 'static,
|
RemoteHandler::Ok: DeserializeOwned,
|
||||||
|
RemoteHandler::Err: From<RpcError>,
|
||||||
{
|
{
|
||||||
async fn implementation(
|
type Params = RemoteHandler::Params;
|
||||||
self,
|
type InheritedParams = RemoteHandler::InheritedParams;
|
||||||
ctx: Context,
|
type Ok = RemoteHandler::Ok;
|
||||||
parent: ParentInfo<Self::Parent>,
|
type Err = RemoteHandler::Err;
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Context, Self>,
|
||||||
) -> Result<Self::Ok, Self::Err> {
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
let mut method = parent.method;
|
let full_method = handle_args
|
||||||
method.push(Self::NAME);
|
.parent_method
|
||||||
Ok(imbl_value::from_value(
|
.into_iter()
|
||||||
ctx.call_remote(
|
.chain(handle_args.method)
|
||||||
&method.join("."),
|
.collect::<Vec<_>>();
|
||||||
combine(
|
match handle_args
|
||||||
imbl_value::to_value(&self).map_err(invalid_params)?,
|
.context
|
||||||
imbl_value::to_value(&parent.params).map_err(invalid_params)?,
|
.call_remote(
|
||||||
)
|
&full_method.join("."),
|
||||||
.map_err(invalid_params)?,
|
imbl_value::to_value(&Flat(handle_args.params, handle_args.inherited_params))
|
||||||
|
.map_err(parse_error)?,
|
||||||
)
|
)
|
||||||
.await?,
|
.await
|
||||||
)
|
{
|
||||||
.map_err(parse_error)?)
|
Ok(a) => imbl_value::from_value(a)
|
||||||
}
|
.map_err(internal_error)
|
||||||
}
|
.map_err(Self::Err::from),
|
||||||
|
Err(e) => Err(Self::Err::from(e)),
|
||||||
impl<T, Context> SyncCommand<Context> for T
|
}
|
||||||
where
|
|
||||||
T: RemoteCommand<Context> + Send + Serialize,
|
|
||||||
T::Parent: Serialize,
|
|
||||||
T::Ok: DeserializeOwned,
|
|
||||||
T::Err: From<RpcError>,
|
|
||||||
Context: CliContext + Send + 'static,
|
|
||||||
{
|
|
||||||
const BLOCKING: bool = true;
|
|
||||||
fn implementation(
|
|
||||||
self,
|
|
||||||
ctx: Context,
|
|
||||||
parent: ParentInfo<Self::Parent>,
|
|
||||||
) -> Result<Self::Ok, Self::Err> {
|
|
||||||
let mut method = parent.method;
|
|
||||||
method.push(Self::NAME);
|
|
||||||
Ok(imbl_value::from_value(
|
|
||||||
ctx.runtime().block_on(
|
|
||||||
ctx.call_remote(
|
|
||||||
&method.join("."),
|
|
||||||
combine(
|
|
||||||
imbl_value::to_value(&self).map_err(invalid_params)?,
|
|
||||||
imbl_value::to_value(&parent.params).map_err(invalid_params)?,
|
|
||||||
)
|
|
||||||
.map_err(invalid_params)?,
|
|
||||||
),
|
|
||||||
)?,
|
|
||||||
)
|
|
||||||
.map_err(parse_error)?)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ use tokio::runtime::Handle;
|
|||||||
|
|
||||||
use crate::Handler;
|
use crate::Handler;
|
||||||
|
|
||||||
pub trait Context: Any + Send + 'static {
|
pub trait Context: Any + Send + Sync + 'static {
|
||||||
fn runtime(&self) -> Handle {
|
fn runtime(&self) -> Handle {
|
||||||
Handle::current()
|
Handle::current()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(private_bounds)]
|
#[allow(private_bounds)]
|
||||||
pub trait IntoContext: sealed::Sealed + Any + Send + Sized + 'static {
|
pub trait IntoContext: sealed::Sealed + Any + Send + Sync + Sized + 'static {
|
||||||
|
fn runtime(&self) -> Handle;
|
||||||
fn type_ids_for<H: Handler<Self> + ?Sized>(handler: &H) -> Option<BTreeSet<TypeId>>;
|
fn type_ids_for<H: Handler<Self> + ?Sized>(handler: &H) -> Option<BTreeSet<TypeId>>;
|
||||||
fn inner_type_id(&self) -> TypeId;
|
fn inner_type_id(&self) -> TypeId;
|
||||||
fn upcast(self) -> AnyContext;
|
fn upcast(self) -> AnyContext;
|
||||||
@@ -20,7 +21,10 @@ pub trait IntoContext: sealed::Sealed + Any + Send + Sized + 'static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context + Sized> IntoContext for C {
|
impl<C: Context + Sized> IntoContext for C {
|
||||||
fn type_ids_for<H: Handler<Self> + ?Sized>(handler: &H) -> Option<BTreeSet<TypeId>> {
|
fn runtime(&self) -> Handle {
|
||||||
|
<C as Context>::runtime(&self)
|
||||||
|
}
|
||||||
|
fn type_ids_for<H: Handler<Self> + ?Sized>(_: &H) -> Option<BTreeSet<TypeId>> {
|
||||||
let mut set = BTreeSet::new();
|
let mut set = BTreeSet::new();
|
||||||
set.insert(TypeId::of::<C>());
|
set.insert(TypeId::of::<C>());
|
||||||
Some(set)
|
Some(set)
|
||||||
@@ -45,7 +49,13 @@ pub enum EitherContext<C1, C2> {
|
|||||||
C2(C2),
|
C2(C2),
|
||||||
}
|
}
|
||||||
impl<C1: Context, C2: Context> IntoContext for EitherContext<C1, C2> {
|
impl<C1: Context, C2: Context> IntoContext for EitherContext<C1, C2> {
|
||||||
fn type_ids_for<H: Handler<Self> + ?Sized>(handler: &H) -> Option<BTreeSet<TypeId>> {
|
fn runtime(&self) -> Handle {
|
||||||
|
match self {
|
||||||
|
Self::C1(a) => a.runtime(),
|
||||||
|
Self::C2(a) => a.runtime(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn type_ids_for<H: Handler<Self> + ?Sized>(_: &H) -> Option<BTreeSet<TypeId>> {
|
||||||
let mut set = BTreeSet::new();
|
let mut set = BTreeSet::new();
|
||||||
set.insert(TypeId::of::<C1>());
|
set.insert(TypeId::of::<C1>());
|
||||||
set.insert(TypeId::of::<C2>());
|
set.insert(TypeId::of::<C2>());
|
||||||
@@ -88,6 +98,9 @@ impl AnyContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl IntoContext for AnyContext {
|
impl IntoContext for AnyContext {
|
||||||
|
fn runtime(&self) -> Handle {
|
||||||
|
self.0.runtime()
|
||||||
|
}
|
||||||
fn type_ids_for<H: Handler<Self> + ?Sized>(_: &H) -> Option<BTreeSet<TypeId>> {
|
fn type_ids_for<H: Handler<Self> + ?Sized>(_: &H) -> Option<BTreeSet<TypeId>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use clap::{ArgMatches, Command, CommandFactory, FromArgMatches, Parser};
|
use clap::{ArgMatches, Command, CommandFactory, FromArgMatches, Parser};
|
||||||
|
use futures::Future;
|
||||||
use imbl_value::Value;
|
use imbl_value::Value;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -12,11 +14,11 @@ use yajrc::RpcError;
|
|||||||
use crate::context::{AnyContext, IntoContext};
|
use crate::context::{AnyContext, IntoContext};
|
||||||
use crate::util::{combine, internal_error, invalid_params, Flat};
|
use crate::util::{combine, internal_error, invalid_params, Flat};
|
||||||
|
|
||||||
struct HandleAnyArgs {
|
pub(crate) struct HandleAnyArgs {
|
||||||
context: AnyContext,
|
pub(crate) context: AnyContext,
|
||||||
parent_method: Vec<&'static str>,
|
pub(crate) parent_method: Vec<&'static str>,
|
||||||
method: VecDeque<&'static str>,
|
pub(crate) method: VecDeque<&'static str>,
|
||||||
params: Value,
|
pub(crate) params: Value,
|
||||||
}
|
}
|
||||||
impl HandleAnyArgs {
|
impl HandleAnyArgs {
|
||||||
fn downcast<Context: IntoContext, H>(self) -> Result<HandleArgs<Context, H>, imbl_value::Error>
|
fn downcast<Context: IntoContext, H>(self) -> Result<HandleArgs<Context, H>, imbl_value::Error>
|
||||||
@@ -40,17 +42,31 @@ impl HandleAnyArgs {
|
|||||||
method,
|
method,
|
||||||
params: imbl_value::from_value(params.clone())?,
|
params: imbl_value::from_value(params.clone())?,
|
||||||
inherited_params: imbl_value::from_value(params.clone())?,
|
inherited_params: imbl_value::from_value(params.clone())?,
|
||||||
|
raw_params: params,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
trait HandleAny {
|
pub(crate) trait HandleAny: Send + Sync {
|
||||||
fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError>;
|
fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError>;
|
||||||
// async fn handle_async(&self, handle_args: HandleAnyArgs<Context>) -> Result<Value, RpcError>;
|
async fn handle_async(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError>;
|
||||||
|
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 method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
self.deref().method_from_dots(method, ctx_ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait CliBindingsAny {
|
pub(crate) trait CliBindingsAny {
|
||||||
fn cli_command(&self, ctx_ty: TypeId) -> Command;
|
fn cli_command(&self, ctx_ty: TypeId) -> Command;
|
||||||
fn cli_parse(
|
fn cli_parse(
|
||||||
&self,
|
&self,
|
||||||
@@ -97,11 +113,21 @@ pub trait PrintCliResult<Context: IntoContext>: Handler<Context> {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct WithCliBindings<Context, H> {
|
struct WithCliBindings<Context, H> {
|
||||||
_ctx: PhantomData<Context>,
|
_ctx: PhantomData<Context>,
|
||||||
handler: H,
|
handler: H,
|
||||||
}
|
}
|
||||||
|
impl<Context, H: Clone> Clone for WithCliBindings<Context, H> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
_ctx: PhantomData,
|
||||||
|
handler: self.handler.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl<Context, H> Handler<Context> for WithCliBindings<Context, H>
|
impl<Context, H> Handler<Context> for WithCliBindings<Context, H>
|
||||||
where
|
where
|
||||||
Context: IntoContext,
|
Context: IntoContext,
|
||||||
@@ -119,6 +145,7 @@ where
|
|||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
inherited_params,
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
}: HandleArgs<Context, Self>,
|
}: HandleArgs<Context, Self>,
|
||||||
) -> Result<Self::Ok, Self::Err> {
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
self.handler.handle_sync(HandleArgs {
|
self.handler.handle_sync(HandleArgs {
|
||||||
@@ -127,8 +154,31 @@ where
|
|||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
inherited_params,
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
}: HandleArgs<Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
self.handler
|
||||||
|
.handle_async(HandleArgs {
|
||||||
|
context,
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Context, H> CliBindings<Context> for WithCliBindings<Context, H>
|
impl<Context, H> CliBindings<Context> for WithCliBindings<Context, H>
|
||||||
@@ -162,6 +212,7 @@ where
|
|||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
inherited_params,
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
}: HandleArgs<Context, Self>,
|
}: HandleArgs<Context, Self>,
|
||||||
result: Self::Ok,
|
result: Self::Ok,
|
||||||
) -> Result<(), Self::Err> {
|
) -> Result<(), Self::Err> {
|
||||||
@@ -172,20 +223,22 @@ where
|
|||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
inherited_params,
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
},
|
},
|
||||||
result,
|
result,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HandleAnyWithCli: HandleAny + CliBindingsAny {}
|
pub(crate) trait HandleAnyWithCli: HandleAny + CliBindingsAny {}
|
||||||
impl<T: HandleAny + CliBindingsAny> HandleAnyWithCli for T {}
|
impl<T: HandleAny + CliBindingsAny> HandleAnyWithCli for T {}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum DynHandler {
|
pub(crate) enum DynHandler {
|
||||||
WithoutCli(Arc<dyn HandleAny>),
|
WithoutCli(Arc<dyn HandleAny>),
|
||||||
WithCli(Arc<dyn HandleAnyWithCli>),
|
WithCli(Arc<dyn HandleAnyWithCli>),
|
||||||
}
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl HandleAny for DynHandler {
|
impl HandleAny for DynHandler {
|
||||||
fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
||||||
match self {
|
match self {
|
||||||
@@ -193,32 +246,91 @@ impl HandleAny for DynHandler {
|
|||||||
DynHandler::WithCli(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 {
|
||||||
pub struct HandleArgs<Context: IntoContext, H: Handler<Context> + ?Sized> {
|
DynHandler::WithoutCli(h) => h.handle_async(handle_args).await,
|
||||||
context: Context,
|
DynHandler::WithCli(h) => h.handle_async(handle_args).await,
|
||||||
parent_method: Vec<&'static str>,
|
}
|
||||||
method: VecDeque<&'static str>,
|
}
|
||||||
params: H::Params,
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
inherited_params: H::InheritedParams,
|
match self {
|
||||||
}
|
DynHandler::WithoutCli(h) => h.method_from_dots(method, ctx_ty),
|
||||||
|
DynHandler::WithCli(h) => h.method_from_dots(method, ctx_ty),
|
||||||
pub trait Handler<Context: IntoContext> {
|
}
|
||||||
type Params;
|
|
||||||
type InheritedParams;
|
|
||||||
type Ok;
|
|
||||||
type Err;
|
|
||||||
fn handle_sync(&self, handle_args: HandleArgs<Context, Self>) -> Result<Self::Ok, Self::Err>;
|
|
||||||
fn contexts(&self) -> Option<BTreeSet<TypeId>> {
|
|
||||||
Context::type_ids_for(self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AnyHandler<Context, H> {
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct HandleArgs<Context: IntoContext, H: Handler<Context> + ?Sized> {
|
||||||
|
pub context: Context,
|
||||||
|
pub parent_method: Vec<&'static str>,
|
||||||
|
pub method: VecDeque<&'static str>,
|
||||||
|
pub params: H::Params,
|
||||||
|
pub inherited_params: H::InheritedParams,
|
||||||
|
pub raw_params: Value,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
pub trait Handler<Context: IntoContext>: Clone + Send + Sync + 'static {
|
||||||
|
type Params: Send + Sync;
|
||||||
|
type InheritedParams: Send + Sync;
|
||||||
|
type Ok: Send + Sync;
|
||||||
|
type Err: Send + Sync;
|
||||||
|
fn handle_sync(&self, handle_args: HandleArgs<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<Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err>;
|
||||||
|
async fn handle_async_with_sync(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
self.handle_sync(handle_args)
|
||||||
|
}
|
||||||
|
async fn handle_async_with_sync_blocking(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<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()
|
||||||
|
}
|
||||||
|
fn contexts(&self) -> Option<BTreeSet<TypeId>> {
|
||||||
|
Context::type_ids_for(self)
|
||||||
|
}
|
||||||
|
#[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<Context, H> {
|
||||||
_ctx: PhantomData<Context>,
|
_ctx: PhantomData<Context>,
|
||||||
handler: H,
|
handler: H,
|
||||||
}
|
}
|
||||||
|
impl<Context, H> AnyHandler<Context, H> {
|
||||||
|
pub(crate) fn new(handler: H) -> Self {
|
||||||
|
Self {
|
||||||
|
_ctx: PhantomData,
|
||||||
|
handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl<Context: IntoContext, H: Handler<Context>> HandleAny for AnyHandler<Context, H>
|
impl<Context: IntoContext, H: Handler<Context>> HandleAny for AnyHandler<Context, H>
|
||||||
where
|
where
|
||||||
H::Params: DeserializeOwned,
|
H::Params: DeserializeOwned,
|
||||||
@@ -234,11 +346,24 @@ where
|
|||||||
)
|
)
|
||||||
.map_err(internal_error)
|
.map_err(internal_error)
|
||||||
}
|
}
|
||||||
|
async fn handle_async(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
||||||
|
imbl_value::to_value(
|
||||||
|
&self
|
||||||
|
.handler
|
||||||
|
.handle_async(handle_args.downcast().map_err(invalid_params)?)
|
||||||
|
.await?,
|
||||||
|
)
|
||||||
|
.map_err(internal_error)
|
||||||
|
}
|
||||||
|
fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option<VecDeque<&'static str>> {
|
||||||
|
self.handler.method_from_dots(method, ctx_ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Context: IntoContext, H: CliBindings<Context>> CliBindingsAny for AnyHandler<Context, H>
|
impl<Context: IntoContext, H: CliBindings<Context>> CliBindingsAny for AnyHandler<Context, H>
|
||||||
where
|
where
|
||||||
H::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
H: CliBindings<Context>,
|
||||||
|
H::Params: DeserializeOwned,
|
||||||
H::InheritedParams: DeserializeOwned,
|
H::InheritedParams: DeserializeOwned,
|
||||||
H::Ok: Serialize + DeserializeOwned,
|
H::Ok: Serialize + DeserializeOwned,
|
||||||
RpcError: From<H::Err>,
|
RpcError: From<H::Err>,
|
||||||
@@ -270,14 +395,15 @@ pub struct NoParams {}
|
|||||||
pub enum Never {}
|
pub enum Never {}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
struct Name(Option<&'static str>);
|
pub(crate) struct Name(pub(crate) Option<&'static str>);
|
||||||
impl<'a> std::borrow::Borrow<Option<&'a str>> for Name {
|
impl<'a> std::borrow::Borrow<Option<&'a str>> for Name {
|
||||||
fn borrow(&self) -> &Option<&'a str> {
|
fn borrow(&self) -> &Option<&'a str> {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SubcommandMap(BTreeMap<Name, BTreeMap<Option<TypeId>, DynHandler>>);
|
#[derive(Clone)]
|
||||||
|
pub(crate) struct SubcommandMap(pub(crate) BTreeMap<Name, BTreeMap<Option<TypeId>, DynHandler>>);
|
||||||
impl SubcommandMap {
|
impl SubcommandMap {
|
||||||
fn insert(
|
fn insert(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -311,7 +437,7 @@ impl SubcommandMap {
|
|||||||
|
|
||||||
pub struct ParentHandler<Params = NoParams, InheritedParams = NoParams> {
|
pub struct ParentHandler<Params = NoParams, InheritedParams = NoParams> {
|
||||||
_phantom: PhantomData<(Params, InheritedParams)>,
|
_phantom: PhantomData<(Params, InheritedParams)>,
|
||||||
subcommands: SubcommandMap,
|
pub(crate) subcommands: SubcommandMap,
|
||||||
}
|
}
|
||||||
impl<Params, InheritedParams> ParentHandler<Params, InheritedParams> {
|
impl<Params, InheritedParams> ParentHandler<Params, InheritedParams> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@@ -321,24 +447,40 @@ impl<Params, InheritedParams> ParentHandler<Params, InheritedParams> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<Params, InheritedParams> Clone for ParentHandler<Params, InheritedParams> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
subcommands: self.subcommands.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct InheritanceHandler<
|
struct InheritanceHandler<Context, Params, InheritedParams, H, F> {
|
||||||
Context: IntoContext,
|
|
||||||
Params,
|
|
||||||
InheritedParams,
|
|
||||||
H: Handler<Context>,
|
|
||||||
F: Fn(Params, InheritedParams) -> H::InheritedParams,
|
|
||||||
> {
|
|
||||||
_phantom: PhantomData<(Context, Params, InheritedParams)>,
|
_phantom: PhantomData<(Context, Params, InheritedParams)>,
|
||||||
handler: H,
|
handler: H,
|
||||||
inherit: F,
|
inherit: F,
|
||||||
}
|
}
|
||||||
|
impl<Context, Params, InheritedParams, H: Clone, F: Clone> Clone
|
||||||
|
for InheritanceHandler<Context, Params, InheritedParams, H, F>
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
_phantom: PhantomData,
|
||||||
|
handler: self.handler.clone(),
|
||||||
|
inherit: self.inherit.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl<Context, Params, InheritedParams, H, F> Handler<Context>
|
impl<Context, Params, InheritedParams, H, F> Handler<Context>
|
||||||
for InheritanceHandler<Context, Params, InheritedParams, H, F>
|
for InheritanceHandler<Context, Params, InheritedParams, H, F>
|
||||||
where
|
where
|
||||||
Context: IntoContext,
|
Context: IntoContext,
|
||||||
|
Params: Send + Sync + 'static,
|
||||||
|
InheritedParams: Send + Sync + 'static,
|
||||||
H: Handler<Context>,
|
H: Handler<Context>,
|
||||||
F: Fn(Params, InheritedParams) -> H::InheritedParams,
|
F: Fn(Params, InheritedParams) -> H::InheritedParams + Send + Sync + Clone + 'static,
|
||||||
{
|
{
|
||||||
type Params = H::Params;
|
type Params = H::Params;
|
||||||
type InheritedParams = Flat<Params, InheritedParams>;
|
type InheritedParams = Flat<Params, InheritedParams>;
|
||||||
@@ -352,6 +494,7 @@ where
|
|||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
inherited_params,
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
}: HandleArgs<Context, Self>,
|
}: HandleArgs<Context, Self>,
|
||||||
) -> Result<Self::Ok, Self::Err> {
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
self.handler.handle_sync(HandleArgs {
|
self.handler.handle_sync(HandleArgs {
|
||||||
@@ -360,6 +503,27 @@ where
|
|||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
inherited_params: (self.inherit)(inherited_params.0, inherited_params.1),
|
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<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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,8 +532,10 @@ impl<Context, Params, InheritedParams, H, F> PrintCliResult<Context>
|
|||||||
for InheritanceHandler<Context, Params, InheritedParams, H, F>
|
for InheritanceHandler<Context, Params, InheritedParams, H, F>
|
||||||
where
|
where
|
||||||
Context: IntoContext,
|
Context: IntoContext,
|
||||||
|
Params: Send + Sync + 'static,
|
||||||
|
InheritedParams: Send + Sync + 'static,
|
||||||
H: Handler<Context> + PrintCliResult<Context>,
|
H: Handler<Context> + PrintCliResult<Context>,
|
||||||
F: Fn(Params, InheritedParams) -> H::InheritedParams,
|
F: Fn(Params, InheritedParams) -> H::InheritedParams + Send + Sync + Clone + 'static,
|
||||||
{
|
{
|
||||||
fn print(
|
fn print(
|
||||||
&self,
|
&self,
|
||||||
@@ -379,6 +545,7 @@ where
|
|||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
inherited_params,
|
inherited_params,
|
||||||
|
raw_params,
|
||||||
}: HandleArgs<Context, Self>,
|
}: HandleArgs<Context, Self>,
|
||||||
result: Self::Ok,
|
result: Self::Ok,
|
||||||
) -> Result<(), Self::Err> {
|
) -> Result<(), Self::Err> {
|
||||||
@@ -389,13 +556,14 @@ where
|
|||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
inherited_params: (self.inherit)(inherited_params.0, inherited_params.1),
|
inherited_params: (self.inherit)(inherited_params.0, inherited_params.1),
|
||||||
|
raw_params,
|
||||||
},
|
},
|
||||||
result,
|
result,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Params, InheritedParams> ParentHandler<Params, InheritedParams> {
|
impl<Params: Send + Sync, InheritedParams: Send + Sync> ParentHandler<Params, InheritedParams> {
|
||||||
pub fn subcommand<Context, H>(mut self, name: &'static str, handler: H) -> Self
|
pub fn subcommand<Context, H>(mut self, name: &'static str, handler: H) -> Self
|
||||||
where
|
where
|
||||||
Context: IntoContext,
|
Context: IntoContext,
|
||||||
@@ -436,7 +604,7 @@ impl<Params, InheritedParams> ParentHandler<Params, InheritedParams> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<Params, InheritedParams> ParentHandler<Params, InheritedParams>
|
impl<Params: Send + Sync, InheritedParams: Send + Sync> ParentHandler<Params, InheritedParams>
|
||||||
where
|
where
|
||||||
Params: DeserializeOwned + 'static,
|
Params: DeserializeOwned + 'static,
|
||||||
InheritedParams: DeserializeOwned + 'static,
|
InheritedParams: DeserializeOwned + 'static,
|
||||||
@@ -453,7 +621,7 @@ where
|
|||||||
H::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
H::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
||||||
H::Ok: Serialize + DeserializeOwned,
|
H::Ok: Serialize + DeserializeOwned,
|
||||||
RpcError: From<H::Err>,
|
RpcError: From<H::Err>,
|
||||||
F: Fn(Params, InheritedParams) -> H::InheritedParams + 'static,
|
F: Fn(Params, InheritedParams) -> H::InheritedParams + Send + Sync + Clone + 'static,
|
||||||
{
|
{
|
||||||
self.subcommands.insert(
|
self.subcommands.insert(
|
||||||
handler.contexts(),
|
handler.contexts(),
|
||||||
@@ -484,7 +652,7 @@ where
|
|||||||
H::Params: DeserializeOwned,
|
H::Params: DeserializeOwned,
|
||||||
H::Ok: Serialize,
|
H::Ok: Serialize,
|
||||||
RpcError: From<H::Err>,
|
RpcError: From<H::Err>,
|
||||||
F: Fn(Params, InheritedParams) -> H::InheritedParams + 'static,
|
F: Fn(Params, InheritedParams) -> H::InheritedParams + Send + Sync + Clone + 'static,
|
||||||
{
|
{
|
||||||
self.subcommands.insert(
|
self.subcommands.insert(
|
||||||
handler.contexts(),
|
handler.contexts(),
|
||||||
@@ -507,7 +675,7 @@ where
|
|||||||
H::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
H::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
||||||
H::Ok: Serialize + DeserializeOwned,
|
H::Ok: Serialize + DeserializeOwned,
|
||||||
RpcError: From<H::Err>,
|
RpcError: From<H::Err>,
|
||||||
F: Fn(Params, InheritedParams) -> H::InheritedParams + 'static,
|
F: Fn(Params, InheritedParams) -> H::InheritedParams + Send + Sync + Clone + 'static,
|
||||||
{
|
{
|
||||||
self.subcommands.insert(
|
self.subcommands.insert(
|
||||||
handler.contexts(),
|
handler.contexts(),
|
||||||
@@ -533,7 +701,7 @@ where
|
|||||||
H::Params: DeserializeOwned,
|
H::Params: DeserializeOwned,
|
||||||
H::Ok: Serialize,
|
H::Ok: Serialize,
|
||||||
RpcError: From<H::Err>,
|
RpcError: From<H::Err>,
|
||||||
F: Fn(Params, InheritedParams) -> H::InheritedParams + 'static,
|
F: Fn(Params, InheritedParams) -> H::InheritedParams + Send + Sync + Clone + 'static,
|
||||||
{
|
{
|
||||||
self.subcommands.insert(
|
self.subcommands.insert(
|
||||||
handler.contexts(),
|
handler.contexts(),
|
||||||
@@ -551,8 +719,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Params: Serialize, InheritedParams: Serialize> Handler<AnyContext>
|
#[async_trait::async_trait]
|
||||||
for ParentHandler<Params, InheritedParams>
|
impl<
|
||||||
|
Context: IntoContext,
|
||||||
|
Params: Serialize + Send + Sync + 'static,
|
||||||
|
InheritedParams: Serialize + Send + Sync + 'static,
|
||||||
|
> Handler<Context> for ParentHandler<Params, InheritedParams>
|
||||||
{
|
{
|
||||||
type Params = Params;
|
type Params = Params;
|
||||||
type InheritedParams = InheritedParams;
|
type InheritedParams = InheritedParams;
|
||||||
@@ -564,9 +736,9 @@ impl<Params: Serialize, InheritedParams: Serialize> Handler<AnyContext>
|
|||||||
context,
|
context,
|
||||||
mut parent_method,
|
mut parent_method,
|
||||||
mut method,
|
mut method,
|
||||||
params,
|
raw_params,
|
||||||
inherited_params,
|
..
|
||||||
}: HandleArgs<AnyContext, Self>,
|
}: HandleArgs<Context, Self>,
|
||||||
) -> Result<Self::Ok, Self::Err> {
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
let cmd = method.pop_front();
|
let cmd = method.pop_front();
|
||||||
if let Some(cmd) = cmd {
|
if let Some(cmd) = cmd {
|
||||||
@@ -577,13 +749,39 @@ impl<Params: Serialize, InheritedParams: Serialize> Handler<AnyContext>
|
|||||||
context: context.upcast(),
|
context: context.upcast(),
|
||||||
parent_method,
|
parent_method,
|
||||||
method,
|
method,
|
||||||
params: imbl_value::to_value(&Flat(params, inherited_params))
|
params: raw_params,
|
||||||
.map_err(invalid_params)?,
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
HandleArgs {
|
||||||
|
context,
|
||||||
|
mut parent_method,
|
||||||
|
mut method,
|
||||||
|
raw_params,
|
||||||
|
..
|
||||||
|
}: HandleArgs<Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
let cmd = method.pop_front();
|
||||||
|
if let Some(cmd) = cmd {
|
||||||
|
parent_method.push(cmd);
|
||||||
|
}
|
||||||
|
if let Some((_, sub_handler)) = self.subcommands.get(context.inner_type_id(), cmd) {
|
||||||
|
sub_handler
|
||||||
|
.handle_async(HandleAnyArgs {
|
||||||
|
context: context.upcast(),
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params: raw_params,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
} else {
|
||||||
|
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
fn contexts(&self) -> Option<BTreeSet<TypeId>> {
|
fn contexts(&self) -> Option<BTreeSet<TypeId>> {
|
||||||
let mut set = BTreeSet::new();
|
let mut set = BTreeSet::new();
|
||||||
for ctx_ty in self.subcommands.0.values().flat_map(|c| c.keys()) {
|
for ctx_ty in self.subcommands.0.values().flat_map(|c| c.keys()) {
|
||||||
@@ -591,12 +789,31 @@ impl<Params: Serialize, InheritedParams: Serialize> Handler<AnyContext>
|
|||||||
}
|
}
|
||||||
Some(set)
|
Some(set)
|
||||||
}
|
}
|
||||||
|
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<AnyContext> for ParentHandler<Params, InheritedParams>
|
impl<Params, InheritedParams> CliBindings<AnyContext> for ParentHandler<Params, InheritedParams>
|
||||||
where
|
where
|
||||||
Params: FromArgMatches + CommandFactory + Serialize,
|
Params: FromArgMatches + CommandFactory + Serialize + Send + Sync + 'static,
|
||||||
InheritedParams: Serialize,
|
InheritedParams: Serialize + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
fn cli_command(&self, ctx_ty: TypeId) -> Command {
|
fn cli_command(&self, ctx_ty: TypeId) -> Command {
|
||||||
let mut base = Params::command();
|
let mut base = Params::command();
|
||||||
@@ -648,8 +865,8 @@ where
|
|||||||
context,
|
context,
|
||||||
mut parent_method,
|
mut parent_method,
|
||||||
mut method,
|
mut method,
|
||||||
params,
|
raw_params,
|
||||||
inherited_params,
|
..
|
||||||
}: HandleArgs<AnyContext, Self>,
|
}: HandleArgs<AnyContext, Self>,
|
||||||
result: Self::Ok,
|
result: Self::Ok,
|
||||||
) -> Result<(), Self::Err> {
|
) -> Result<(), Self::Err> {
|
||||||
@@ -665,8 +882,7 @@ where
|
|||||||
context,
|
context,
|
||||||
parent_method,
|
parent_method,
|
||||||
method,
|
method,
|
||||||
params: imbl_value::to_value(&Flat(params, inherited_params))
|
params: raw_params,
|
||||||
.map_err(invalid_params)?,
|
|
||||||
},
|
},
|
||||||
result,
|
result,
|
||||||
)
|
)
|
||||||
@@ -679,19 +895,61 @@ where
|
|||||||
pub struct FromFn<F, T, E, Args> {
|
pub struct FromFn<F, T, E, Args> {
|
||||||
_phantom: PhantomData<(T, E, Args)>,
|
_phantom: PhantomData<(T, E, Args)>,
|
||||||
function: F,
|
function: F,
|
||||||
|
blocking: bool,
|
||||||
|
}
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_fn<F, T, E, Args>(function: F) -> FromFn<F, T, E, Args> {
|
pub fn from_fn<F, T, E, Args>(function: F) -> FromFn<F, T, E, Args> {
|
||||||
FromFn {
|
FromFn {
|
||||||
function,
|
function,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
|
blocking: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_fn_blocking<F, T, E, Args>(function: F) -> FromFn<F, T, E, Args> {
|
||||||
|
FromFn {
|
||||||
|
function,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
blocking: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FromFnAsync<F, Fut, T, E, Args> {
|
||||||
|
_phantom: PhantomData<(Fut, T, E, Args)>,
|
||||||
|
function: F,
|
||||||
|
}
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_fn_async<F, Fut, T, E, Args>(function: F) -> FromFnAsync<F, Fut, T, E, Args> {
|
||||||
|
FromFnAsync {
|
||||||
|
function,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl<Context, F, T, E> Handler<Context> for FromFn<F, T, E, ()>
|
impl<Context, F, T, E> Handler<Context> for FromFn<F, T, E, ()>
|
||||||
where
|
where
|
||||||
Context: IntoContext,
|
Context: IntoContext,
|
||||||
F: Fn() -> Result<T, E>,
|
F: Fn() -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
type Params = NoParams;
|
type Params = NoParams;
|
||||||
type InheritedParams = NoParams;
|
type InheritedParams = NoParams;
|
||||||
@@ -700,12 +958,42 @@ where
|
|||||||
fn handle_sync(&self, _: HandleArgs<Context, Self>) -> Result<Self::Ok, Self::Err> {
|
fn handle_sync(&self, _: HandleArgs<Context, Self>) -> Result<Self::Ok, Self::Err> {
|
||||||
(self.function)()
|
(self.function)()
|
||||||
}
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, Fut, T, E> Handler<Context> for FromFnAsync<F, Fut, T, E, ()>
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
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 fn handle_async(&self, _: HandleArgs<Context, Self>) -> Result<Self::Ok, Self::Err> {
|
||||||
|
(self.function)().await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl<Context, F, T, E> Handler<Context> for FromFn<F, T, E, (Context,)>
|
impl<Context, F, T, E> Handler<Context> for FromFn<F, T, E, (Context,)>
|
||||||
where
|
where
|
||||||
Context: IntoContext,
|
Context: IntoContext,
|
||||||
F: Fn(Context) -> Result<T, E>,
|
F: Fn(Context) -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
type Params = NoParams;
|
type Params = NoParams;
|
||||||
type InheritedParams = NoParams;
|
type InheritedParams = NoParams;
|
||||||
@@ -714,12 +1002,46 @@ where
|
|||||||
fn handle_sync(&self, handle_args: HandleArgs<Context, Self>) -> Result<Self::Ok, Self::Err> {
|
fn handle_sync(&self, handle_args: HandleArgs<Context, Self>) -> Result<Self::Ok, Self::Err> {
|
||||||
(self.function)(handle_args.context)
|
(self.function)(handle_args.context)
|
||||||
}
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, Fut, T, E> Handler<Context> 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 fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
(self.function)(handle_args.context).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl<Context, F, T, E, Params> Handler<Context> for FromFn<F, T, E, (Context, Params)>
|
impl<Context, F, T, E, Params> Handler<Context> for FromFn<F, T, E, (Context, Params)>
|
||||||
where
|
where
|
||||||
Context: IntoContext,
|
Context: IntoContext,
|
||||||
F: Fn(Context, Params) -> Result<T, E>,
|
F: Fn(Context, Params) -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
Params: DeserializeOwned,
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
type Params = Params;
|
type Params = Params;
|
||||||
type InheritedParams = NoParams;
|
type InheritedParams = NoParams;
|
||||||
@@ -731,14 +1053,53 @@ where
|
|||||||
} = handle_args;
|
} = handle_args;
|
||||||
(self.function)(context, params)
|
(self.function)(context, params)
|
||||||
}
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, Fut, T, E, Params> Handler<Context>
|
||||||
|
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 fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
let HandleArgs {
|
||||||
|
context, params, ..
|
||||||
|
} = handle_args;
|
||||||
|
(self.function)(context, params).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl<Context, F, T, E, Params, InheritedParams> Handler<Context>
|
impl<Context, F, T, E, Params, InheritedParams> Handler<Context>
|
||||||
for FromFn<F, T, E, (Context, Params, InheritedParams)>
|
for FromFn<F, T, E, (Context, Params, InheritedParams)>
|
||||||
where
|
where
|
||||||
Context: IntoContext,
|
Context: IntoContext,
|
||||||
F: Fn(Context, Params, InheritedParams) -> Result<T, E>,
|
F: Fn(Context, Params, InheritedParams) -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
Params: DeserializeOwned,
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
InheritedParams: DeserializeOwned,
|
InheritedParams: DeserializeOwned + Send + Sync + 'static,
|
||||||
|
T: Send + Sync + 'static,
|
||||||
|
E: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
type Params = Params;
|
type Params = Params;
|
||||||
type InheritedParams = InheritedParams;
|
type InheritedParams = InheritedParams;
|
||||||
@@ -753,44 +1114,43 @@ where
|
|||||||
} = handle_args;
|
} = handle_args;
|
||||||
(self.function)(context, params, inherited_params)
|
(self.function)(context, params, inherited_params)
|
||||||
}
|
}
|
||||||
|
async fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<Context, F, Fut, T, E, Params, InheritedParams> Handler<Context>
|
||||||
|
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 fn handle_async(
|
||||||
|
&self,
|
||||||
|
handle_args: HandleArgs<Context, Self>,
|
||||||
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
|
let HandleArgs {
|
||||||
|
context,
|
||||||
|
params,
|
||||||
|
inherited_params,
|
||||||
|
..
|
||||||
|
} = handle_args;
|
||||||
|
(self.function)(context, params, inherited_params).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
|
||||||
#[command(about = "this is db stuff")]
|
|
||||||
struct DbParams {}
|
|
||||||
|
|
||||||
// Server::new(
|
|
||||||
// ParentCommand::new()
|
|
||||||
// .subcommand("foo", from_fn(foo))
|
|
||||||
// .subcommand("db",
|
|
||||||
// ParentCommand::new::<DbParams>()
|
|
||||||
// .subcommand("dump", from_fn(dump))
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
|
|
||||||
// Server::new<Error = Error>()
|
|
||||||
// .handle(
|
|
||||||
// "db",
|
|
||||||
// with_description("Description maybe?")
|
|
||||||
// .handle("dump", from_fn(dump_route))
|
|
||||||
// )
|
|
||||||
// .handle(
|
|
||||||
// "server",
|
|
||||||
// no_description()
|
|
||||||
// .handle("version", from_fn(version))
|
|
||||||
// )
|
|
||||||
|
|
||||||
// #[derive(clap::Parser)]
|
|
||||||
// struct DumpParams {
|
|
||||||
// test: Option<String>
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dump_route(context: Context, param: Param<MyRouteParams>) -> Result<Value, Error> {
|
|
||||||
// Ok(json!({
|
|
||||||
// "db": {}
|
|
||||||
// }))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn version() -> &'static str {
|
|
||||||
// "1.0.0"
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// pub use cli::*;
|
pub use cli::*;
|
||||||
// pub use command::*;
|
// pub use command::*;
|
||||||
pub use context::*;
|
pub use context::*;
|
||||||
pub use handler::*;
|
pub use handler::*;
|
||||||
@@ -24,15 +24,11 @@ pub use handler::*;
|
|||||||
///
|
///
|
||||||
/// See also: [arg](rpc_toolkit_macro::arg), [context](rpc_toolkit_macro::context)
|
/// See also: [arg](rpc_toolkit_macro::arg), [context](rpc_toolkit_macro::context)
|
||||||
pub use rpc_toolkit_macro::command;
|
pub use rpc_toolkit_macro::command;
|
||||||
// pub use server::*;
|
pub use server::*;
|
||||||
pub use {clap, futures, hyper, reqwest, serde, serde_json, tokio, url, yajrc};
|
pub use {clap, futures, hyper, reqwest, serde, serde_json, tokio, url, yajrc};
|
||||||
|
|
||||||
// mod cli;
|
mod cli;
|
||||||
// mod command;
|
|
||||||
mod handler;
|
|
||||||
// pub mod command_helpers;
|
|
||||||
mod context;
|
mod context;
|
||||||
// mod metadata;
|
mod handler;
|
||||||
// pub mod rpc_server_helpers;
|
mod server;
|
||||||
// mod server;
|
|
||||||
mod util;
|
mod util;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pub trait Middleware<Context: crate::Context> {
|
|||||||
async fn process_rpc_request(
|
async fn process_rpc_request(
|
||||||
&self,
|
&self,
|
||||||
prev: Self::ProcessHttpRequestResult,
|
prev: Self::ProcessHttpRequestResult,
|
||||||
metadata: &Context::Metadata,
|
// metadata: &Context::Metadata,
|
||||||
req: &mut RpcRequest,
|
req: &mut RpcRequest,
|
||||||
) -> Result<Self::ProcessRpcRequestResult, RpcResponse>;
|
) -> Result<Self::ProcessRpcRequestResult, RpcResponse>;
|
||||||
type ProcessRpcResponseResult;
|
type ProcessRpcResponseResult;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
use std::borrow::Cow;
|
use std::any::TypeId;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use futures::future::{join_all, BoxFuture};
|
use futures::future::{join_all, BoxFuture};
|
||||||
use futures::{Future, FutureExt, Stream, StreamExt};
|
use futures::{Future, FutureExt, Stream, StreamExt};
|
||||||
use imbl_value::Value;
|
use imbl_value::Value;
|
||||||
use yajrc::{AnyParams, AnyRpcMethod, RpcError, RpcMethod};
|
use yajrc::{RpcError, RpcMethod};
|
||||||
|
|
||||||
use crate::util::{invalid_request, JobRunner};
|
use crate::util::{invalid_request, JobRunner};
|
||||||
use crate::DynCommand;
|
use crate::{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>;
|
||||||
@@ -20,41 +20,21 @@ mod socket;
|
|||||||
pub use http::*;
|
pub use http::*;
|
||||||
pub use socket::*;
|
pub use socket::*;
|
||||||
|
|
||||||
impl<Context: crate::Context> DynCommand<Context> {
|
|
||||||
fn cmd_from_method(
|
|
||||||
&self,
|
|
||||||
method: &[&str],
|
|
||||||
parent_method: Vec<&'static str>,
|
|
||||||
) -> Result<(Vec<&'static str>, &DynCommand<Context>), RpcError> {
|
|
||||||
let mut ret_method = parent_method;
|
|
||||||
ret_method.push(self.name);
|
|
||||||
if let Some((cmd, rest)) = method.split_first() {
|
|
||||||
self.subcommands
|
|
||||||
.iter()
|
|
||||||
.find(|c| c.name == *cmd)
|
|
||||||
.ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?
|
|
||||||
.cmd_from_method(rest, ret_method)
|
|
||||||
} else {
|
|
||||||
Ok((ret_method, self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Server<Context: crate::Context> {
|
pub struct Server<Context: crate::Context> {
|
||||||
commands: Vec<DynCommand<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>>,
|
||||||
}
|
}
|
||||||
impl<Context: crate::Context> Server<Context> {
|
impl<Context: crate::Context> Server<Context> {
|
||||||
pub fn new<
|
pub fn new<
|
||||||
F: Fn() -> Fut + Send + Sync + 'static,
|
MakeCtx: Fn() -> Fut + Send + Sync + 'static,
|
||||||
Fut: Future<Output = Result<Context, RpcError>> + Send + 'static,
|
Fut: Future<Output = Result<Context, RpcError>> + Send + 'static,
|
||||||
>(
|
>(
|
||||||
commands: Vec<DynCommand<Context>>,
|
make_ctx: MakeCtx,
|
||||||
make_ctx: F,
|
root_handler: ParentHandler,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Server {
|
Server {
|
||||||
commands,
|
|
||||||
make_ctx: Arc::new(move || make_ctx().boxed()),
|
make_ctx: Arc::new(move || make_ctx().boxed()),
|
||||||
|
root_handler: Arc::new(AnyHandler::new(root_handler)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,30 +43,22 @@ impl<Context: crate::Context> Server<Context> {
|
|||||||
method: &str,
|
method: &str,
|
||||||
params: Value,
|
params: Value,
|
||||||
) -> impl Future<Output = Result<Value, RpcError>> + Send + 'static {
|
) -> impl Future<Output = Result<Value, RpcError>> + Send + 'static {
|
||||||
let from_self = (|| {
|
let (make_ctx, root_handler, method) = (
|
||||||
let method: Vec<_> = method.split(".").collect();
|
self.make_ctx.clone(),
|
||||||
let (cmd, rest) = method.split_first().ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?;
|
self.root_handler.clone(),
|
||||||
let (method, cmd) = self
|
self.root_handler
|
||||||
.commands
|
.method_from_dots(method, TypeId::of::<Context>()),
|
||||||
.iter()
|
);
|
||||||
.find(|c| c.name == *cmd)
|
|
||||||
.ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?
|
|
||||||
.cmd_from_method(rest, Vec::new())?;
|
|
||||||
Ok::<_, RpcError>((
|
|
||||||
cmd.implementation
|
|
||||||
.as_ref()
|
|
||||||
.ok_or(yajrc::METHOD_NOT_FOUND_ERROR)?
|
|
||||||
.async_impl
|
|
||||||
.clone(),
|
|
||||||
self.make_ctx.clone(),
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
))
|
|
||||||
})();
|
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let (implementation, make_ctx, method, params) = from_self?;
|
root_handler
|
||||||
implementation(make_ctx().await?, method, params).await
|
.handle_async(HandleAnyArgs {
|
||||||
|
context: make_ctx().await?.upcast(),
|
||||||
|
parent_method: Vec::new(),
|
||||||
|
method: method.ok_or_else(|| yajrc::METHOD_NOT_FOUND_ERROR)?,
|
||||||
|
params,
|
||||||
|
})
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,10 +69,8 @@ impl Context for CliContext {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
fn make_api() -> ParentHandler<CliContext> {
|
fn make_api() -> ParentHandler<CliContext> {
|
||||||
ParentHandler::new().subcommand_no_cli(
|
ParentHandler::new()
|
||||||
Some("hello"),
|
.subcommand_no_cli("hello", from_fn(|_: CliContext| Ok::<_, RpcError>("world")))
|
||||||
from_fn(|_: CliContext| Ok::<_, RpcError>("world")),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn internal_error(e: impl Display) -> RpcError {
|
pub fn internal_error(e: impl Display) -> RpcError {
|
||||||
|
|||||||
Reference in New Issue
Block a user