diff --git a/src/handler/adapters.rs b/src/handler/adapters.rs index 36e9528..024f7c0 100644 --- a/src/handler/adapters.rs +++ b/src/handler/adapters.rs @@ -44,6 +44,9 @@ pub trait HandlerExt: HandlerFor + Sized { fn with_about(self, message: M) -> WithAbout where M: IntoResettable; + fn no_ts(self) -> NoTS; + fn unknown_ts(self) -> UnknownTS; + fn custom_ts(self, params_ty: String, return_ty: String) -> CustomTS; } impl + Sized> HandlerExt for T { @@ -107,6 +110,22 @@ impl + Sized> HandlerExt NoTS { + NoTS(self) + } + + fn unknown_ts(self) -> UnknownTS { + UnknownTS(self) + } + + fn custom_ts(self, params_ty: String, return_ty: String) -> CustomTS { + CustomTS { + handler: self, + params_ty, + return_ty, + } + } } #[derive(Debug, Clone)] @@ -648,7 +667,7 @@ impl Handler where Context: crate::Context + CallRemote, RemoteContext: crate::Context, - H: HandlerFor + CliBindings, + H: HandlerFor + CliBindings + crate::handler::HandlerTS, H::Ok: Serialize + DeserializeOwned, H::Err: From, H::Params: Serialize + DeserializeOwned, @@ -926,3 +945,304 @@ where self.handler.cli_display(handler, result) } } + +#[derive(Debug, Clone)] +pub struct NoTS(pub H); + +impl HandlerTypes for NoTS +where + H: HandlerTypes, +{ + type Params = H::Params; + type InheritedParams = H::InheritedParams; + type Ok = H::Ok; + type Err = H::Err; +} + +#[cfg(feature = "ts-rs")] +impl crate::handler::HandlerTS for NoTS { + fn type_info(&self) -> Option { + None + } +} + +impl HandlerFor for NoTS +where + Context: crate::Context, + H: HandlerFor, +{ + fn handle_sync( + &self, + HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }: HandlerArgsFor, + ) -> Result { + self.0.handle_sync(HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }) + } + async fn handle_async( + &self, + HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }: HandlerArgsFor, + ) -> Result { + self.0 + .handle_async(HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }) + .await + } + fn metadata(&self, method: VecDeque<&'static str>) -> OrdMap<&'static str, Value> { + self.0.metadata(method) + } + fn method_from_dots(&self, method: &str) -> Option> { + self.0.method_from_dots(method) + } +} + +impl CliBindings for NoTS +where + Context: crate::Context, + H: CliBindings, +{ + fn cli_command(&self) -> clap::Command { + self.0.cli_command() + } + fn cli_parse( + &self, + arg_matches: &clap::ArgMatches, + ) -> Result<(VecDeque<&'static str>, Value), clap::Error> { + self.0.cli_parse(arg_matches) + } + fn cli_display( + &self, + handler: HandlerArgsFor, + result: Self::Ok, + ) -> Result<(), Self::Err> { + self.0.cli_display(handler, result) + } +} + +#[derive(Debug, Clone)] +pub struct UnknownTS(pub H); + +impl HandlerTypes for UnknownTS +where + H: HandlerTypes, +{ + type Params = H::Params; + type InheritedParams = H::InheritedParams; + type Ok = H::Ok; + type Err = H::Err; +} + +#[cfg(feature = "ts-rs")] +impl crate::handler::HandlerTS for UnknownTS { + fn type_info(&self) -> Option { + Some("{_PARAMS:unknown,_RETURN:unknown}".to_string()) + } +} + +impl HandlerFor for UnknownTS +where + Context: crate::Context, + H: HandlerFor, +{ + fn handle_sync( + &self, + HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }: HandlerArgsFor, + ) -> Result { + self.0.handle_sync(HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }) + } + async fn handle_async( + &self, + HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }: HandlerArgsFor, + ) -> Result { + self.0 + .handle_async(HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }) + .await + } + fn metadata(&self, method: VecDeque<&'static str>) -> OrdMap<&'static str, Value> { + self.0.metadata(method) + } + fn method_from_dots(&self, method: &str) -> Option> { + self.0.method_from_dots(method) + } +} + +impl CliBindings for UnknownTS +where + Context: crate::Context, + H: CliBindings, +{ + fn cli_command(&self) -> clap::Command { + self.0.cli_command() + } + fn cli_parse( + &self, + arg_matches: &clap::ArgMatches, + ) -> Result<(VecDeque<&'static str>, Value), clap::Error> { + self.0.cli_parse(arg_matches) + } + fn cli_display( + &self, + handler: HandlerArgsFor, + result: Self::Ok, + ) -> Result<(), Self::Err> { + self.0.cli_display(handler, result) + } +} + +#[derive(Debug, Clone)] +pub struct CustomTS { + pub handler: H, + pub params_ty: String, + pub return_ty: String, +} + +impl HandlerTypes for CustomTS +where + H: HandlerTypes, +{ + type Params = H::Params; + type InheritedParams = H::InheritedParams; + type Ok = H::Ok; + type Err = H::Err; +} + +#[cfg(feature = "ts-rs")] +impl crate::handler::HandlerTS for CustomTS { + fn type_info(&self) -> Option { + Some(format!( + "{{_PARAMS:{},_RETURN:{}}}", + self.params_ty, self.return_ty + )) + } +} + +impl HandlerFor for CustomTS +where + Context: crate::Context, + H: HandlerFor, +{ + fn handle_sync( + &self, + HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }: HandlerArgsFor, + ) -> Result { + self.handler.handle_sync(HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }) + } + async fn handle_async( + &self, + HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }: HandlerArgsFor, + ) -> Result { + self.handler + .handle_async(HandlerArgs { + context, + parent_method, + method, + params, + inherited_params, + raw_params, + }) + .await + } + fn metadata(&self, method: VecDeque<&'static str>) -> OrdMap<&'static str, Value> { + self.handler.metadata(method) + } + fn method_from_dots(&self, method: &str) -> Option> { + self.handler.method_from_dots(method) + } +} + +impl CliBindings for CustomTS +where + Context: crate::Context, + H: CliBindings, +{ + fn cli_command(&self) -> clap::Command { + self.handler.cli_command() + } + fn cli_parse( + &self, + arg_matches: &clap::ArgMatches, + ) -> Result<(VecDeque<&'static str>, Value), clap::Error> { + self.handler.cli_parse(arg_matches) + } + fn cli_display( + &self, + handler: HandlerArgsFor, + result: Self::Ok, + ) -> Result<(), Self::Err> { + self.handler.cli_display(handler, result) + } +} diff --git a/src/handler/mod.rs b/src/handler/mod.rs index aa09d7c..fdf6220 100644 --- a/src/handler/mod.rs +++ b/src/handler/mod.rs @@ -55,28 +55,22 @@ impl HandleAnyArgs Option; + #[allow(dead_code)] + fn type_info(&self) -> Option { + None + } } -#[cfg(feature = "ts-rs")] impl HandleAnyTS for Arc { fn type_info(&self) -> Option { self.deref().type_info() } } -#[cfg(feature = "ts-rs")] pub(crate) trait HandleAnyRequires: HandleAnyTS + Send + Sync {} -#[cfg(feature = "ts-rs")] impl HandleAnyRequires for T {} -#[cfg(not(feature = "ts-rs"))] -pub(crate) trait HandleAnyRequires: Send + Sync {} -#[cfg(not(feature = "ts-rs"))] -impl HandleAnyRequires for T {} - #[async_trait::async_trait] pub(crate) trait HandleAny: HandleAnyRequires { type Inherited: Send; @@ -175,7 +169,6 @@ impl Debug for DynHandler { f.debug_struct("DynHandler").finish() } } -#[cfg(feature = "ts-rs")] impl HandleAnyTS for DynHandler { fn type_info(&self) -> Option { self.0.type_info() @@ -234,19 +227,18 @@ pub trait HandlerTypes { type Err: Send + Sync; } -#[cfg(feature = "ts-rs")] pub trait HandlerTS { fn type_info(&self) -> Option; } -#[cfg(feature = "ts-rs")] -pub trait HandlerRequires: HandlerTS + HandlerTypes + Clone + Send + Sync + 'static {} -#[cfg(feature = "ts-rs")] -impl HandlerRequires for T {} +#[cfg(not(feature = "ts-rs"))] +impl HandlerTS for T { + fn type_info(&self) -> Option { + None + } +} -#[cfg(not(feature = "ts-rs"))] pub trait HandlerRequires: HandlerTypes + Clone + Send + Sync + 'static {} -#[cfg(not(feature = "ts-rs"))] impl HandlerRequires for T {} pub trait HandlerFor: HandlerRequires { @@ -321,7 +313,7 @@ impl WithContext { impl Handler for WithContext where Context: crate::Context, - H: HandlerFor + CliBindings, + H: HandlerFor + CliBindings + HandlerTS, H::Ok: Serialize + DeserializeOwned, H::Params: DeserializeOwned, H::InheritedParams: OrEmpty, @@ -362,10 +354,9 @@ impl std::fmt::Debug for AnyHandler HandleAnyTS for AnyHandler where - H: crate::handler::HandlerTS, + H: HandlerTS, { fn type_info(&self) -> Option { self.handler.type_info() @@ -376,7 +367,7 @@ where impl HandleAny for AnyHandler where Context: crate::Context, - H: HandlerFor + CliBindings, + H: HandlerFor + CliBindings + HandlerTS, H::Params: DeserializeOwned, H::Ok: Serialize + DeserializeOwned, H::InheritedParams: OrEmpty, diff --git a/src/lib.rs b/src/lib.rs index 73d0a16..112db5f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -#![cfg_attr(feature = "nightly", feature(const_trait_impl, const_type_id))] - pub use cli::*; // pub use command::*; pub use context::*; diff --git a/tests/test.rs b/tests/test.rs index a0a9f9b..44b9bb4 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,5 +1,7 @@ use clap::Parser; -use rpc_toolkit::{from_fn_async, Context, Empty, HandlerTS, ParentHandler, Server}; +use rpc_toolkit::{ + from_fn, from_fn_async, Context, Empty, HandlerExt, HandlerTS, ParentHandler, Server, +}; use serde::{Deserialize, Serialize}; use yajrc::RpcError; @@ -14,10 +16,19 @@ struct Thing1Params { thing: String, } +#[derive(Debug, Deserialize, Serialize, Parser)] +struct NoTSParams { + foo: String, +} + async fn thing1_handler(_ctx: TestContext, params: Thing1Params) -> Result { Ok(format!("Thing1 is {}", params.thing)) } +fn no_ts_handler(_ctx: TestContext, params: NoTSParams) -> Result { + Ok(format!("foo:{}", params.foo)) +} + #[derive(Debug, Deserialize, Serialize, Parser)] #[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))] struct GroupParams { @@ -38,7 +49,8 @@ async fn test_basic_server() { from_fn_async(|_ctx: TestContext, params: GroupParams| async move { Ok::<_, RpcError>(format!("verbose: {}", params.verbose)) }), - ), + ) + .subcommand("no-ts", from_fn(no_ts_handler).no_ts()), ); println!("{}", root_handler.type_info().unwrap_or_default());