better custom ts for parent handlers

This commit is contained in:
Aiden McClelland
2025-11-10 14:51:40 -07:00
parent eb64c1f422
commit 4f036d0345
4 changed files with 96 additions and 26 deletions

View File

@@ -13,7 +13,7 @@ use yajrc::RpcError;
use crate::util::{Flat, PhantomData}; use crate::util::{Flat, PhantomData};
use crate::{ use crate::{
CallRemote, CallRemoteHandler, CliBindings, DynHandler, Handler, HandlerArgs, HandlerArgsFor, CallRemote, CallRemoteHandler, CliBindings, DynHandler, Handler, HandlerArgs, HandlerArgsFor,
HandlerFor, HandlerTypes, OrEmpty, PrintCliResult, WithContext, HandlerFor, HandlerTypes, LeafHandler, OrEmpty, PrintCliResult, WithContext,
}; };
pub trait HandlerExt<Context: crate::Context>: HandlerFor<Context> + Sized { pub trait HandlerExt<Context: crate::Context>: HandlerFor<Context> + Sized {
@@ -130,6 +130,9 @@ impl<Context: crate::Context, T: HandlerFor<Context> + Sized> HandlerExt<Context
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct NoCli<H>(pub H); pub struct NoCli<H>(pub H);
impl<H: LeafHandler> LeafHandler for NoCli<H> {}
impl<H: HandlerTypes> HandlerTypes for NoCli<H> { impl<H: HandlerTypes> HandlerTypes for NoCli<H> {
type Params = H::Params; type Params = H::Params;
type InheritedParams = H::InheritedParams; type InheritedParams = H::InheritedParams;
@@ -221,6 +224,9 @@ where
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct NoDisplay<H>(pub H); pub struct NoDisplay<H>(pub H);
impl<H: LeafHandler> LeafHandler for NoDisplay<H> {}
impl<H: HandlerTypes> HandlerTypes for NoDisplay<H> { impl<H: HandlerTypes> HandlerTypes for NoDisplay<H> {
type Params = H::Params; type Params = H::Params;
type InheritedParams = H::InheritedParams; type InheritedParams = H::InheritedParams;
@@ -337,6 +343,9 @@ pub struct CustomDisplay<P, H> {
print: P, print: P,
handler: H, handler: H,
} }
impl<P, H: LeafHandler> LeafHandler for CustomDisplay<P, H> {}
impl<P, H> HandlerTypes for CustomDisplay<P, H> impl<P, H> HandlerTypes for CustomDisplay<P, H>
where where
H: HandlerTypes, H: HandlerTypes,
@@ -488,6 +497,9 @@ pub struct CustomDisplayFn<F, H, Context> {
print: F, print: F,
handler: H, handler: H,
} }
impl<F, H: LeafHandler, Context> LeafHandler for CustomDisplayFn<F, H, Context> {}
impl<Context, F: Clone, H: Clone> Clone for CustomDisplayFn<F, H, Context> { impl<Context, F: Clone, H: Clone> Clone for CustomDisplayFn<F, H, Context> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
@@ -648,6 +660,12 @@ pub struct RemoteCaller<Context, RemoteContext, H> {
_phantom: PhantomData<(Context, RemoteContext)>, _phantom: PhantomData<(Context, RemoteContext)>,
handler: H, handler: H,
} }
impl<Context, RemoteContext, H: LeafHandler> LeafHandler
for RemoteCaller<Context, RemoteContext, H>
{
}
impl<Context, RemoteContext, H: Clone> Clone for RemoteCaller<Context, RemoteContext, H> { impl<Context, RemoteContext, H: Clone> Clone for RemoteCaller<Context, RemoteContext, H> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
@@ -694,6 +712,12 @@ pub struct InheritanceHandler<Params, InheritedParams, H, F> {
handler: H, handler: H,
inherit: F, inherit: F,
} }
impl<Params, InheritedParams, H: LeafHandler, F> LeafHandler
for InheritanceHandler<Params, InheritedParams, H, F>
{
}
impl<Params, InheritedParams, H: Clone, F: Clone> Clone impl<Params, InheritedParams, H: Clone, F: Clone> Clone
for InheritanceHandler<Params, InheritedParams, H, F> for InheritanceHandler<Params, InheritedParams, H, F>
{ {
@@ -848,6 +872,9 @@ pub struct WithAbout<M, H> {
handler: H, handler: H,
message: M, message: M,
} }
impl<M, H: LeafHandler> LeafHandler for WithAbout<M, H> {}
impl<M, H> HandlerTypes for WithAbout<M, H> impl<M, H> HandlerTypes for WithAbout<M, H>
where where
H: HandlerTypes, H: HandlerTypes,
@@ -949,6 +976,8 @@ where
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct NoTS<H>(pub H); pub struct NoTS<H>(pub H);
impl<H: LeafHandler> LeafHandler for NoTS<H> {}
impl<H> HandlerTypes for NoTS<H> impl<H> HandlerTypes for NoTS<H>
where where
H: HandlerTypes, H: HandlerTypes,
@@ -1047,6 +1076,8 @@ where
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct UnknownTS<H>(pub H); pub struct UnknownTS<H>(pub H);
impl<H: LeafHandler> LeafHandler for UnknownTS<H> {}
impl<H> HandlerTypes for UnknownTS<H> impl<H> HandlerTypes for UnknownTS<H>
where where
H: HandlerTypes, H: HandlerTypes,
@@ -1058,7 +1089,7 @@ where
} }
#[cfg(feature = "ts-rs")] #[cfg(feature = "ts-rs")]
impl<H> crate::handler::HandlerTS for UnknownTS<H> { impl<H: LeafHandler> crate::handler::HandlerTS for UnknownTS<H> {
fn type_info(&self) -> Option<String> { fn type_info(&self) -> Option<String> {
Some("{_PARAMS:unknown,_RETURN:unknown}".to_string()) Some("{_PARAMS:unknown,_RETURN:unknown}".to_string())
} }
@@ -1149,6 +1180,8 @@ pub struct CustomTS<H> {
pub return_ty: String, pub return_ty: String,
} }
impl<H: LeafHandler> LeafHandler for CustomTS<H> {}
impl<H> HandlerTypes for CustomTS<H> impl<H> HandlerTypes for CustomTS<H>
where where
H: HandlerTypes, H: HandlerTypes,
@@ -1160,7 +1193,7 @@ where
} }
#[cfg(feature = "ts-rs")] #[cfg(feature = "ts-rs")]
impl<H> crate::handler::HandlerTS for CustomTS<H> { impl<H: LeafHandler> crate::handler::HandlerTS for CustomTS<H> {
fn type_info(&self) -> Option<String> { fn type_info(&self) -> Option<String> {
Some(format!( Some(format!(
"{{_PARAMS:{},_RETURN:{}}}", "{{_PARAMS:{},_RETURN:{}}}",

View File

@@ -12,7 +12,8 @@ use ts_rs::TS;
use crate::util::PhantomData; use crate::util::PhantomData;
use crate::{ use crate::{
CliBindings, Empty, HandlerArgs, HandlerArgsFor, HandlerFor, HandlerTypes, PrintCliResult, CliBindings, Empty, HandlerArgs, HandlerArgsFor, HandlerFor, HandlerTypes, LeafHandler,
PrintCliResult,
}; };
pub struct FromFn<F, T, E, Args> { pub struct FromFn<F, T, E, Args> {
@@ -21,6 +22,8 @@ pub struct FromFn<F, T, E, Args> {
blocking: bool, blocking: bool,
metadata: OrdMap<&'static str, Value>, metadata: OrdMap<&'static str, Value>,
} }
impl<F, T, E, Args> LeafHandler for FromFn<F, T, E, Args> {}
impl<F, T, E, Args> FromFn<F, T, E, Args> { impl<F, T, E, Args> FromFn<F, T, E, Args> {
pub fn with_metadata(mut self, key: &'static str, value: Value) -> Self { pub fn with_metadata(mut self, key: &'static str, value: Value) -> Self {
self.metadata.insert(key, value); self.metadata.insert(key, value);
@@ -147,6 +150,8 @@ pub struct FromFnAsync<F, Fut, T, E, Args> {
function: F, function: F,
metadata: OrdMap<&'static str, Value>, metadata: OrdMap<&'static str, Value>,
} }
impl<F, Fut, T, E, Args> LeafHandler for FromFnAsync<F, Fut, T, E, Args> {}
impl<F, Fut, T, E, Args> FromFnAsync<F, Fut, T, E, Args> { impl<F, Fut, T, E, Args> FromFnAsync<F, Fut, T, E, Args> {
pub fn with_metadata(mut self, key: &'static str, value: Value) -> Self { pub fn with_metadata(mut self, key: &'static str, value: Value) -> Self {
self.metadata.insert(key, value); self.metadata.insert(key, value);
@@ -257,6 +262,8 @@ pub struct FromFnAsyncLocal<F, Fut, T, E, Args> {
function: F, function: F,
metadata: OrdMap<&'static str, Value>, metadata: OrdMap<&'static str, Value>,
} }
impl<F, Fut, T, E, Args> LeafHandler for FromFnAsyncLocal<F, Fut, T, E, Args> {}
impl<F, Fut, T, E, Args> FromFnAsyncLocal<F, Fut, T, E, Args> { impl<F, Fut, T, E, Args> FromFnAsyncLocal<F, Fut, T, E, Args> {
pub fn with_metadata(mut self, key: &'static str, value: Value) -> Self { pub fn with_metadata(mut self, key: &'static str, value: Value) -> Self {
self.metadata.insert(key, value); self.metadata.insert(key, value);

View File

@@ -227,6 +227,8 @@ pub trait HandlerTypes {
type Err: Send + Sync; type Err: Send + Sync;
} }
pub trait LeafHandler {}
pub trait HandlerTS { pub trait HandlerTS {
fn type_info(&self) -> Option<String>; fn type_info(&self) -> Option<String>;
} }

View File

@@ -14,6 +14,8 @@ use crate::{
CliBindings, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, HandlerArgs, HandlerArgsFor, CliBindings, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, HandlerArgs, HandlerArgsFor,
HandlerFor, HandlerRequires, HandlerTypes, WithContext, HandlerFor, HandlerRequires, HandlerTypes, WithContext,
}; };
#[cfg(feature = "ts-rs")]
use crate::{CustomTS, UnknownTS};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) struct Name(pub(crate) &'static str); pub(crate) struct Name(pub(crate) &'static str);
@@ -86,6 +88,31 @@ impl<Context, Params, InheritedParams> ParentHandler<Context, Params, InheritedP
self.metadata.insert(key, value); self.metadata.insert(key, value);
self self
} }
#[cfg(feature = "ts-rs")]
fn type_info_impl(&self, params_ty: &str) -> Option<String> {
use std::fmt::Write;
let mut res = "{".to_owned();
res.push_str("_CHILDREN:{");
for (name, handler) in &self.subcommands.1 {
let Some(ty) = handler.type_info() else {
continue;
};
write!(
&mut res,
"{}:{};",
serde_json::to_string(&name.0).unwrap(),
ty,
)
.ok()?;
}
res.push_str("};}");
if let Some(ty) = self.subcommands.0.as_ref().and_then(|h| h.type_info()) {
write!(&mut res, "&{}", ty).ok()?;
} else {
write!(&mut res, "&{{_PARAMS:{}}}", params_ty).ok()?;
}
Some(res)
}
} }
impl<Context, Params, InheritedParams> Clone for ParentHandler<Context, Params, InheritedParams> { impl<Context, Params, InheritedParams> Clone for ParentHandler<Context, Params, InheritedParams> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
@@ -150,28 +177,29 @@ where
InheritedParams: Send + Sync + 'static, InheritedParams: Send + Sync + 'static,
{ {
fn type_info(&self) -> Option<String> { fn type_info(&self) -> Option<String> {
use std::fmt::Write; self.type_info_impl(&Params::inline())
let mut res = "{".to_owned(); }
res.push_str("_CHILDREN:{"); }
for (name, handler) in &self.subcommands.1 { #[cfg(feature = "ts-rs")]
let Some(ty) = handler.type_info() else { impl<Context, Params, InheritedParams> crate::handler::HandlerTS
continue; for CustomTS<ParentHandler<Context, Params, InheritedParams>>
}; where
write!( Params: Send + Sync + 'static,
&mut res, InheritedParams: Send + Sync + 'static,
"{}:{};", {
serde_json::to_string(&name.0).unwrap(), fn type_info(&self) -> Option<String> {
ty, self.handler.type_info_impl(&self.params_ty)
) }
.ok()?; }
} #[cfg(feature = "ts-rs")]
res.push_str("};}"); impl<Context, Params, InheritedParams> crate::handler::HandlerTS
if let Some(ty) = self.subcommands.0.as_ref().and_then(|h| h.type_info()) { for UnknownTS<ParentHandler<Context, Params, InheritedParams>>
write!(&mut res, "&{}", ty).ok()?; where
} else { Params: Send + Sync + 'static,
write!(&mut res, "&{{_PARAMS:{}}}", Params::inline()).ok()?; InheritedParams: Send + Sync + 'static,
} {
Some(res) fn type_info(&self) -> Option<String> {
self.0.type_info_impl("unknown")
} }
} }