From e733885d98c233f169c6705120cb433b159a77ae Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Fri, 3 May 2024 18:53:44 -0600 Subject: [PATCH] wip --- src/cli.rs | 48 +++++------ src/context.rs | 28 +++++-- src/handler/adapters.rs | 133 +++++++++++++----------------- src/handler/from_fn.rs | 178 +++++++++++++++++++++++++++++----------- src/handler/mod.rs | 177 +++++++++++++++------------------------ src/handler/parent.rs | 115 ++++++++++++-------------- src/lib.rs | 2 + src/server/mod.rs | 8 +- tests/handler.rs | 6 +- 9 files changed, 362 insertions(+), 333 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 9de0e55..68f91bf 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -4,7 +4,7 @@ use std::ffi::OsString; use clap::{CommandFactory, FromArgMatches}; use futures::Future; -use imbl_value::{InOMap, Value}; +use imbl_value::Value; use reqwest::header::{ACCEPT, CONTENT_LENGTH, CONTENT_TYPE}; use reqwest::{Client, Method}; use serde::de::DeserializeOwned; @@ -15,7 +15,7 @@ use yajrc::{Id, RpcError}; use crate::util::{internal_error, invalid_params, parse_error, without, Flat, PhantomData}; use crate::{ - AnyHandler, CliBindingsAny, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, HandlerArgs, + AnyHandler, CliBindingsAny, Empty, HandleAny, HandleAnyArgs, Handler, HandlerArgs, HandlerArgsFor, HandlerTypes, IntoContext, Name, ParentHandler, PrintCliResult, }; @@ -45,17 +45,17 @@ impl let ctx_ty = TypeId::of::(); let mut cmd = Config::command(); for (name, handlers) in &self.root_handler.subcommands.0 { - if let (Name(Some(name)), Some(DynHandler::WithCli(handler))) = ( + if let (Name(Some(name)), Some(cli)) = ( name, if let Some(handler) = handlers.get(&Some(ctx_ty)) { - Some(handler) + handler.cli() } else if let Some(handler) = handlers.get(&None) { - Some(handler) + handler.cli() } else { None }, ) { - cmd = cmd.subcommand(handler.cli_command(ctx_ty).name(name)); + cmd = cmd.subcommand(cli.cli_command(ctx_ty).name(name)); } } let matches = cmd.get_matches_from(args); @@ -172,11 +172,13 @@ pub async fn call_remote_socket( .result } -pub struct CallRemoteHandler { - _phantom: PhantomData<(Context, Extra)>, +pub struct CallRemoteHandler { + _phantom: PhantomData<(Context, RemoteContext, Extra)>, handler: RemoteHandler, } -impl CallRemoteHandler { +impl + CallRemoteHandler +{ pub fn new(handler: RemoteHandler) -> Self { Self { _phantom: PhantomData::new(), @@ -184,8 +186,8 @@ impl CallRemoteHandler Clone - for CallRemoteHandler +impl Clone + for CallRemoteHandler { fn clone(&self) -> Self { Self { @@ -202,8 +204,8 @@ impl std::fmt::Debug } } -impl HandlerTypes - for CallRemoteHandler +impl HandlerTypes + for CallRemoteHandler where RemoteHandler: HandlerTypes, RemoteHandler::Params: Serialize, @@ -218,17 +220,18 @@ where type Err = RemoteHandler::Err; } -impl Handler for CallRemoteHandler +impl Handler + for CallRemoteHandler where - Context: CallRemote, - RemoteHandler: Handler, + Context: CallRemote, + RemoteContext: IntoContext, + RemoteHandler: Handler, RemoteHandler::Params: Serialize, RemoteHandler::InheritedParams: Serialize, RemoteHandler::Ok: DeserializeOwned, RemoteHandler::Err: From, Extra: Serialize + Send + Sync + 'static, { - type Context = Context; async fn handle_async( &self, handle_args: HandlerArgsFor, @@ -255,18 +258,17 @@ where } } } -impl PrintCliResult - for CallRemoteHandler +impl PrintCliResult + for CallRemoteHandler where - Context: CallRemote, - RemoteHandler: PrintCliResult, + Context: CallRemote, + RemoteHandler: PrintCliResult, RemoteHandler::Params: Serialize, RemoteHandler::InheritedParams: Serialize, RemoteHandler::Ok: DeserializeOwned, RemoteHandler::Err: From, Extra: Send + Sync + 'static, { - type Context = Context; fn print( &self, HandlerArgs { @@ -276,7 +278,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, result: Self::Ok, ) -> Result<(), Self::Err> { self.handler.print( diff --git a/src/context.rs b/src/context.rs index a5a0deb..328cb6d 100644 --- a/src/context.rs +++ b/src/context.rs @@ -84,6 +84,8 @@ impl IntoContext for EitherContext { } } } +impl From for EitherContext {} +impl From for EitherContext {} pub struct AnyContext(Box); impl AnyContext { @@ -114,9 +116,25 @@ impl IntoContext for AnyContext { } } -mod sealed { - pub(crate) trait Sealed {} - impl Sealed for C {} - impl Sealed for super::EitherContext {} - impl Sealed for super::AnyContext {} +pub(crate) mod sealed { + use std::any::TypeId; + + pub(crate) trait Sealed { + fn contains_type_id(id: TypeId) -> bool; + } + impl Sealed for C { + fn contains_type_id(id: TypeId) -> bool { + id == TypeId::of::() + } + } + impl Sealed for super::EitherContext { + fn contains_type_id(id: TypeId) -> bool { + C1::contains_type_id(id) || C2::contains_type_id(id) + } + } + impl Sealed for super::AnyContext { + fn contains_type_id(_: TypeId) -> bool { + true + } + } } diff --git a/src/handler/adapters.rs b/src/handler/adapters.rs index a738d6a..4f473b3 100644 --- a/src/handler/adapters.rs +++ b/src/handler/adapters.rs @@ -1,7 +1,6 @@ use std::any::TypeId; use std::collections::VecDeque; use std::fmt::Debug; -use std::sync::Arc; use clap::{CommandFactory, FromArgMatches}; use imbl_value::imbl::{OrdMap, OrdSet}; @@ -10,25 +9,25 @@ use serde::de::DeserializeOwned; use serde::Serialize; use yajrc::RpcError; -use crate::util::{internal_error, invalid_params, without, Flat, PhantomData}; +use crate::util::{internal_error, Flat, PhantomData}; use crate::{ - iter_from_ctx_and_handler, AnyContext, AnyHandler, CallRemote, CliBindings, DynHandler, - EitherContext, Empty, Handler, HandlerArgs, HandlerArgsFor, HandlerTypes, IntoContext, - IntoHandlers, OrEmpty, PrintCliResult, + AnyContext, CallRemote, CliBindings, EitherContext, Empty, Handler, HandlerArgs, + HandlerArgsFor, HandlerTypes, IntoContext, PrintCliResult, }; -pub trait HandlerExt: Handler + Sized { +pub trait HandlerExt: Handler + Sized { fn no_cli(self) -> NoCli; fn no_display(self) -> NoDisplay; - fn with_custom_display

(self, display: P) -> CustomDisplay + fn with_custom_display(self, display: P) -> CustomDisplay where P: PrintCliResult< + C, Params = Self::Params, InheritedParams = Self::InheritedParams, Ok = Self::Ok, Err = Self::Err, >; - fn with_custom_display_fn( + fn with_custom_display_fn( self, display: F, ) -> CustomDisplayFn @@ -40,19 +39,20 @@ pub trait HandlerExt: Handler + Sized { ) -> InheritanceHandler where F: Fn(Params, InheritedParams) -> Self::InheritedParams; - fn with_call_remote(self) -> RemoteCaller; + fn with_call_remote(self) -> RemoteCaller; } -impl HandlerExt for T { +impl + Sized> HandlerExt for T { fn no_cli(self) -> NoCli { NoCli(self) } fn no_display(self) -> NoDisplay { NoDisplay(self) } - fn with_custom_display

(self, display: P) -> CustomDisplay + fn with_custom_display(self, display: P) -> CustomDisplay where P: PrintCliResult< + C, Params = Self::Params, InheritedParams = Self::InheritedParams, Ok = Self::Ok, @@ -64,7 +64,7 @@ impl HandlerExt for T { handler: self, } } - fn with_custom_display_fn( + fn with_custom_display_fn( self, display: F, ) -> CustomDisplayFn @@ -90,7 +90,7 @@ impl HandlerExt for T { inherit: f, } } - fn with_call_remote(self) -> RemoteCaller { + fn with_call_remote(self) -> RemoteCaller { RemoteCaller { _phantom: PhantomData::new(), handler: self, @@ -106,25 +106,7 @@ impl HandlerTypes for NoCli { type Ok = H::Ok; type Err = H::Err; } -impl IntoHandlers> for NoCli -where - H: Handler, - H::Params: 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>)> { - iter_from_ctx_and_handler( - self.0.contexts(), - DynHandler::WithoutCli(Arc::new(AnyHandler::new( - self.0.with_inherited(|a, b| OrEmpty::from_t(Flat(a, b))), - ))), - ) - } -} +// TODO: implement Handler #[derive(Debug, Clone)] pub struct NoDisplay(pub H); @@ -135,11 +117,11 @@ impl HandlerTypes for NoDisplay { type Err = H::Err; } -impl Handler for NoDisplay +impl Handler for NoDisplay where - H: Handler, + Context: IntoContext, + H: Handler, { - type Context = H::Context; fn handle_sync( &self, HandlerArgs { @@ -149,7 +131,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, ) -> Result { self.0.handle_sync(HandlerArgs { context, @@ -169,7 +151,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, ) -> Result { self.0 .handle_async(HandlerArgs { @@ -196,13 +178,13 @@ where self.0.method_from_dots(method, ctx_ty) } } -impl PrintCliResult for NoDisplay +impl PrintCliResult for NoDisplay where + Context: IntoContext, H: HandlerTypes, H::Params: FromArgMatches + CommandFactory + Serialize, { - type Context = AnyContext; - fn print(&self, _: HandlerArgsFor, _: Self::Ok) -> Result<(), Self::Err> { + fn print(&self, _: HandlerArgsFor, _: Self::Ok) -> Result<(), Self::Err> { Ok(()) } } @@ -222,12 +204,12 @@ where type Err = H::Err; } -impl Handler for CustomDisplay +impl Handler for CustomDisplay where - H: Handler, + Context: IntoContext, + H: Handler, P: Send + Sync + Clone + 'static, { - type Context = H::Context; fn handle_sync( &self, HandlerArgs { @@ -237,7 +219,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, ) -> Result { self.handler.handle_sync(HandlerArgs { context, @@ -257,7 +239,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, ) -> Result { self.handler .handle_async(HandlerArgs { @@ -284,10 +266,12 @@ where self.handler.method_from_dots(method, ctx_ty) } } -impl PrintCliResult for CustomDisplay +impl PrintCliResult for CustomDisplay where + Context: IntoContext, H: HandlerTypes, P: PrintCliResult< + Context, Params = H::Params, InheritedParams = H::InheritedParams, Ok = H::Ok, @@ -297,7 +281,6 @@ where + Clone + 'static, { - type Context = P::Context; fn print( &self, HandlerArgs { @@ -307,7 +290,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, result: Self::Ok, ) -> Result<(), Self::Err> { self.print.print( @@ -356,13 +339,13 @@ where type Err = H::Err; } -impl Handler for CustomDisplayFn +impl Handler for CustomDisplayFn where - Context: Send + Sync + 'static, - H: Handler, + Context: IntoContext, + C: 'static, + H: Handler, F: Send + Sync + Clone + 'static, { - type Context = H::Context; fn handle_sync( &self, HandlerArgs { @@ -372,7 +355,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, ) -> Result { self.handler.handle_sync(HandlerArgs { context, @@ -392,7 +375,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, ) -> Result { self.handler .handle_async(HandlerArgs { @@ -419,13 +402,12 @@ where self.handler.method_from_dots(method, ctx_ty) } } -impl PrintCliResult for CustomDisplayFn +impl PrintCliResult for CustomDisplayFn where Context: IntoContext, H: HandlerTypes, F: Fn(HandlerArgsFor, H::Ok) -> Result<(), H::Err> + Send + Sync + Clone + 'static, { - type Context = Context; fn print( &self, HandlerArgs { @@ -479,16 +461,17 @@ where type Err = H::Err; } -impl Handler for RemoteCaller +impl Handler> + for RemoteCaller where - Context: CallRemote, - H: Handler, + Context: CallRemote, + RemoteContext: IntoContext, + H: Handler, H::Params: Serialize, H::InheritedParams: Serialize, H::Ok: DeserializeOwned, H::Err: From, { - type Context = EitherContext; async fn handle_async( &self, HandlerArgs { @@ -498,7 +481,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, Self>, ) -> Result { match context { EitherContext::C1(context) => { @@ -535,18 +518,17 @@ where self.handler.metadata(method, ctx_ty) } fn contexts(&self) -> Option> { - Self::Context::type_ids() + Context::type_ids() } fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option> { self.handler.method_from_dots(method, ctx_ty) } } -impl PrintCliResult for RemoteCaller +impl PrintCliResult for RemoteCaller where Context: IntoContext, - H: PrintCliResult, + H: PrintCliResult, { - type Context = H::Context; fn print( &self, HandlerArgs { @@ -556,7 +538,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, result: Self::Ok, ) -> Result<(), Self::Err> { self.handler.print( @@ -611,14 +593,15 @@ where type Err = H::Err; } -impl Handler for InheritanceHandler +impl Handler + for InheritanceHandler where + Context: IntoContext, Params: Send + Sync + 'static, InheritedParams: Send + Sync + 'static, - H: Handler, + H: Handler, F: Fn(Params, InheritedParams) -> H::InheritedParams + Send + Sync + Clone + 'static, { - type Context = H::Context; fn handle_sync( &self, HandlerArgs { @@ -628,7 +611,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, ) -> Result { self.handler.handle_sync(HandlerArgs { context, @@ -648,7 +631,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, ) -> Result { self.handler .handle_async(HandlerArgs { @@ -676,15 +659,15 @@ where } } -impl CliBindings +impl CliBindings for InheritanceHandler where + Context: IntoContext, Params: Send + Sync + 'static, InheritedParams: Send + Sync + 'static, - H: CliBindings, + H: CliBindings, F: Fn(Params, InheritedParams) -> H::InheritedParams + Send + Sync + Clone + 'static, { - type Context = H::Context; fn cli_command(&self, ctx_ty: TypeId) -> clap::Command { self.handler.cli_command(ctx_ty) } @@ -704,7 +687,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, result: Self::Ok, ) -> Result<(), Self::Err> { self.handler.cli_display( diff --git a/src/handler/from_fn.rs b/src/handler/from_fn.rs index c77a0f2..253132a 100644 --- a/src/handler/from_fn.rs +++ b/src/handler/from_fn.rs @@ -2,14 +2,16 @@ use std::any::TypeId; use std::collections::VecDeque; use std::fmt::Display; +use clap::{CommandFactory, FromArgMatches}; use futures::Future; use imbl_value::imbl::OrdMap; use imbl_value::Value; use serde::de::DeserializeOwned; +use serde::Serialize; use crate::util::PhantomData; use crate::{ - AnyContext, Empty, Handler, HandlerArgs, HandlerArgsFor, HandlerTypes, IntoContext, + CliBindings, Empty, Handler, HandlerArgs, HandlerArgsFor, HandlerTypes, IntoContext, PrintCliResult, }; @@ -42,18 +44,62 @@ impl std::fmt::Debug for FromFn { .finish() } } -impl PrintCliResult for FromFn +impl PrintCliResult for FromFn where + Context: IntoContext, Self: HandlerTypes, ::Ok: Display, { - type Context = AnyContext; - fn print( + fn print(&self, _: HandlerArgsFor, result: Self::Ok) -> Result<(), Self::Err> { + Ok(println!("{result}")) + } +} +impl CliBindings for FromFn +where + Context: IntoContext, + Self: HandlerTypes, + Self::Params: CommandFactory + FromArgMatches + Serialize, + Self: PrintCliResult, +{ + fn cli_command(&self, _: TypeId) -> clap::Command { + Self::Params::command() + } + fn cli_parse( &self, - _: HandlerArgsFor, + matches: &clap::ArgMatches, + _: TypeId, + ) -> Result<(VecDeque<&'static str>, Value), clap::Error> { + Self::Params::from_arg_matches(matches).and_then(|a| { + Ok(( + VecDeque::new(), + imbl_value::to_value(&a) + .map_err(|e| clap::Error::raw(clap::error::ErrorKind::ValueValidation, e))?, + )) + }) + } + fn cli_display( + &self, + HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }: HandlerArgsFor, result: Self::Ok, ) -> Result<(), Self::Err> { - Ok(println!("{result}")) + self.print( + HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }, + result, + ) } } @@ -106,18 +152,62 @@ impl std::fmt::Debug for FromFnAsync { f.debug_struct("FromFnAsync").finish() } } -impl PrintCliResult for FromFnAsync +impl PrintCliResult for FromFnAsync where + Context: IntoContext, Self: HandlerTypes, ::Ok: Display, { - type Context = AnyContext; - fn print( + fn print(&self, _: HandlerArgsFor, result: Self::Ok) -> Result<(), Self::Err> { + Ok(println!("{result}")) + } +} +impl CliBindings for FromFnAsync +where + Context: IntoContext, + Self: HandlerTypes, + Self::Params: CommandFactory + FromArgMatches + Serialize, + Self: PrintCliResult, +{ + fn cli_command(&self, _: TypeId) -> clap::Command { + Self::Params::command() + } + fn cli_parse( &self, - _: HandlerArgsFor, + matches: &clap::ArgMatches, + _: TypeId, + ) -> Result<(VecDeque<&'static str>, Value), clap::Error> { + Self::Params::from_arg_matches(matches).and_then(|a| { + Ok(( + VecDeque::new(), + imbl_value::to_value(&a) + .map_err(|e| clap::Error::raw(clap::error::ErrorKind::ValueValidation, e))?, + )) + }) + } + fn cli_display( + &self, + HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }: HandlerArgsFor, result: Self::Ok, ) -> Result<(), Self::Err> { - Ok(println!("{result}")) + self.print( + HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }, + result, + ) } } @@ -152,7 +242,7 @@ where type Err = E; } -impl Handler +impl Handler for FromFn> where F: Fn(HandlerArgs) -> Result @@ -166,16 +256,15 @@ where Params: Send + Sync + 'static, InheritedParams: Send + Sync + 'static, { - type Context = Context; fn handle_sync( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { (self.function)(handle_args) } async fn handle_async( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { if self.blocking { self.handle_async_with_sync_blocking(handle_args).await @@ -204,7 +293,7 @@ where type Err = E; } -impl Handler +impl Handler for FromFnAsync> where F: Fn(HandlerArgs) -> Fut + Send + Sync + Clone + 'static, @@ -215,10 +304,9 @@ where Params: Send + Sync + 'static, InheritedParams: Send + Sync + 'static, { - type Context = Context; async fn handle_async( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { (self.function)(handle_args).await } @@ -239,19 +327,19 @@ where type Err = E; } -impl Handler for FromFn +impl Handler for FromFn where + Context: IntoContext, F: Fn() -> Result + Send + Sync + Clone + 'static, T: Send + Sync + 'static, E: Send + Sync + 'static, { - type Context = AnyContext; - fn handle_sync(&self, _: HandlerArgsFor) -> Result { + fn handle_sync(&self, _: HandlerArgsFor) -> Result { (self.function)() } async fn handle_async( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { if self.blocking { self.handle_async_with_sync_blocking(handle_args).await @@ -276,18 +364,15 @@ where type Err = E; } -impl Handler for FromFnAsync +impl Handler for FromFnAsync where + Context: IntoContext, F: Fn() -> Fut + Send + Sync + Clone + 'static, Fut: Future> + Send + 'static, T: Send + Sync + 'static, E: Send + Sync + 'static, { - type Context = AnyContext; - async fn handle_async( - &self, - _: HandlerArgsFor, - ) -> Result { + async fn handle_async(&self, _: HandlerArgsFor) -> Result { (self.function)().await } fn metadata(&self, _: VecDeque<&'static str>, _: TypeId) -> OrdMap<&'static str, Value> { @@ -308,23 +393,22 @@ where type Err = E; } -impl Handler for FromFn +impl Handler for FromFn where Context: IntoContext, F: Fn(Context) -> Result + Send + Sync + Clone + 'static, T: Send + Sync + 'static, E: Send + Sync + 'static, { - type Context = Context; fn handle_sync( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { (self.function)(handle_args.context) } async fn handle_async( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { if self.blocking { self.handle_async_with_sync_blocking(handle_args).await @@ -350,7 +434,7 @@ where type Err = E; } -impl Handler for FromFnAsync +impl Handler for FromFnAsync where Context: IntoContext, F: Fn(Context) -> Fut + Send + Sync + Clone + 'static, @@ -358,10 +442,9 @@ where T: Send + Sync + 'static, E: Send + Sync + 'static, { - type Context = Context; async fn handle_async( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { (self.function)(handle_args.context).await } @@ -384,7 +467,7 @@ where type Err = E; } -impl Handler for FromFn +impl Handler for FromFn where Context: IntoContext, F: Fn(Context, Params) -> Result + Send + Sync + Clone + 'static, @@ -392,10 +475,9 @@ where T: Send + Sync + 'static, E: Send + Sync + 'static, { - type Context = Context; fn handle_sync( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { let HandlerArgs { context, params, .. @@ -404,7 +486,7 @@ where } async fn handle_async( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { if self.blocking { self.handle_async_with_sync_blocking(handle_args).await @@ -431,7 +513,8 @@ where type Err = E; } -impl Handler for FromFnAsync +impl Handler + for FromFnAsync where Context: IntoContext, F: Fn(Context, Params) -> Fut + Send + Sync + Clone + 'static, @@ -440,10 +523,9 @@ where T: Send + Sync + 'static, E: Send + Sync + 'static, { - type Context = Context; async fn handle_async( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { let HandlerArgs { context, params, .. @@ -471,7 +553,7 @@ where type Err = E; } -impl Handler +impl Handler for FromFn where Context: IntoContext, @@ -481,10 +563,9 @@ where T: Send + Sync + 'static, E: Send + Sync + 'static, { - type Context = Context; fn handle_sync( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { let HandlerArgs { context, @@ -496,7 +577,7 @@ where } async fn handle_async( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { if self.blocking { self.handle_async_with_sync_blocking(handle_args).await @@ -525,7 +606,7 @@ where type Err = E; } -impl Handler +impl Handler for FromFnAsync where Context: IntoContext, @@ -536,10 +617,9 @@ where T: Send + Sync + 'static, E: Send + Sync + 'static, { - type Context = Context; async fn handle_async( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { let HandlerArgs { context, diff --git a/src/handler/mod.rs b/src/handler/mod.rs index 31d9587..c7bb9a5 100644 --- a/src/handler/mod.rs +++ b/src/handler/mod.rs @@ -1,9 +1,10 @@ use std::any::TypeId; use std::collections::VecDeque; +use std::marker::PhantomData; use std::ops::Deref; use std::sync::Arc; -use clap::{ArgMatches, Command, CommandFactory, FromArgMatches, Parser}; +use clap::{ArgMatches, Command, Parser}; use futures::Future; use imbl_value::imbl::{OrdMap, OrdSet}; use imbl_value::Value; @@ -72,6 +73,7 @@ pub(crate) trait HandleAny: Send + Sync { ctx_ty: TypeId, ) -> OrdMap<&'static str, Value>; fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option>; + fn cli(&self) -> Option<&dyn CliBindingsAny>; } #[async_trait::async_trait] impl HandleAny for Arc { @@ -95,6 +97,9 @@ impl HandleAny for Arc { fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option> { self.deref().method_from_dots(method, ctx_ty) } + fn cli(&self) -> Option<&dyn CliBindingsAny> { + self.deref().cli() + } } pub(crate) trait CliBindingsAny { @@ -112,8 +117,8 @@ pub(crate) trait CliBindingsAny { ) -> Result<(), RpcError>; } -pub trait CliBindings: HandlerTypes { - type Context: IntoContext; +pub trait CliBindings: HandlerTypes { + const NO_CLI: bool = false; fn cli_command(&self, ctx_ty: TypeId) -> Command; fn cli_parse( &self, @@ -122,124 +127,57 @@ pub trait CliBindings: HandlerTypes { ) -> Result<(VecDeque<&'static str>, Value), clap::Error>; fn cli_display( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, result: Self::Ok, ) -> Result<(), Self::Err>; } -pub trait PrintCliResult: HandlerTypes { - type Context: IntoContext; +pub trait PrintCliResult: HandlerTypes { fn print( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, result: Self::Ok, ) -> Result<(), Self::Err>; } -impl CliBindings for T -where - T: HandlerTypes, - T::Params: CommandFactory + FromArgMatches + Serialize, - T: PrintCliResult, -{ - type Context = T::Context; - fn cli_command(&self, _: TypeId) -> clap::Command { - Self::Params::command() - } - fn cli_parse( - &self, - matches: &clap::ArgMatches, - _: TypeId, - ) -> Result<(VecDeque<&'static str>, Value), clap::Error> { - Self::Params::from_arg_matches(matches).and_then(|a| { - Ok(( - VecDeque::new(), - imbl_value::to_value(&a) - .map_err(|e| clap::Error::raw(clap::error::ErrorKind::ValueValidation, e))?, - )) - }) - } - fn cli_display( - &self, - HandlerArgs { - context, - parent_method, - method, - params, - inherited_params, - raw_params, - }: HandlerArgsFor, - result: Self::Ok, - ) -> Result<(), Self::Err> { - self.print( - HandlerArgs { - context, - parent_method, - method, - params, - inherited_params, - raw_params, - }, - result, - ) - } -} - -pub(crate) trait HandleAnyWithCli: - HandleAny + CliBindingsAny -{ -} -impl + CliBindingsAny> - HandleAnyWithCli for T -{ -} - #[allow(private_interfaces)] -pub enum DynHandler { - WithoutCli(Arc>), - WithCli(Arc>), +pub struct DynHandler(Arc>); +impl DynHandler { + pub fn iter + CliBindings>( + h: H, + ) -> Option, Self)>> { + iter_from_ctx_and_handler(ctx, handler) + } } impl Clone for DynHandler { fn clone(&self) -> Self { - match self { - Self::WithCli(a) => Self::WithCli(a.clone()), - Self::WithoutCli(a) => Self::WithoutCli(a.clone()), - } + Self(self.0.clone()) } } #[async_trait::async_trait] 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), - } + self.0.handle_sync(handle_args) } 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, - } + self.0.handle_async(handle_args).await } fn metadata( &self, method: VecDeque<&'static str>, ctx_ty: TypeId, ) -> OrdMap<&'static str, Value> { - match self { - DynHandler::WithoutCli(h) => h.metadata(method, ctx_ty), - DynHandler::WithCli(h) => h.metadata(method, ctx_ty), - } + self.0.metadata(method, ctx_ty) } fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option> { - match self { - DynHandler::WithoutCli(h) => h.method_from_dots(method, ctx_ty), - DynHandler::WithCli(h) => h.method_from_dots(method, ctx_ty), - } + self.0.method_from_dots(method, ctx_ty) + } + fn cli(&self) -> Option<&dyn CliBindingsAny> { + self.0.cli() } } @@ -268,11 +206,10 @@ pub trait HandlerTypes { type Err: Send + Sync; } -pub trait Handler: HandlerTypes + Clone + Send + Sync + 'static { - type Context: IntoContext; +pub trait Handler: HandlerTypes + Clone + Send + Sync + 'static { fn handle_sync( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> Result { handle_args .context @@ -281,17 +218,17 @@ pub trait Handler: HandlerTypes + Clone + Send + Sync + 'static { } fn handle_async( &self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> impl Future> + Send; fn handle_async_with_sync<'a>( &'a self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> impl Future> + Send + 'a { async move { self.handle_sync(handle_args) } } fn handle_async_with_sync_blocking<'a>( &'a self, - handle_args: HandlerArgsFor, + handle_args: HandlerArgsFor, ) -> impl Future> + Send + 'a { async move { let s = self.clone(); @@ -312,7 +249,7 @@ pub trait Handler: HandlerTypes + Clone + Send + Sync + 'static { OrdMap::new() } fn contexts(&self) -> Option> { - Self::Context::type_ids() + Context::type_ids() } #[allow(unused_variables)] fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option> { @@ -324,30 +261,40 @@ pub trait Handler: HandlerTypes + Clone + Send + Sync + 'static { } } -pub(crate) struct AnyHandler(H); -impl AnyHandler { +pub(crate) struct AnyHandler { + _phantom: PhantomData, + handler: H, +} +impl AnyHandler { pub(crate) fn new(handler: H) -> Self { - Self(handler) + Self { + _phantom: PhantomData, + handler, + } } } -impl std::fmt::Debug for AnyHandler { +impl std::fmt::Debug for AnyHandler { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("AnyHandler").field(&self.0).finish() + f.debug_struct("AnyHandler") + .field("handler", &self.handler) + .finish() } } #[async_trait::async_trait] -impl HandleAny for AnyHandler +impl HandleAny for AnyHandler where + Context: IntoContext, + H: Handler + CliBindings, H::Params: DeserializeOwned, - H::Ok: Serialize, + H::Ok: Serialize + DeserializeOwned, RpcError: From, { type Inherited = H::InheritedParams; fn handle_sync(&self, handle_args: HandleAnyArgs) -> Result { imbl_value::to_value( &self - .0 + .handler .handle_sync(handle_args.downcast::<_, H>().map_err(invalid_params)?)?, ) .map_err(internal_error) @@ -358,7 +305,7 @@ where ) -> Result { imbl_value::to_value( &self - .0 + .handler .handle_async(handle_args.downcast::<_, H>().map_err(invalid_params)?) .await?, ) @@ -369,37 +316,45 @@ where method: VecDeque<&'static str>, ctx_ty: TypeId, ) -> OrdMap<&'static str, Value> { - self.0.metadata(method, ctx_ty) + self.handler.metadata(method, ctx_ty) } fn method_from_dots(&self, method: &str, ctx_ty: TypeId) -> Option> { - self.0.method_from_dots(method, ctx_ty) + self.handler.method_from_dots(method, ctx_ty) + } + fn cli(&self) -> Option<&dyn CliBindingsAny> { + if H::NO_CLI { + None + } else { + Some(self) + } } } -impl CliBindingsAny for AnyHandler +impl CliBindingsAny for AnyHandler where - H: CliBindings, + Context: IntoContext, + H: CliBindings, H::Params: 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) + self.handler.cli_command(ctx_ty) } fn cli_parse( &self, matches: &ArgMatches, ctx_ty: TypeId, ) -> Result<(VecDeque<&'static str>, Value), clap::Error> { - self.0.cli_parse(matches, ctx_ty) + self.handler.cli_parse(matches, ctx_ty) } fn cli_display( &self, handle_args: HandleAnyArgs, result: Value, ) -> Result<(), RpcError> { - self.0 + self.handler .cli_display( handle_args.downcast::<_, H>().map_err(invalid_params)?, imbl_value::from_value(result).map_err(internal_error)?, diff --git a/src/handler/parent.rs b/src/handler/parent.rs index 09d79b1..cd8ff91 100644 --- a/src/handler/parent.rs +++ b/src/handler/parent.rs @@ -1,44 +1,18 @@ use std::any::TypeId; use std::collections::VecDeque; -use std::sync::Arc; use clap::{ArgMatches, Command, CommandFactory, FromArgMatches}; use imbl_value::imbl::{OrdMap, OrdSet}; use imbl_value::Value; -use serde::de::DeserializeOwned; use serde::Serialize; use yajrc::RpcError; use crate::util::{combine, Flat, PhantomData}; use crate::{ - AnyContext, AnyHandler, CliBindings, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, - HandlerArgs, HandlerArgsFor, HandlerExt, HandlerTypes, IntoContext, OrEmpty, + AnyContext, CliBindings, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, HandlerArgs, + HandlerArgsFor, HandlerTypes, IntoContext, }; -pub trait IntoHandlers: HandlerTypes { - fn into_handlers(self) -> impl IntoIterator, DynHandler)>; -} - -impl IntoHandlers> for H -where - H: Handler + CliBindings, - H::Params: 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>)> { - iter_from_ctx_and_handler( - intersect_type_ids(self.contexts(), ::Context::type_ids()), - 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( ctx: Option>, handler: DynHandler, @@ -109,12 +83,12 @@ impl SubcommandMap { } } -pub struct ParentHandler { - _phantom: PhantomData, +pub struct ParentHandler { + _phantom: PhantomData, pub(crate) subcommands: SubcommandMap>, metadata: OrdMap<&'static str, Value>, } -impl ParentHandler { +impl ParentHandler { pub fn new() -> Self { Self { _phantom: PhantomData::new(), @@ -127,7 +101,7 @@ impl ParentHandler { self } } -impl Clone for ParentHandler { +impl Clone for ParentHandler { fn clone(&self) -> Self { Self { _phantom: PhantomData::new(), @@ -136,7 +110,9 @@ impl Clone for ParentHandler { } } } -impl std::fmt::Debug for ParentHandler { +impl std::fmt::Debug + for ParentHandler +{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("ParentHandler") // .field(&self.subcommands) @@ -144,7 +120,9 @@ impl std::fmt::Debug for ParentHandler ParentHandler { +impl + ParentHandler +{ fn get_contexts(&self) -> Option> { let mut set = OrdSet::new(); for ctx_ty in self.subcommands.0.values().flat_map(|c| c.keys()) { @@ -153,25 +131,30 @@ impl ParentHandler { Some(set) } #[allow(private_bounds)] - pub fn subcommand(mut self, name: &'static str, handler: H) -> Self + pub fn subcommand(mut self, name: &'static str, handler: H) -> Self where - H: IntoHandlers>, + H: Handler> + CliBindings, { - self.subcommands - .insert(name.into(), handler.into_handlers()); + if let Some(h) = DynHandler::iter(handler) { + self.subcommands.insert(name.into(), h); + } self } #[allow(private_bounds)] - pub fn root_handler(mut self, handler: H) -> Self + pub fn root_handler(mut self, handler: H) -> Self where - H: IntoHandlers> + HandlerTypes, + H: Handler> + + CliBindings, { - self.subcommands.insert(None, handler.into_handlers()); + if let Some((c, h)) = DynHandler::iter(handler) { + self.subcommands.insert(None, h); + } self } } -impl HandlerTypes for ParentHandler +impl HandlerTypes + for ParentHandler where Params: Send + Sync, InheritedParams: Send + Sync, @@ -182,12 +165,13 @@ where type Err = RpcError; } -impl Handler for ParentHandler +impl Handler + for ParentHandler where + Context: IntoContext, Params: Send + Sync + 'static, InheritedParams: Serialize + Send + Sync + 'static, { - type Context = AnyContext; fn handle_sync( &self, HandlerArgs { @@ -197,7 +181,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, ) -> Result { let cmd = method.pop_front(); if let Some(cmd) = cmd { @@ -205,7 +189,7 @@ where } if let Some((_, sub_handler)) = &self.subcommands.get(context.inner_type_id(), cmd) { sub_handler.handle_sync(HandleAnyArgs { - context, + context: context.upcast(), parent_method, method, params: raw_params, @@ -224,7 +208,7 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, ) -> Result { let cmd = method.pop_front(); if let Some(cmd) = cmd { @@ -233,7 +217,7 @@ where if let Some((_, sub_handler)) = self.subcommands.get(context.inner_type_id(), cmd) { sub_handler .handle_async(HandleAnyArgs { - context, + context: context.upcast(), parent_method, method, params: raw_params, @@ -280,29 +264,30 @@ where } } -impl CliBindings for ParentHandler +impl CliBindings + for ParentHandler where + Context: IntoContext, Params: FromArgMatches + CommandFactory + Serialize + Send + Sync + 'static, InheritedParams: Serialize + Send + Sync + 'static, { - type Context = AnyContext; fn cli_command(&self, ctx_ty: TypeId) -> Command { let mut base = Params::command().subcommand_required(true); for (name, handlers) in &self.subcommands.0 { match ( name, if let Some(handler) = handlers.get(&Some(ctx_ty)) { - Some(handler) + handler.cli() } else if let Some(handler) = handlers.get(&None) { - Some(handler) + handler.cli() } else { None }, ) { - (Name(Some(name)), Some(DynHandler::WithCli(handler))) => { - base = base.subcommand(handler.cli_command(ctx_ty).name(name)); + (Name(Some(name)), Some(cli)) => { + base = base.subcommand(cli.cli_command(ctx_ty).name(name)); } - (Name(None), Some(DynHandler::WithCli(_))) => { + (Name(None), Some(_)) => { base = base.subcommand_required(false); } _ => (), @@ -321,10 +306,12 @@ where Some((name, matches)) => (Some(name), matches), None => (None, matches), }; - if let Some((Name(Some(name)), DynHandler::WithCli(handler))) = - self.subcommands.get(ctx_ty, name) + if let Some((Name(Some(name)), cli)) = self + .subcommands + .get(ctx_ty, name) + .and_then(|(n, h)| h.cli().map(|c| (n, c))) { - let (mut method, params) = handler.cli_parse(matches, ctx_ty)?; + let (mut method, params) = cli.cli_parse(matches, ctx_ty)?; method.push_front(name); Ok(( @@ -345,19 +332,21 @@ where params, inherited_params, raw_params, - }: HandlerArgsFor, + }: HandlerArgsFor, result: Self::Ok, ) -> Result<(), Self::Err> { let cmd = method.pop_front(); if let Some(cmd) = cmd { parent_method.push_back(cmd); } - if let Some((_, DynHandler::WithCli(sub_handler))) = - self.subcommands.get(context.inner_type_id(), cmd) + if let Some((_, cli)) = self + .subcommands + .get(context.inner_type_id(), cmd) + .and_then(|(n, h)| h.cli().map(|c| (n, c))) { - sub_handler.cli_display( + cli.cli_display( HandleAnyArgs { - context, + context: context.upcast(), parent_method, method, params: raw_params, diff --git a/src/lib.rs b/src/lib.rs index 6369216..062b5c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "nightly", feature(const_trait_impl, const_type_id))] + pub use cli::*; // pub use command::*; pub use context::*; diff --git a/src/server/mod.rs b/src/server/mod.rs index 3d86e02..8172522 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -4,11 +4,11 @@ use std::sync::Arc; use futures::future::{join_all, BoxFuture}; use futures::{Future, FutureExt, Stream, StreamExt}; -use imbl_value::{InOMap, Value}; +use imbl_value::Value; use yajrc::{RpcError, RpcMethod}; use crate::util::{invalid_request, JobRunner}; -use crate::{AnyHandler, Empty, HandleAny, HandleAnyArgs, IntoContext, ParentHandler}; +use crate::{AnyHandler, HandleAny, HandleAnyArgs, IntoContext, ParentHandler}; pub type GenericRpcMethod = yajrc::GenericRpcMethod; pub type RpcRequest = yajrc::RpcRequest; @@ -23,7 +23,7 @@ pub use socket::*; pub struct Server { make_ctx: Arc BoxFuture<'static, Result> + Send + Sync>, - root_handler: Arc>, + root_handler: Arc>>, } impl Clone for Server { fn clone(&self) -> Self { @@ -39,7 +39,7 @@ impl Server { Fut: Future> + Send + 'static, >( make_ctx: MakeCtx, - root_handler: ParentHandler, + root_handler: ParentHandler, ) -> Self { Server { make_ctx: Arc::new(move || make_ctx().boxed()), diff --git a/tests/handler.rs b/tests/handler.rs index 74ca8a1..8b9bde2 100644 --- a/tests/handler.rs +++ b/tests/handler.rs @@ -140,7 +140,7 @@ fn make_api() -> ParentHandler { .subcommand("a_hello", from_fn_async(a_hello)) .subcommand( "dondes", - ParentHandler::::new().subcommand( + ParentHandler::::new().subcommand( "donde", from_fn(|c: CliContext, _: (), donde| { Ok::<_, RpcError>( @@ -157,7 +157,7 @@ fn make_api() -> ParentHandler { ) .subcommand( "fizz", - ParentHandler::::new().root_handler( + ParentHandler::::new().root_handler( from_fn(|c: CliContext, _: Empty, InheritParams { donde }| { Ok::<_, RpcError>( format!( @@ -172,7 +172,7 @@ fn make_api() -> ParentHandler { ) .subcommand( "error", - ParentHandler::::new().root_handler( + ParentHandler::::new().root_handler( from_fn(|_: CliContext, _: Empty, InheritParams { .. }| { Err::(RpcError { code: 1,