mirror of
https://github.com/Start9Labs/rpc-toolkit.git
synced 2026-03-30 12:21:58 +00:00
wip
This commit is contained in:
@@ -1,8 +1,110 @@
|
|||||||
use std::any::Any;
|
use std::any::{Any, TypeId};
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
|
|
||||||
|
use crate::Handler;
|
||||||
|
|
||||||
pub trait Context: Any + Send + 'static {
|
pub trait Context: Any + Send + 'static {
|
||||||
fn runtime(&self) -> Handle {
|
fn runtime(&self) -> Handle {
|
||||||
Handle::current()
|
Handle::current()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(private_bounds)]
|
||||||
|
pub trait IntoContext: sealed::Sealed + Any + Send + Sized + 'static {
|
||||||
|
fn type_ids_for<H: Handler<Self> + ?Sized>(handler: &H) -> Option<BTreeSet<TypeId>>;
|
||||||
|
fn inner_type_id(&self) -> TypeId;
|
||||||
|
fn upcast(self) -> AnyContext;
|
||||||
|
fn downcast(value: AnyContext) -> Result<Self, AnyContext>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: Context + Sized> IntoContext for C {
|
||||||
|
fn type_ids_for<H: Handler<Self> + ?Sized>(handler: &H) -> Option<BTreeSet<TypeId>> {
|
||||||
|
let mut set = BTreeSet::new();
|
||||||
|
set.insert(TypeId::of::<C>());
|
||||||
|
Some(set)
|
||||||
|
}
|
||||||
|
fn inner_type_id(&self) -> TypeId {
|
||||||
|
TypeId::of::<C>()
|
||||||
|
}
|
||||||
|
fn upcast(self) -> AnyContext {
|
||||||
|
AnyContext::new(self)
|
||||||
|
}
|
||||||
|
fn downcast(value: AnyContext) -> Result<Self, AnyContext> {
|
||||||
|
if value.0.type_id() == TypeId::of::<C>() {
|
||||||
|
unsafe { Ok(value.downcast_unchecked::<C>()) }
|
||||||
|
} else {
|
||||||
|
Err(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum EitherContext<C1, C2> {
|
||||||
|
C1(C1),
|
||||||
|
C2(C2),
|
||||||
|
}
|
||||||
|
impl<C1: Context, C2: Context> IntoContext for EitherContext<C1, C2> {
|
||||||
|
fn type_ids_for<H: Handler<Self> + ?Sized>(handler: &H) -> Option<BTreeSet<TypeId>> {
|
||||||
|
let mut set = BTreeSet::new();
|
||||||
|
set.insert(TypeId::of::<C1>());
|
||||||
|
set.insert(TypeId::of::<C2>());
|
||||||
|
Some(set)
|
||||||
|
}
|
||||||
|
fn inner_type_id(&self) -> TypeId {
|
||||||
|
match self {
|
||||||
|
EitherContext::C1(c) => c.type_id(),
|
||||||
|
EitherContext::C2(c) => c.type_id(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn downcast(value: AnyContext) -> Result<Self, AnyContext> {
|
||||||
|
if value.inner_type_id() == TypeId::of::<C1>() {
|
||||||
|
Ok(EitherContext::C1(C1::downcast(value)?))
|
||||||
|
} else if value.inner_type_id() == TypeId::of::<C2>() {
|
||||||
|
Ok(EitherContext::C2(C2::downcast(value)?))
|
||||||
|
} else {
|
||||||
|
Err(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn upcast(self) -> AnyContext {
|
||||||
|
match self {
|
||||||
|
Self::C1(c) => AnyContext::new(c),
|
||||||
|
Self::C2(c) => AnyContext::new(c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AnyContext(Box<dyn Context>);
|
||||||
|
impl AnyContext {
|
||||||
|
pub fn new<C: Context>(value: C) -> Self {
|
||||||
|
Self(Box::new(value))
|
||||||
|
}
|
||||||
|
unsafe fn downcast_unchecked<C: Context>(self) -> C {
|
||||||
|
unsafe {
|
||||||
|
let raw: *mut dyn Context = Box::into_raw(self.0);
|
||||||
|
*Box::from_raw(raw as *mut C)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoContext for AnyContext {
|
||||||
|
fn type_ids_for<H: Handler<Self> + ?Sized>(_: &H) -> Option<BTreeSet<TypeId>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn inner_type_id(&self) -> TypeId {
|
||||||
|
self.0.type_id()
|
||||||
|
}
|
||||||
|
fn downcast(value: AnyContext) -> Result<Self, AnyContext> {
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
fn upcast(self) -> AnyContext {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod sealed {
|
||||||
|
pub(crate) trait Sealed {}
|
||||||
|
impl<C: super::Context> Sealed for C {}
|
||||||
|
impl<C1: super::Context, C2: super::Context> Sealed for super::EitherContext<C1, C2> {}
|
||||||
|
impl Sealed for super::AnyContext {}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use std::collections::{BTreeMap, VecDeque};
|
use std::any::TypeId;
|
||||||
|
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use clap::{ArgMatches, Command, CommandFactory, FromArgMatches, Parser};
|
use clap::{ArgMatches, Command, CommandFactory, FromArgMatches, Parser};
|
||||||
use imbl_value::Value;
|
use imbl_value::Value;
|
||||||
@@ -7,16 +9,18 @@ use serde::de::DeserializeOwned;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use yajrc::RpcError;
|
use yajrc::RpcError;
|
||||||
|
|
||||||
|
use crate::context::{AnyContext, IntoContext};
|
||||||
|
use crate::handler;
|
||||||
use crate::util::{combine, internal_error, invalid_params, Flat};
|
use crate::util::{combine, internal_error, invalid_params, Flat};
|
||||||
|
|
||||||
struct HandleAnyArgs {
|
struct HandleAnyArgs {
|
||||||
context: Box<dyn crate::Context>,
|
context: AnyContext,
|
||||||
parent_method: Vec<&'static str>,
|
parent_method: Vec<&'static str>,
|
||||||
method: VecDeque<&'static str>,
|
method: VecDeque<&'static str>,
|
||||||
params: Value,
|
params: Value,
|
||||||
}
|
}
|
||||||
impl HandleAnyArgs {
|
impl HandleAnyArgs {
|
||||||
fn downcast<Context: crate::Context, H>(self) -> Result<HandleArgs<Context, H>, imbl_value::Error>
|
fn downcast<Context: IntoContext, H>(self) -> Result<HandleArgs<Context, H>, imbl_value::Error>
|
||||||
where
|
where
|
||||||
H: Handler<Context>,
|
H: Handler<Context>,
|
||||||
H::Params: DeserializeOwned,
|
H::Params: DeserializeOwned,
|
||||||
@@ -29,38 +33,34 @@ impl HandleAnyArgs {
|
|||||||
params,
|
params,
|
||||||
} = self;
|
} = self;
|
||||||
Ok(HandleArgs {
|
Ok(HandleArgs {
|
||||||
context,
|
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,
|
parent_method,
|
||||||
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())?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}rams.clone())?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
trait HandleAny<Context: crate::Context> {
|
trait HandleAny {
|
||||||
fn handle_sync(&self, handle_args: HandleAnyArgs<Context>) -> 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<Context>) -> Result<Value, RpcError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait CliBindingsAny<Context: crate::Context> {
|
trait CliBindingsAny {
|
||||||
fn cli_command(&self) -> Command;
|
fn cli_command(&self) -> Command;
|
||||||
fn cli_parse(
|
fn cli_parse(
|
||||||
&self,
|
&self,
|
||||||
matches: &ArgMatches,
|
matches: &ArgMatches,
|
||||||
) -> Result<(VecDeque<&'static str>, Value), clap::Error>;
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error>;
|
||||||
fn cli_display(
|
fn cli_display(&self, handle_args: HandleAnyArgs, result: Value) -> Result<(), RpcError>;
|
||||||
&self,
|
|
||||||
handle_args: HandleAnyArgs<Context>,
|
|
||||||
result: Value,
|
|
||||||
) -> Result<(), RpcError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CliBindings<Context: crate::Context>: Handler<Context> {
|
pub trait CliBindings<Context: IntoContext>: Handler<Context> {
|
||||||
fn cli_command(&self) -> Command;
|
fn cli_command(&self) -> Command;
|
||||||
fn cli_parse(
|
fn cli_parse(
|
||||||
&self,
|
&self,
|
||||||
@@ -73,7 +73,7 @@ pub trait CliBindings<Context: crate::Context>: Handler<Context> {
|
|||||||
) -> Result<(), Self::Err>;
|
) -> Result<(), Self::Err>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PrintCliResult<Context: crate::Context>: Handler<Context> {
|
pub trait PrintCliResult<Context: IntoContext>: Handler<Context> {
|
||||||
fn print(
|
fn print(
|
||||||
&self,
|
&self,
|
||||||
handle_args: HandleArgs<Context, Self>,
|
handle_args: HandleArgs<Context, Self>,
|
||||||
@@ -83,7 +83,7 @@ pub trait PrintCliResult<Context: crate::Context>: Handler<Context> {
|
|||||||
|
|
||||||
// impl<Context, H> PrintCliResult<Context> for H
|
// impl<Context, H> PrintCliResult<Context> for H
|
||||||
// where
|
// where
|
||||||
// Context: crate::Context,
|
// Context: IntoContext,
|
||||||
// H: Handler<Context>,
|
// H: Handler<Context>,
|
||||||
// H::Ok: Display,
|
// H::Ok: Display,
|
||||||
// {
|
// {
|
||||||
@@ -103,7 +103,7 @@ struct WithCliBindings<Context, H> {
|
|||||||
|
|
||||||
impl<Context, H> Handler<Context> for WithCliBindings<Context, H>
|
impl<Context, H> Handler<Context> for WithCliBindings<Context, H>
|
||||||
where
|
where
|
||||||
Context: crate::Context,
|
Context: IntoContext,
|
||||||
H: Handler<Context>,
|
H: Handler<Context>,
|
||||||
{
|
{
|
||||||
type Params = H::Params;
|
type Params = H::Params;
|
||||||
@@ -132,7 +132,7 @@ where
|
|||||||
|
|
||||||
impl<Context, H> CliBindings<Context> for WithCliBindings<Context, H>
|
impl<Context, H> CliBindings<Context> for WithCliBindings<Context, H>
|
||||||
where
|
where
|
||||||
Context: crate::Context,
|
Context: IntoContext,
|
||||||
H: Handler<Context>,
|
H: Handler<Context>,
|
||||||
H::Params: FromArgMatches + CommandFactory + Serialize,
|
H::Params: FromArgMatches + CommandFactory + Serialize,
|
||||||
H: PrintCliResult<Context>,
|
H: PrintCliResult<Context>,
|
||||||
@@ -176,18 +176,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HandleAnyWithCli<Context: crate::Context>: HandleAny<Context> + CliBindingsAny<Context> {}
|
trait HandleAnyWithCli: HandleAny + CliBindingsAny {}
|
||||||
impl<Context: crate::Context, T: HandleAny<Context> + CliBindingsAny<Context>>
|
impl<T: HandleAny + CliBindingsAny> HandleAnyWithCli for T {}
|
||||||
HandleAnyWithCli<Context> for T
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
enum DynHandler<Context> {
|
#[derive(Clone)]
|
||||||
WithoutCli(Box<dyn HandleAny<Context>>),
|
enum DynHandler {
|
||||||
WithCli(Box<dyn HandleAnyWithCli<Context>>),
|
WithoutCli(Arc<dyn HandleAny>),
|
||||||
|
WithCli(Arc<dyn HandleAnyWithCli>),
|
||||||
}
|
}
|
||||||
impl<Context: crate::Context> HandleAny<Context> for DynHandler<Context> {
|
impl HandleAny for DynHandler {
|
||||||
fn handle_sync(&self, handle_args: HandleAnyArgs<Context>) -> Result<Value, RpcError> {
|
fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
||||||
match self {
|
match self {
|
||||||
DynHandler::WithoutCli(h) => h.handle_sync(handle_args),
|
DynHandler::WithoutCli(h) => h.handle_sync(handle_args),
|
||||||
DynHandler::WithCli(h) => h.handle_sync(handle_args),
|
DynHandler::WithCli(h) => h.handle_sync(handle_args),
|
||||||
@@ -195,47 +193,23 @@ impl<Context: crate::Context> HandleAny<Context> for DynHandler<Context> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HandleArgs<Context: crate::Context, H: Handler<Context> + ?Sized> {
|
pub struct HandleArgs<Context: IntoContext, H: Handler<Context> + ?Sized> {
|
||||||
context: Context,
|
context: Context,
|
||||||
parent_method: Vec<&'static str>,
|
parent_method: Vec<&'static str>,
|
||||||
method: VecDeque<&'static str>,
|
method: VecDeque<&'static str>,
|
||||||
params: H::Params,
|
params: H::Params,
|
||||||
inherited_params: H::InheritedParams,
|
inherited_params: H::InheritedParams,
|
||||||
}
|
}
|
||||||
impl<Context, H> HandleArgs<Context, H>
|
|
||||||
where
|
|
||||||
Context: crate::Context,
|
|
||||||
H: Handler<Context>,
|
|
||||||
H::Params: Serialize,
|
|
||||||
H::InheritedParams: Serialize,
|
|
||||||
{
|
|
||||||
fn upcast(
|
|
||||||
Self {
|
|
||||||
context,
|
|
||||||
parent_method,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
inherited_params,
|
|
||||||
}: Self,
|
|
||||||
) -> Result<HandleAnyArgs<Context>, imbl_value::Error> {
|
|
||||||
Ok(HandleAnyArgs {
|
|
||||||
context,
|
|
||||||
parent_method,
|
|
||||||
method,
|
|
||||||
params: combine(
|
|
||||||
imbl_value::to_value(¶ms)?,
|
|
||||||
imbl_value::to_value(&inherited_params)?,
|
|
||||||
)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Handler<Context: crate::Context> {
|
pub trait Handler<Context: IntoContext> {
|
||||||
type Params;
|
type Params;
|
||||||
type InheritedParams;
|
type InheritedParams;
|
||||||
type Ok;
|
type Ok;
|
||||||
type Err;
|
type Err;
|
||||||
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>;
|
||||||
|
fn contexts(&self) -> Option<BTreeSet<TypeId>> {
|
||||||
|
Context::type_ids_for(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AnyHandler<Context, H> {
|
struct AnyHandler<Context, H> {
|
||||||
@@ -243,14 +217,14 @@ struct AnyHandler<Context, H> {
|
|||||||
handler: H,
|
handler: H,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Context: crate::Context, H: Handler<Context>> HandleAny<Context> for AnyHandler<Context, H>
|
impl<Context: IntoContext, H: Handler<Context>> HandleAny for AnyHandler<Context, H>
|
||||||
where
|
where
|
||||||
H::Params: DeserializeOwned,
|
H::Params: DeserializeOwned,
|
||||||
H::InheritedParams: DeserializeOwned,
|
H::InheritedParams: DeserializeOwned,
|
||||||
H::Ok: Serialize,
|
H::Ok: Serialize,
|
||||||
RpcError: From<H::Err>,
|
RpcError: From<H::Err>,
|
||||||
{
|
{
|
||||||
fn handle_sync(&self, handle_args: HandleAnyArgs<Context>) -> Result<Value, RpcError> {
|
fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result<Value, RpcError> {
|
||||||
imbl_value::to_value(
|
imbl_value::to_value(
|
||||||
&self
|
&self
|
||||||
.handler
|
.handler
|
||||||
@@ -260,8 +234,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Context: crate::Context, H: CliBindings<Context>> CliBindingsAny<Context>
|
impl<Context: IntoContext, H: CliBindings<Context>> CliBindingsAny for AnyHandler<Context, H>
|
||||||
for AnyHandler<Context, H>
|
|
||||||
where
|
where
|
||||||
H::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
H::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
||||||
H::InheritedParams: DeserializeOwned,
|
H::InheritedParams: DeserializeOwned,
|
||||||
@@ -277,11 +250,7 @@ where
|
|||||||
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
||||||
self.handler.cli_parse(matches)
|
self.handler.cli_parse(matches)
|
||||||
}
|
}
|
||||||
fn cli_display(
|
fn cli_display(&self, handle_args: HandleAnyArgs, result: Value) -> Result<(), RpcError> {
|
||||||
&self,
|
|
||||||
handle_args: HandleAnyArgs<Context>,
|
|
||||||
result: Value,
|
|
||||||
) -> Result<(), RpcError> {
|
|
||||||
self.handler
|
self.handler
|
||||||
.cli_display(
|
.cli_display(
|
||||||
handle_args.downcast().map_err(invalid_params)?,
|
handle_args.downcast().map_err(invalid_params)?,
|
||||||
@@ -295,83 +264,83 @@ where
|
|||||||
pub struct NoParams {}
|
pub struct NoParams {}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)]
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)]
|
||||||
enum Never {}
|
pub enum Never {}
|
||||||
|
|
||||||
pub(crate) struct EmptyHandler<Params = NoParams, InheritedParams = NoParams>(
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
PhantomData<(Params, InheritedParams)>,
|
struct Name(Option<&'static str>);
|
||||||
);
|
impl<'a> std::borrow::Borrow<Option<&'a str>> for Name {
|
||||||
impl<Context: crate::Context, Params, InheritedParams> Handler<Context>
|
fn borrow(&self) -> &Option<&'a str> {
|
||||||
for EmptyHandler<Params, InheritedParams>
|
&self.0
|
||||||
{
|
|
||||||
type Params = Params;
|
|
||||||
type InheritedParams = InheritedParams;
|
|
||||||
type Ok = Never;
|
|
||||||
type Err = RpcError;
|
|
||||||
fn handle_sync(&self, _: HandleArgs<Context, Self>) -> Result<Self::Ok, Self::Err> {
|
|
||||||
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ParentHandler<Context: crate::Context, H: Handler<Context> = EmptyHandler> {
|
struct SubcommandMap(BTreeMap<Name, BTreeMap<Option<TypeId>, DynHandler>>);
|
||||||
handler: H,
|
impl SubcommandMap {
|
||||||
subcommands: BTreeMap<&'static str, DynHandler<Context>>,
|
fn insert(
|
||||||
|
&mut self,
|
||||||
|
ctx_tys: Option<BTreeSet<TypeId>>,
|
||||||
|
name: Option<&'static str>,
|
||||||
|
handler: DynHandler,
|
||||||
|
) {
|
||||||
|
let mut for_name = self.0.remove(&name).unwrap_or_default();
|
||||||
|
if let Some(ctx_tys) = ctx_tys {
|
||||||
|
for ctx_ty in ctx_tys {
|
||||||
|
for_name.insert(Some(ctx_ty), handler.clone());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for_name.insert(None, 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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl<Context: crate::Context> ParentHandler<Context>
|
|
||||||
where
|
pub struct ParentHandler<Params = NoParams, InheritedParams = NoParams> {
|
||||||
EmptyHandler: CliBindings<Context>,
|
_phantom: PhantomData<(Params, InheritedParams)>,
|
||||||
{
|
subcommands: SubcommandMap,
|
||||||
|
}
|
||||||
|
impl<Params, InheritedParams> ParentHandler<Params, InheritedParams> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
handler: WithCliBindings {
|
_phantom: PhantomData,
|
||||||
_ctx: PhantomData,
|
subcommands: SubcommandMap(BTreeMap::new()),
|
||||||
handler: EmptyHandler(PhantomData).into(),
|
|
||||||
},
|
|
||||||
subcommands: BTreeMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Context: crate::Context, Params, InheritedParams>
|
|
||||||
ParentHandler<Context, EmptyHandler<Params, InheritedParams>>
|
|
||||||
{
|
|
||||||
pub fn new_no_cli() -> Self {
|
|
||||||
Self {
|
|
||||||
handler: EmptyHandler(PhantomData).into(),
|
|
||||||
subcommands: BTreeMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Context: crate::Context, H: Handler<Context>> From<H> for ParentHandler<Context, H> {
|
|
||||||
fn from(value: H) -> Self {
|
|
||||||
Self {
|
|
||||||
handler: value.into(),
|
|
||||||
subcommands: BTreeMap::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InheritanceHandler<
|
struct InheritanceHandler<
|
||||||
Context: crate::Context,
|
Context: IntoContext,
|
||||||
|
Params,
|
||||||
|
InheritedParams,
|
||||||
H: Handler<Context>,
|
H: Handler<Context>,
|
||||||
SubH: Handler<Context>,
|
F: Fn(Params, InheritedParams) -> H::InheritedParams,
|
||||||
F: Fn(H::Params, H::InheritedParams) -> SubH::InheritedParams,
|
|
||||||
> {
|
> {
|
||||||
_phantom: PhantomData<(Context, H)>,
|
_phantom: PhantomData<(Context, Params, InheritedParams)>,
|
||||||
handler: SubH,
|
handler: H,
|
||||||
inherit: F,
|
inherit: F,
|
||||||
}
|
}
|
||||||
impl<
|
impl<Context, Params, InheritedParams, H, F> Handler<Context>
|
||||||
Context: crate::Context,
|
for InheritanceHandler<Context, Params, InheritedParams, H, F>
|
||||||
H: Handler<Context>,
|
where
|
||||||
SubH: Handler<Context>,
|
Context: IntoContext,
|
||||||
F: Fn(H::Params, H::InheritedParams) -> SubH::InheritedParams,
|
H: Handler<Context>,
|
||||||
> Handler<Context> for InheritanceHandler<Context, H, SubH, F>
|
F: Fn(Params, InheritedParams) -> H::InheritedParams,
|
||||||
{
|
{
|
||||||
type Params = SubH::Params;
|
type Params = H::Params;
|
||||||
type InheritedParams = Flat<H::Params, H::InheritedParams>;
|
type InheritedParams = Flat<Params, InheritedParams>;
|
||||||
type Ok = SubH::Ok;
|
type Ok = H::Ok;
|
||||||
type Err = SubH::Err;
|
type Err = H::Err;
|
||||||
fn handle_sync(
|
fn handle_sync(
|
||||||
&self,
|
&self,
|
||||||
HandleArgs {
|
HandleArgs {
|
||||||
@@ -392,12 +361,12 @@ impl<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Context, H, SubH, F> PrintCliResult<Context> for InheritanceHandler<Context, H, SubH, F>
|
impl<Context, Params, InheritedParams, H, F> PrintCliResult<Context>
|
||||||
|
for InheritanceHandler<Context, Params, InheritedParams, H, F>
|
||||||
where
|
where
|
||||||
Context: crate::Context,
|
Context: IntoContext,
|
||||||
H: Handler<Context>,
|
H: Handler<Context> + PrintCliResult<Context>,
|
||||||
SubH: Handler<Context> + PrintCliResult<Context>,
|
F: Fn(Params, InheritedParams) -> H::InheritedParams,
|
||||||
F: Fn(H::Params, H::InheritedParams) -> SubH::InheritedParams,
|
|
||||||
{
|
{
|
||||||
fn print(
|
fn print(
|
||||||
&self,
|
&self,
|
||||||
@@ -423,17 +392,19 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Context: crate::Context, H: Handler<Context>> ParentHandler<Context, H> {
|
impl<Params, InheritedParams> ParentHandler<Params, InheritedParams> {
|
||||||
pub fn subcommand<SubH>(mut self, method: &'static str, handler: SubH) -> Self
|
pub fn subcommand<Context, H>(mut self, name: Option<&'static str>, handler: H) -> Self
|
||||||
where
|
where
|
||||||
SubH: Handler<Context, InheritedParams = NoParams> + PrintCliResult<Context> + 'static,
|
Context: IntoContext,
|
||||||
SubH::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
H: Handler<Context, InheritedParams = NoParams> + PrintCliResult<Context> + 'static,
|
||||||
SubH::Ok: Serialize + DeserializeOwned,
|
H::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
||||||
RpcError: From<SubH::Err>,
|
H::Ok: Serialize + DeserializeOwned,
|
||||||
|
RpcError: From<H::Err>,
|
||||||
{
|
{
|
||||||
self.subcommands.insert(
|
self.subcommands.insert(
|
||||||
method,
|
handler.contexts(),
|
||||||
DynHandler::WithCli(Box::new(AnyHandler {
|
name,
|
||||||
|
DynHandler::WithCli(Arc::new(AnyHandler {
|
||||||
_ctx: PhantomData,
|
_ctx: PhantomData,
|
||||||
handler: WithCliBindings {
|
handler: WithCliBindings {
|
||||||
_ctx: PhantomData,
|
_ctx: PhantomData,
|
||||||
@@ -443,29 +414,52 @@ impl<Context: crate::Context, H: Handler<Context>> ParentHandler<Context, H> {
|
|||||||
);
|
);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn subcommand_with_inherited<SubH, F>(
|
pub fn subcommand_no_cli<Context, H>(mut self, name: Option<&'static str>, handler: H) -> Self
|
||||||
|
where
|
||||||
|
Context: IntoContext,
|
||||||
|
H: Handler<Context, InheritedParams = NoParams> + 'static,
|
||||||
|
H::Params: DeserializeOwned,
|
||||||
|
H::Ok: Serialize,
|
||||||
|
RpcError: From<H::Err>,
|
||||||
|
{
|
||||||
|
self.subcommands.insert(
|
||||||
|
handler.contexts(),
|
||||||
|
name,
|
||||||
|
DynHandler::WithoutCli(Arc::new(AnyHandler {
|
||||||
|
_ctx: PhantomData,
|
||||||
|
handler,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Params, InheritedParams> ParentHandler<Params, InheritedParams>
|
||||||
|
where
|
||||||
|
Params: DeserializeOwned + 'static,
|
||||||
|
InheritedParams: DeserializeOwned + 'static,
|
||||||
|
{
|
||||||
|
pub fn subcommand_with_inherited<Context, H, F>(
|
||||||
mut self,
|
mut self,
|
||||||
method: &'static str,
|
name: Option<&'static str>,
|
||||||
handler: SubH,
|
handler: H,
|
||||||
inherit: F,
|
inherit: F,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
SubH: Handler<Context> + PrintCliResult<Context> + 'static,
|
Context: IntoContext,
|
||||||
SubH::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
H: Handler<Context> + PrintCliResult<Context> + 'static,
|
||||||
SubH::Ok: Serialize + DeserializeOwned,
|
H::Params: FromArgMatches + CommandFactory + Serialize + DeserializeOwned,
|
||||||
H: 'static,
|
H::Ok: Serialize + DeserializeOwned,
|
||||||
H::Params: DeserializeOwned,
|
RpcError: From<H::Err>,
|
||||||
H::InheritedParams: DeserializeOwned,
|
F: Fn(Params, InheritedParams) -> H::InheritedParams + 'static,
|
||||||
RpcError: From<SubH::Err>,
|
|
||||||
F: Fn(H::Params, H::InheritedParams) -> SubH::InheritedParams + 'static,
|
|
||||||
{
|
{
|
||||||
self.subcommands.insert(
|
self.subcommands.insert(
|
||||||
method,
|
handler.contexts(),
|
||||||
DynHandler::WithCli(Box::new(AnyHandler {
|
name,
|
||||||
|
DynHandler::WithCli(Arc::new(AnyHandler {
|
||||||
_ctx: PhantomData,
|
_ctx: PhantomData,
|
||||||
handler: WithCliBindings {
|
handler: WithCliBindings {
|
||||||
_ctx: PhantomData,
|
_ctx: PhantomData,
|
||||||
handler: InheritanceHandler::<Context, H, SubH, F> {
|
handler: InheritanceHandler::<Context, Params, InheritedParams, H, F> {
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
handler,
|
handler,
|
||||||
inherit,
|
inherit,
|
||||||
@@ -475,43 +469,26 @@ impl<Context: crate::Context, H: Handler<Context>> ParentHandler<Context, H> {
|
|||||||
);
|
);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn subcommand_no_cli<SubH>(mut self, method: &'static str, handler: SubH) -> Self
|
pub fn subcommand_with_inherited_no_cli<Context, H, F>(
|
||||||
where
|
|
||||||
SubH: Handler<Context, InheritedParams = NoParams> + 'static,
|
|
||||||
SubH::Params: DeserializeOwned,
|
|
||||||
SubH::Ok: Serialize,
|
|
||||||
RpcError: From<SubH::Err>,
|
|
||||||
{
|
|
||||||
self.subcommands.insert(
|
|
||||||
method,
|
|
||||||
DynHandler::WithoutCli(Box::new(AnyHandler {
|
|
||||||
_ctx: PhantomData,
|
|
||||||
handler,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn subcommand_with_inherited_no_cli<SubH, F>(
|
|
||||||
mut self,
|
mut self,
|
||||||
method: &'static str,
|
name: Option<&'static str>,
|
||||||
handler: SubH,
|
handler: H,
|
||||||
inherit: F,
|
inherit: F,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
SubH: Handler<Context> + 'static,
|
Context: IntoContext,
|
||||||
SubH::Params: DeserializeOwned,
|
H: Handler<Context> + 'static,
|
||||||
SubH::Ok: Serialize,
|
|
||||||
H: 'static,
|
|
||||||
H::Params: DeserializeOwned,
|
H::Params: DeserializeOwned,
|
||||||
H::InheritedParams: DeserializeOwned,
|
H::Ok: Serialize,
|
||||||
RpcError: From<SubH::Err>,
|
RpcError: From<H::Err>,
|
||||||
F: Fn(H::Params, H::InheritedParams) -> SubH::InheritedParams + 'static,
|
F: Fn(Params, InheritedParams) -> H::InheritedParams + 'static,
|
||||||
{
|
{
|
||||||
self.subcommands.insert(
|
self.subcommands.insert(
|
||||||
method,
|
handler.contexts(),
|
||||||
DynHandler::WithoutCli(Box::new(AnyHandler {
|
name,
|
||||||
|
DynHandler::WithoutCli(Arc::new(AnyHandler {
|
||||||
_ctx: PhantomData,
|
_ctx: PhantomData,
|
||||||
handler: InheritanceHandler::<Context, H, SubH, F> {
|
handler: InheritanceHandler::<Context, Params, InheritedParams, H, F> {
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
handler,
|
handler,
|
||||||
inherit,
|
inherit,
|
||||||
@@ -522,17 +499,11 @@ impl<Context: crate::Context, H: Handler<Context>> ParentHandler<Context, H> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Context, H> Handler<Context> for ParentHandler<Context, H>
|
impl<Params: Serialize, InheritedParams: Serialize> Handler<AnyContext>
|
||||||
where
|
for ParentHandler<Params, InheritedParams>
|
||||||
Context: crate::Context,
|
|
||||||
H: Handler<Context>,
|
|
||||||
H::Params: Serialize,
|
|
||||||
H::InheritedParams: Serialize,
|
|
||||||
H::Ok: Serialize + DeserializeOwned,
|
|
||||||
RpcError: From<H::Err>,
|
|
||||||
{
|
{
|
||||||
type Params = H::Params;
|
type Params = Params;
|
||||||
type InheritedParams = H::InheritedParams;
|
type InheritedParams = InheritedParams;
|
||||||
type Ok = Value;
|
type Ok = Value;
|
||||||
type Err = RpcError;
|
type Err = RpcError;
|
||||||
fn handle_sync(
|
fn handle_sync(
|
||||||
@@ -543,71 +514,74 @@ where
|
|||||||
mut method,
|
mut method,
|
||||||
params,
|
params,
|
||||||
inherited_params,
|
inherited_params,
|
||||||
}: HandleArgs<Context, Self>,
|
}: HandleArgs<AnyContext, Self>,
|
||||||
) -> Result<Self::Ok, Self::Err> {
|
) -> Result<Self::Ok, Self::Err> {
|
||||||
if let Some(cmd) = method.pop_front() {
|
let cmd = method.pop_front();
|
||||||
|
if let Some(cmd) = cmd {
|
||||||
parent_method.push(cmd);
|
parent_method.push(cmd);
|
||||||
if let Some(sub_handler) = self.subcommands.get(cmd) {
|
|
||||||
sub_handler.handle_sync(HandleAnyArgs {
|
|
||||||
context,
|
|
||||||
parent_method,
|
|
||||||
method,
|
|
||||||
params: imbl_value::to_value(&Flat(params, inherited_params))
|
|
||||||
.map_err(invalid_params)?,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.handler
|
|
||||||
.handle_sync(HandleArgs {
|
|
||||||
context,
|
|
||||||
parent_method,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
inherited_params,
|
|
||||||
})
|
|
||||||
.map_err(RpcError::from)
|
|
||||||
.and_then(|r| imbl_value::to_value(&r).map_err(internal_error))
|
|
||||||
}
|
}
|
||||||
|
if let Some((_, sub_handler)) = self.subcommands.get(context.inner_type_id(), cmd) {
|
||||||
|
sub_handler.handle_sync(HandleAnyArgs {
|
||||||
|
context: context.upcast(),
|
||||||
|
parent_method,
|
||||||
|
method,
|
||||||
|
params: imbl_value::to_value(&Flat(params, inherited_params))
|
||||||
|
.map_err(invalid_params)?,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn contexts(&self) -> Option<BTreeSet<TypeId>> {
|
||||||
|
let mut set = BTreeSet::new();
|
||||||
|
for ctx_ty in self.subcommands.0.values().flat_map(|c| c.keys()) {
|
||||||
|
set.insert((*ctx_ty)?);
|
||||||
|
}
|
||||||
|
Some(set)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Context, H> CliBindings<Context> for ParentHandler<Context, H>
|
impl<Params, InheritedParams> CliBindings<AnyContext> for ParentHandler<Params, InheritedParams>
|
||||||
where
|
where
|
||||||
Context: crate::Context,
|
Params: FromArgMatches + CommandFactory + Serialize,
|
||||||
H: CliBindings<Context>,
|
InheritedParams: Serialize,
|
||||||
H::Params: FromArgMatches + CommandFactory + Serialize,
|
|
||||||
H::InheritedParams: Serialize,
|
|
||||||
H::Ok: PrintCliResult<Context> + Serialize + DeserializeOwned,
|
|
||||||
RpcError: From<H::Err>,
|
|
||||||
{
|
{
|
||||||
fn cli_command(&self) -> Command {
|
fn cli_command(&self) -> Command {
|
||||||
H::Params::command().subcommands(self.subcommands.iter().filter_map(|(method, handler)| {
|
// Params::command().subcommands(self.subcommands.0.iter().filter_map(|(name, handlers)| {
|
||||||
match handler {
|
// handlers.iter().find_map(|(ctx_ty, handler)| {
|
||||||
DynHandler::WithCli(h) => Some(h.cli_command().name(method)),
|
// if let DynHandler::WithCli(h) = handler {
|
||||||
DynHandler::WithoutCli(_) => None,
|
// h.cli_command()
|
||||||
}
|
// }
|
||||||
}))
|
// })
|
||||||
|
// }))
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
fn cli_parse(
|
fn cli_parse(
|
||||||
&self,
|
&self,
|
||||||
matches: &ArgMatches,
|
matches: &ArgMatches,
|
||||||
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
|
||||||
let (_, root_params) = self.handler.cli_parse(matches)?;
|
// let root_params = imbl_value::to_value(&Params::from_arg_matches(matches)?)
|
||||||
if let Some((sub, matches)) = matches.subcommand() {
|
// .map_err(|e| clap::Error::raw(clap::error::ErrorKind::ValueValidation, e))?;
|
||||||
if let Some((sub, DynHandler::WithCli(h))) = self.subcommands.get_key_value(sub) {
|
// let (m, matches) = match matches.subcommand() {
|
||||||
let (mut method, params) = h.cli_parse(matches)?;
|
// Some((m, matches)) => (Some(m), matches),
|
||||||
method.push_front(*sub);
|
// None => (None, matches),
|
||||||
return Ok((
|
// };
|
||||||
method,
|
// if let Some((SubcommandKey((_, m)), DynHandler::WithCli(h))) = self
|
||||||
combine(root_params, params).map_err(|e| {
|
// .subcommands
|
||||||
clap::Error::raw(clap::error::ErrorKind::ArgumentConflict, e)
|
// .get_key_value(&(TypeId::of::<Context>(), m))
|
||||||
})?,
|
// {
|
||||||
));
|
// let (mut method, params) = h.cli_parse(matches)?;
|
||||||
}
|
// if let Some(m) = m {
|
||||||
}
|
// method.push_front(*m);
|
||||||
Ok((VecDeque::new(), root_params))
|
// }
|
||||||
|
// return Ok((
|
||||||
|
// method,
|
||||||
|
// combine(root_params, params)
|
||||||
|
// .map_err(|e| clap::Error::raw(clap::error::ErrorKind::ArgumentConflict, e))?,
|
||||||
|
// ));
|
||||||
|
// }
|
||||||
|
// Ok((VecDeque::new(), root_params))
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
fn cli_display(
|
fn cli_display(
|
||||||
&self,
|
&self,
|
||||||
@@ -617,39 +591,30 @@ where
|
|||||||
mut method,
|
mut method,
|
||||||
params,
|
params,
|
||||||
inherited_params,
|
inherited_params,
|
||||||
}: HandleArgs<Context, Self>,
|
}: HandleArgs<AnyContext, Self>,
|
||||||
result: Self::Ok,
|
result: Self::Ok,
|
||||||
) -> Result<(), Self::Err> {
|
) -> Result<(), Self::Err> {
|
||||||
if let Some(cmd) = method.pop_front() {
|
// let cmd = method.pop_front();
|
||||||
parent_method.push(cmd);
|
// if let Some(cmd) = cmd {
|
||||||
if let Some(DynHandler::WithCli(sub_handler)) = self.subcommands.get(cmd) {
|
// parent_method.push(cmd);
|
||||||
sub_handler.cli_display(
|
// }
|
||||||
HandleAnyArgs {
|
// if let Some(DynHandler::WithCli(sub_handler)) =
|
||||||
context,
|
// self.subcommands.get(&(context.inner_type_id(), cmd))
|
||||||
parent_method,
|
// {
|
||||||
method,
|
// sub_handler.cli_display(
|
||||||
params: imbl_value::to_value(&Flat(params, inherited_params))
|
// HandleAnyArgs {
|
||||||
.map_err(invalid_params)?,
|
// context: AnyContext::new(context),
|
||||||
},
|
// parent_method,
|
||||||
result,
|
// method,
|
||||||
)
|
// params: imbl_value::to_value(&Flat(params, inherited_params))
|
||||||
} else {
|
// .map_err(invalid_params)?,
|
||||||
Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
// },
|
||||||
}
|
// result,
|
||||||
} else {
|
// )
|
||||||
self.handler
|
// } else {
|
||||||
.cli_display(
|
// Err(yajrc::METHOD_NOT_FOUND_ERROR)
|
||||||
HandleArgs {
|
// }
|
||||||
context,
|
todo!()
|
||||||
parent_method,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
inherited_params,
|
|
||||||
},
|
|
||||||
imbl_value::from_value(result).map_err(internal_error)?,
|
|
||||||
)
|
|
||||||
.map_err(RpcError::from)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,7 +632,7 @@ pub fn from_fn<F, T, E, Args>(function: F) -> FromFn<F, T, E, Args> {
|
|||||||
|
|
||||||
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: crate::Context,
|
Context: IntoContext,
|
||||||
F: Fn() -> Result<T, E>,
|
F: Fn() -> Result<T, E>,
|
||||||
{
|
{
|
||||||
type Params = NoParams;
|
type Params = NoParams;
|
||||||
@@ -681,7 +646,7 @@ where
|
|||||||
|
|
||||||
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: crate::Context,
|
Context: IntoContext,
|
||||||
F: Fn(Context) -> Result<T, E>,
|
F: Fn(Context) -> Result<T, E>,
|
||||||
{
|
{
|
||||||
type Params = NoParams;
|
type Params = NoParams;
|
||||||
@@ -694,7 +659,7 @@ where
|
|||||||
}
|
}
|
||||||
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: crate::Context,
|
Context: IntoContext,
|
||||||
F: Fn(Context, Params) -> Result<T, E>,
|
F: Fn(Context, Params) -> Result<T, E>,
|
||||||
Params: DeserializeOwned,
|
Params: DeserializeOwned,
|
||||||
{
|
{
|
||||||
@@ -712,7 +677,7 @@ where
|
|||||||
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: crate::Context,
|
Context: IntoContext,
|
||||||
F: Fn(Context, Params, InheritedParams) -> Result<T, E>,
|
F: Fn(Context, Params, InheritedParams) -> Result<T, E>,
|
||||||
Params: DeserializeOwned,
|
Params: DeserializeOwned,
|
||||||
InheritedParams: DeserializeOwned,
|
InheritedParams: DeserializeOwned,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// pub use cli::*;
|
// pub use cli::*;
|
||||||
// pub use command::*;
|
// pub use command::*;
|
||||||
pub use context::Context;
|
pub use context::*;
|
||||||
pub use handler::*;
|
pub use handler::*;
|
||||||
/// `#[command(...)]`
|
/// `#[command(...)]`
|
||||||
/// - `#[command(cli_only)]` -> executed by CLI instead of RPC server (leaf commands only)
|
/// - `#[command(cli_only)]` -> executed by CLI instead of RPC server (leaf commands only)
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use rpc_toolkit::{Context, ParentHandler};
|
use rpc_toolkit::{from_fn, Context, ParentHandler};
|
||||||
use tokio::{
|
use serde::Deserialize;
|
||||||
runtime::{Handle, Runtime},
|
use tokio::runtime::{Handle, Runtime};
|
||||||
sync::OnceCell,
|
use tokio::sync::OnceCell;
|
||||||
};
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use yajrc::RpcError;
|
use yajrc::RpcError;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser, Deserialize)]
|
||||||
#[command(
|
#[command(
|
||||||
name = "test-cli",
|
name = "test-cli",
|
||||||
version,
|
version,
|
||||||
@@ -17,13 +18,13 @@ use yajrc::RpcError;
|
|||||||
about = "This is a test cli application."
|
about = "This is a test cli application."
|
||||||
)]
|
)]
|
||||||
struct CliConfig {
|
struct CliConfig {
|
||||||
host: Option<Url>,
|
host: Option<String>,
|
||||||
config: Option<PathBuf>,
|
config: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
impl CliConfig {
|
impl CliConfig {
|
||||||
fn load_rec(&mut self) -> Result<(), RpcError> {
|
fn load_rec(&mut self) -> Result<(), RpcError> {
|
||||||
if let Some(path) = self.config.as_ref() {
|
if let Some(path) = self.config.as_ref() {
|
||||||
let extra_cfg =
|
let mut extra_cfg: Self =
|
||||||
serde_json::from_str(&std::fs::read_to_string(path).map_err(internal_error)?)
|
serde_json::from_str(&std::fs::read_to_string(path).map_err(internal_error)?)
|
||||||
.map_err(internal_error)?;
|
.map_err(internal_error)?;
|
||||||
extra_cfg.load_rec()?;
|
extra_cfg.load_rec()?;
|
||||||
@@ -46,27 +47,37 @@ struct CliContextSeed {
|
|||||||
struct CliContext(Arc<CliContextSeed>);
|
struct CliContext(Arc<CliContextSeed>);
|
||||||
impl Context for CliContext {
|
impl Context for CliContext {
|
||||||
fn runtime(&self) -> Handle {
|
fn runtime(&self) -> Handle {
|
||||||
if self.rt.get().is_none() {
|
if self.0.rt.get().is_none() {
|
||||||
self.rt.set(Runtime::new().unwrap()).unwrap();
|
self.0.rt.set(Runtime::new().unwrap()).unwrap();
|
||||||
}
|
}
|
||||||
self.rt.get().unwrap().handle()
|
self.0.rt.get().unwrap().handle().clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_cli() -> CliApp<CliConfig> {
|
// fn make_cli() -> CliApp<CliConfig> {
|
||||||
CliApp::new::<_, CliConfig>(|mut config| {
|
// CliApp::new::<_, CliConfig>(|mut config| {
|
||||||
config.load_rec()?;
|
// config.load_rec()?;
|
||||||
Ok(CliContext(Arc::new(CliContextSeed {
|
// Ok(CliContext(Arc::new(CliContextSeed {
|
||||||
host: config
|
// host: config
|
||||||
.host
|
// .host
|
||||||
.unwrap_or_else("http://localhost:8080/rpc".parse().unwrap()),
|
// .unwrap_or_else("http://localhost:8080/rpc".parse().unwrap()),
|
||||||
rt: OnceCell::new(),
|
// rt: OnceCell::new(),
|
||||||
})))
|
// })))
|
||||||
})
|
// })
|
||||||
.subcommands(make_api())
|
// .subcommands(make_api())
|
||||||
.subcommands(ParentHandler::new().subcommand("hello", from_fn(|| Ok("world"))));
|
// .subcommands(ParentHandler::new().subcommand("hello", from_fn(|| Ok("world"))));
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn make_api() -> ParentHandler<CliContext> {
|
fn make_api() -> ParentHandler<CliContext> {
|
||||||
ParentHandler::new().subcommand("hello", from_fn(|| Ok("world")))
|
ParentHandler::new().subcommand_no_cli(
|
||||||
|
Some("hello"),
|
||||||
|
from_fn(|_: CliContext| Ok::<_, RpcError>("world")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn internal_error(e: impl Display) -> RpcError {
|
||||||
|
RpcError {
|
||||||
|
data: Some(e.to_string().into()),
|
||||||
|
..yajrc::INTERNAL_ERROR
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user