diff --git a/rpc-toolkit/src/cli.rs b/rpc-toolkit/src/cli.rs index dd98ca9..6ba2d37 100644 --- a/rpc-toolkit/src/cli.rs +++ b/rpc-toolkit/src/cli.rs @@ -67,7 +67,7 @@ impl parent_method: VecDeque::new(), method: method.clone(), params: params.clone(), - inherited: Value::Object(InOMap::new()), + inherited: crate::Empty {}, })?; root_handler.cli_display( HandleAnyArgs { @@ -75,7 +75,7 @@ impl parent_method: VecDeque::new(), method, params, - inherited: Value::Object(InOMap::new()), + inherited: crate::Empty {}, }, res, )?; diff --git a/rpc-toolkit/src/handler/adapters.rs b/rpc-toolkit/src/handler/adapters.rs index 2b05cd5..a4ea662 100644 --- a/rpc-toolkit/src/handler/adapters.rs +++ b/rpc-toolkit/src/handler/adapters.rs @@ -10,11 +10,11 @@ use serde::de::DeserializeOwned; use serde::Serialize; use yajrc::RpcError; -use crate::util::{internal_error, parse_error, Flat, PhantomData}; +use crate::util::{internal_error, Flat, PhantomData}; use crate::{ iter_from_ctx_and_handler, AnyContext, AnyHandler, CallRemote, CliBindings, DynHandler, EitherContext, Handler, HandlerArgs, HandlerArgsFor, HandlerTypes, IntoContext, IntoHandlers, - PrintCliResult, + OrEmpty, PrintCliResult, }; pub trait HandlerExt: Handler + Sized { @@ -106,18 +106,22 @@ impl HandlerTypes for NoCli { type Ok = H::Ok; type Err = H::Err; } -impl IntoHandlers for NoCli +impl IntoHandlers> for NoCli where H: Handler, H::Params: DeserializeOwned, - H::InheritedParams: DeserializeOwned, + H::InheritedParams: OrEmpty>, H::Ok: Serialize + DeserializeOwned, RpcError: From, + A: Send + Sync + 'static, + B: Send + Sync + 'static, { - fn into_handlers(self) -> impl IntoIterator, DynHandler)> { + fn into_handlers(self) -> impl IntoIterator, DynHandler>)> { iter_from_ctx_and_handler( self.0.contexts(), - DynHandler::WithoutCli(Arc::new(AnyHandler::new(self.0))), + DynHandler::WithoutCli(Arc::new(AnyHandler::new( + self.0.with_inherited(|a, b| OrEmpty::from_t(Flat(a, b))), + ))), ) } } diff --git a/rpc-toolkit/src/handler/from_fn.rs b/rpc-toolkit/src/handler/from_fn.rs index a8b6777..02144b8 100644 --- a/rpc-toolkit/src/handler/from_fn.rs +++ b/rpc-toolkit/src/handler/from_fn.rs @@ -461,7 +461,7 @@ where Context: IntoContext, F: Fn(Context, Params, InheritedParams) -> Result + Send + Sync + Clone + 'static, Params: DeserializeOwned + Send + Sync + 'static, - InheritedParams: DeserializeOwned + Send + Sync + 'static, + InheritedParams: Send + Sync + 'static, T: Send + Sync + 'static, E: Send + Sync + 'static, { @@ -477,7 +477,7 @@ where Context: IntoContext, F: Fn(Context, Params, InheritedParams) -> Result + Send + Sync + Clone + 'static, Params: DeserializeOwned + Send + Sync + 'static, - InheritedParams: DeserializeOwned + Send + Sync + 'static, + InheritedParams: Send + Sync + 'static, T: Send + Sync + 'static, E: Send + Sync + 'static, { @@ -515,7 +515,7 @@ where F: Fn(Context, Params, InheritedParams) -> Fut + Send + Sync + Clone + 'static, Fut: Future> + Send + 'static, Params: DeserializeOwned + Send + Sync + 'static, - InheritedParams: DeserializeOwned + Send + Sync + 'static, + InheritedParams: Send + Sync + 'static, T: Send + Sync + 'static, E: Send + Sync + 'static, { @@ -532,7 +532,7 @@ where F: Fn(Context, Params, InheritedParams) -> Fut + Send + Sync + Clone + 'static, Fut: Future> + Send + 'static, Params: DeserializeOwned + Send + Sync + 'static, - InheritedParams: DeserializeOwned + Send + Sync + 'static, + InheritedParams: Send + Sync + 'static, T: Send + Sync + 'static, E: Send + Sync + 'static, { diff --git a/rpc-toolkit/src/handler/mod.rs b/rpc-toolkit/src/handler/mod.rs index 51e5a66..1a5a643 100644 --- a/rpc-toolkit/src/handler/mod.rs +++ b/rpc-toolkit/src/handler/mod.rs @@ -21,21 +21,20 @@ pub use adapters::*; pub use from_fn::*; pub use parent::*; -pub(crate) struct HandleAnyArgs { +pub(crate) struct HandleAnyArgs { pub(crate) context: AnyContext, pub(crate) parent_method: VecDeque<&'static str>, pub(crate) method: VecDeque<&'static str>, pub(crate) params: Value, - pub(crate) inherited: Value, + pub(crate) inherited: Inherited, } -impl HandleAnyArgs { +impl HandleAnyArgs { fn downcast( self, ) -> Result, imbl_value::Error> where - H: HandlerTypes, + H: HandlerTypes, H::Params: DeserializeOwned, - H::InheritedParams: DeserializeOwned, { let Self { context, @@ -52,7 +51,7 @@ impl HandleAnyArgs { parent_method, method, params: imbl_value::from_value(params.clone())?, - inherited_params: imbl_value::from_value(inherited.clone())?, + inherited_params: inherited, raw_params: params, }) } @@ -60,8 +59,12 @@ impl HandleAnyArgs { #[async_trait::async_trait] pub(crate) trait HandleAny: Send + Sync { - fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result; - async fn handle_async(&self, handle_args: HandleAnyArgs) -> Result; + type Inherited: Send; + fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result; + async fn handle_async( + &self, + handle_args: HandleAnyArgs, + ) -> Result; fn metadata( &self, method: VecDeque<&'static str>, @@ -71,10 +74,14 @@ pub(crate) trait HandleAny: Send + Sync { } #[async_trait::async_trait] impl HandleAny for Arc { - fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result { + type Inherited = T::Inherited; + fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result { self.deref().handle_sync(handle_args) } - async fn handle_async(&self, handle_args: HandleAnyArgs) -> Result { + async fn handle_async( + &self, + handle_args: HandleAnyArgs, + ) -> Result { self.deref().handle_async(handle_args).await } fn metadata( @@ -90,13 +97,18 @@ impl HandleAny for Arc { } pub(crate) trait CliBindingsAny { + type Inherited; fn cli_command(&self, ctx_ty: TypeId) -> Command; fn cli_parse( &self, matches: &ArgMatches, ctx_ty: TypeId, ) -> Result<(VecDeque<&'static str>, Value), clap::Error>; - fn cli_display(&self, handle_args: HandleAnyArgs, result: Value) -> Result<(), RpcError>; + fn cli_display( + &self, + handle_args: HandleAnyArgs, + result: Value, + ) -> Result<(), RpcError>; } pub trait CliBindings: HandlerTypes { @@ -172,24 +184,41 @@ where } } -pub(crate) trait HandleAnyWithCli: HandleAny + CliBindingsAny {} -impl HandleAnyWithCli for T {} +pub(crate) trait HandleAnyWithCli: + HandleAny + CliBindingsAny +{ +} +impl + CliBindingsAny> + HandleAnyWithCli for T +{ +} -#[derive(Clone)] #[allow(private_interfaces)] -pub enum DynHandler { - WithoutCli(Arc), - WithCli(Arc), +pub enum DynHandler { + WithoutCli(Arc>), + WithCli(Arc>), +} +impl Clone for DynHandler { + fn clone(&self) -> Self { + match self { + Self::WithCli(a) => Self::WithCli(a.clone()), + Self::WithoutCli(a) => Self::WithoutCli(a.clone()), + } + } } #[async_trait::async_trait] -impl HandleAny for DynHandler { - fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result { +impl HandleAny for DynHandler { + type Inherited = Inherited; + fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result { match self { DynHandler::WithoutCli(h) => h.handle_sync(handle_args), DynHandler::WithCli(h) => h.handle_sync(handle_args), } } - async fn handle_async(&self, handle_args: HandleAnyArgs) -> Result { + async fn handle_async( + &self, + handle_args: HandleAnyArgs, + ) -> Result { match self { DynHandler::WithoutCli(h) => h.handle_async(handle_args).await, DynHandler::WithCli(h) => h.handle_async(handle_args).await, @@ -309,11 +338,11 @@ impl std::fmt::Debug for AnyHandler { impl HandleAny for AnyHandler where H::Params: DeserializeOwned, - H::InheritedParams: DeserializeOwned, H::Ok: Serialize, RpcError: From, { - fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result { + type Inherited = H::InheritedParams; + fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result { imbl_value::to_value( &self .0 @@ -321,7 +350,10 @@ where ) .map_err(internal_error) } - async fn handle_async(&self, handle_args: HandleAnyArgs) -> Result { + async fn handle_async( + &self, + handle_args: HandleAnyArgs, + ) -> Result { imbl_value::to_value( &self .0 @@ -346,10 +378,10 @@ impl CliBindingsAny for AnyHandler where H: CliBindings, H::Params: DeserializeOwned, - H::InheritedParams: DeserializeOwned, H::Ok: Serialize + DeserializeOwned, RpcError: From, { + type Inherited = H::InheritedParams; fn cli_command(&self, ctx_ty: TypeId) -> Command { self.0.cli_command(ctx_ty) } @@ -360,7 +392,11 @@ where ) -> Result<(VecDeque<&'static str>, Value), clap::Error> { self.0.cli_parse(matches, ctx_ty) } - fn cli_display(&self, handle_args: HandleAnyArgs, result: Value) -> Result<(), RpcError> { + fn cli_display( + &self, + handle_args: HandleAnyArgs, + result: Value, + ) -> Result<(), RpcError> { self.0 .cli_display( handle_args.downcast::<_, H>().map_err(invalid_params)?, @@ -373,9 +409,19 @@ where #[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)] pub struct Empty {} -pub(crate) trait OrEmpty {} -impl OrEmpty for T {} -impl OrEmpty> for Empty {} +pub(crate) trait OrEmpty { + fn from_t(t: T) -> Self; +} +impl OrEmpty for T { + fn from_t(t: T) -> Self { + t + } +} +impl OrEmpty> for Empty { + fn from_t(t: Flat) -> Self { + Empty {} + } +} #[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)] pub enum Never {} diff --git a/rpc-toolkit/src/handler/parent.rs b/rpc-toolkit/src/handler/parent.rs index 04fc49d..0b61eab 100644 --- a/rpc-toolkit/src/handler/parent.rs +++ b/rpc-toolkit/src/handler/parent.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use clap::{ArgMatches, Command, CommandFactory, FromArgMatches}; use imbl_value::imbl::{OrdMap, OrdSet}; -use imbl_value::{to_value, Value}; +use imbl_value::Value; use serde::de::DeserializeOwned; use serde::Serialize; use yajrc::RpcError; @@ -12,33 +12,37 @@ use yajrc::RpcError; use crate::util::{combine, Flat, PhantomData}; use crate::{ AnyContext, AnyHandler, CliBindings, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, - HandlerArgs, HandlerArgsFor, HandlerTypes, IntoContext, OrEmpty, + HandlerArgs, HandlerArgsFor, HandlerExt, HandlerTypes, IntoContext, OrEmpty, }; -pub trait IntoHandlers: HandlerTypes { - fn into_handlers(self) -> impl IntoIterator, DynHandler)>; +pub trait IntoHandlers: HandlerTypes { + fn into_handlers(self) -> impl IntoIterator, DynHandler)>; } -impl IntoHandlers for H +impl IntoHandlers> for H where H: Handler + CliBindings, H::Params: DeserializeOwned, - H::InheritedParams: DeserializeOwned, + H::InheritedParams: OrEmpty>, H::Ok: Serialize + DeserializeOwned, RpcError: From, + A: Send + Sync + 'static, + B: Send + Sync + 'static, { - fn into_handlers(self) -> impl IntoIterator, DynHandler)> { + fn into_handlers(self) -> impl IntoIterator, DynHandler>)> { iter_from_ctx_and_handler( intersect_type_ids(self.contexts(), ::Context::type_ids()), - DynHandler::WithCli(Arc::new(AnyHandler::new(self))), + DynHandler::WithCli(Arc::new(AnyHandler::new( + self.with_inherited(|a, b| OrEmpty::from_t(Flat(a, b))), + ))), ) } } -pub(crate) fn iter_from_ctx_and_handler( +pub(crate) fn iter_from_ctx_and_handler( ctx: Option>, - handler: DynHandler, -) -> impl IntoIterator, DynHandler)> { + handler: DynHandler, +) -> impl IntoIterator, DynHandler)> { if let Some(ctx) = ctx { itertools::Either::Left(ctx.into_iter().map(Some)) } else { @@ -67,13 +71,19 @@ impl<'a> std::borrow::Borrow> for Name { } } -#[derive(Clone)] -pub(crate) struct SubcommandMap(pub(crate) OrdMap, DynHandler>>); -impl SubcommandMap { +pub(crate) struct SubcommandMap( + pub(crate) OrdMap, DynHandler>>, +); +impl Clone for SubcommandMap { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} +impl SubcommandMap { fn insert( &mut self, name: Option<&'static str>, - handlers: impl IntoIterator, DynHandler)>, + handlers: impl IntoIterator, DynHandler)>, ) { let mut for_name = self.0.remove(&name).unwrap_or_default(); for (ctx_ty, handler) in handlers { @@ -82,7 +92,11 @@ impl SubcommandMap { self.0.insert(Name(name), for_name); } - fn get<'a>(&'a self, ctx_ty: TypeId, name: Option<&str>) -> Option<(Name, &'a DynHandler)> { + 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)) @@ -96,8 +110,8 @@ impl SubcommandMap { } pub struct ParentHandler { - _phantom: PhantomData<(Params, InheritedParams)>, - pub(crate) subcommands: SubcommandMap, + _phantom: PhantomData, + pub(crate) subcommands: SubcommandMap>, metadata: OrdMap<&'static str, Value>, } impl ParentHandler { @@ -141,8 +155,7 @@ impl ParentHandler { #[allow(private_bounds)] pub fn subcommand(mut self, name: &'static str, handler: H) -> Self where - H: IntoHandlers, - H::InheritedParams: OrEmpty>, + H: IntoHandlers>, { self.subcommands .insert(name.into(), handler.into_handlers()); @@ -151,8 +164,7 @@ impl ParentHandler { #[allow(private_bounds)] pub fn root_handler(mut self, handler: H) -> Self where - H: IntoHandlers, - H::InheritedParams: OrEmpty>, + H: IntoHandlers>, { self.subcommands.insert(None, handler.into_handlers()); self @@ -182,9 +194,9 @@ where context, mut parent_method, mut method, + params, inherited_params, raw_params, - .. }: HandlerArgsFor, ) -> Result { let cmd = method.pop_front(); @@ -197,7 +209,7 @@ where parent_method, method, params: raw_params, - inherited: to_value(&inherited_params)?, + inherited: Flat(params, inherited_params), }) } else { Err(yajrc::METHOD_NOT_FOUND_ERROR) @@ -209,9 +221,9 @@ where context, mut parent_method, mut method, + params, inherited_params, raw_params, - .. }: HandlerArgsFor, ) -> Result { let cmd = method.pop_front(); @@ -225,7 +237,7 @@ where parent_method, method, params: raw_params, - inherited: to_value(&inherited_params)?, + inherited: Flat(params, inherited_params), }) .await } else { @@ -330,9 +342,9 @@ where context, mut parent_method, mut method, + params, inherited_params, raw_params, - .. }: HandlerArgsFor, result: Self::Ok, ) -> Result<(), Self::Err> { @@ -349,7 +361,7 @@ where parent_method, method, params: raw_params, - inherited: to_value(&inherited_params)?, + inherited: Flat(params, inherited_params), }, result, ) diff --git a/rpc-toolkit/src/server/mod.rs b/rpc-toolkit/src/server/mod.rs index 4dbf590..3d86e02 100644 --- a/rpc-toolkit/src/server/mod.rs +++ b/rpc-toolkit/src/server/mod.rs @@ -8,7 +8,7 @@ use imbl_value::{InOMap, Value}; use yajrc::{RpcError, RpcMethod}; use crate::util::{invalid_request, JobRunner}; -use crate::{AnyHandler, HandleAny, HandleAnyArgs, IntoContext, ParentHandler}; +use crate::{AnyHandler, Empty, HandleAny, HandleAnyArgs, IntoContext, ParentHandler}; pub type GenericRpcMethod = yajrc::GenericRpcMethod; pub type RpcRequest = yajrc::RpcRequest; @@ -66,7 +66,7 @@ impl Server { parent_method: VecDeque::new(), method: method.ok_or_else(|| yajrc::METHOD_NOT_FOUND_ERROR)?, params, - inherited: Value::Object(InOMap::new()), + inherited: crate::Empty {}, }) .await } diff --git a/rpc-toolkit/tests/handler.rs b/rpc-toolkit/tests/handler.rs index cc6e203..c07e0c9 100644 --- a/rpc-toolkit/tests/handler.rs +++ b/rpc-toolkit/tests/handler.rs @@ -159,7 +159,7 @@ fn make_api() -> ParentHandler { .subcommand( "fizz", ParentHandler::::new().root_handler( - from_fn(|c: CliContext, _, InheritParams { donde }| { + from_fn(|c: CliContext, _: Empty, InheritParams { donde }| { Ok::<_, RpcError>( format!( "Root Command: Host {host} Donde = {donde}", @@ -174,7 +174,7 @@ fn make_api() -> ParentHandler { .subcommand( "error", ParentHandler::::new().root_handler( - from_fn(|c: CliContext, _, InheritParams { donde }| { + from_fn(|c: CliContext, _: Empty, InheritParams { donde }| { Err::(RpcError { code: 1, message: "This is an example message".into(),