mirror of
https://github.com/Start9Labs/rpc-toolkit.git
synced 2026-03-26 02:11:56 +00:00
wip: metadata
This commit is contained in:
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -1745,9 +1745,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "visit-rs"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbd4baf031bf580bc7ba411f4625a304909c975bf3d3e8d9c43ed88d23be1b8e"
|
||||
checksum = "f89c27f644c3e4ce302bc7bce5144e295405d569784e5f4921271404e600cecf"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"futures",
|
||||
@@ -1757,9 +1757,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "visit-rs-derive"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2336cc680cfb205620939f0fa62348a4b6da37d1e727670f3d7d77aebc50b611"
|
||||
checksum = "2a3bfb04fd13da4fc8df24709b7a0949667f43c63691d9fecddf1d3be8af5099"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
authors = ["Aiden McClelland <me@drbonez.dev>"]
|
||||
description = "A toolkit for creating JSON-RPC 2.0 servers with automatic cli bindings"
|
||||
documentation = "https://docs.rs/rpc-toolkit"
|
||||
edition = "2018"
|
||||
edition = "2024"
|
||||
keywords = ["cli", "json", "rpc"]
|
||||
license = "MIT"
|
||||
name = "rpc-toolkit"
|
||||
@@ -39,5 +39,5 @@ thiserror = "2.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-stream = { version = "0.1", features = ["io-util", "net"] }
|
||||
url = "2"
|
||||
visit-rs = { version = "0.1.8", optional = true }
|
||||
visit-rs = { version = "0.1.9", optional = true }
|
||||
yajrc = "0.1"
|
||||
|
||||
@@ -50,11 +50,11 @@ impl<Context: crate::Context> Server<Context> {
|
||||
&self,
|
||||
method: &str,
|
||||
params: Value,
|
||||
) -> impl Future<Output = Result<Value, RpcError>> + Send + 'static {
|
||||
) -> impl Future<Output = Result<Value, RpcError>> + Send + 'static + use<Context> {
|
||||
let (make_ctx, root_handler, method) = (
|
||||
self.make_ctx.clone(),
|
||||
self.root_handler.clone(),
|
||||
self.root_handler.method_from_dots(method),
|
||||
self.root_handler.method_from_dots(method.as_ref()),
|
||||
);
|
||||
|
||||
async move {
|
||||
@@ -74,14 +74,11 @@ impl<Context: crate::Context> Server<Context> {
|
||||
&self,
|
||||
RpcRequest { id, method, params }: RpcRequest,
|
||||
) -> impl Future<Output = RpcResponse> + Send + 'static {
|
||||
let handle = (|| Ok::<_, RpcError>(self.handle_command(method.as_str(), params)))();
|
||||
let handle = self.handle_command(method.as_str(), params);
|
||||
async move {
|
||||
RpcResponse {
|
||||
id,
|
||||
result: match handle {
|
||||
Ok(handle) => handle.await,
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
result: handle.await,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
143
src/ts.rs
143
src/ts.rs
@@ -6,7 +6,11 @@ use std::sync::Arc;
|
||||
|
||||
use imbl_value::imbl::{OrdMap, Vector};
|
||||
use imbl_value::InternedString;
|
||||
use visit_rs::{Named, Static, Visit, VisitFieldsStaticNamed, Visitor};
|
||||
use visit_rs::{
|
||||
Named, Static, StructInfo, StructInfoData, Variant, Visit, VisitFieldsStatic,
|
||||
VisitFieldsStaticNamed, VisitVariantFieldsStatic, VisitVariantFieldsStaticNamed,
|
||||
VisitVariantsStatic, Visitor,
|
||||
};
|
||||
|
||||
use crate::{Adapter, FromFn, FromFnAsync, FromFnAsyncLocal, HandlerTypes, ParentHandler};
|
||||
|
||||
@@ -315,6 +319,96 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SerdeTag {
|
||||
pub tag: Option<syn::LitStr>,
|
||||
pub contents: Option<syn::LitStr>,
|
||||
}
|
||||
impl SerdeTag {
|
||||
pub fn apply_meta(this: &mut Option<Self>, meta: &syn::Meta) {
|
||||
if meta.path().is_ident("untagged") {
|
||||
*this = None;
|
||||
} else if meta.path().is_ident("tag") {
|
||||
if let Some(tag) = meta.require_name_value().ok() {
|
||||
if let syn::Expr::Lit(syn::ExprLit {
|
||||
lit: syn::Lit::Str(tag),
|
||||
..
|
||||
}) = &tag.value
|
||||
{
|
||||
this.get_or_insert_default().tag = Some(tag.clone());
|
||||
}
|
||||
}
|
||||
} else if meta.path().is_ident("contents") {
|
||||
if let Some(tag) = meta.require_name_value().ok() {
|
||||
if let syn::Expr::Lit(syn::ExprLit {
|
||||
lit: syn::Lit::Str(tag),
|
||||
..
|
||||
}) = &tag.value
|
||||
{
|
||||
this.get_or_insert_default().contents = Some(tag.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn from_metas(metas: &[syn::Meta]) -> Option<Self> {
|
||||
let mut res = Some(SerdeTag::default());
|
||||
for meta in metas.into_iter().filter_map(|m| m.require_list().ok()) {
|
||||
if meta.path.is_ident("serde") {
|
||||
syn::parse2::<syn::Meta>(meta.tokens.clone())
|
||||
.ok()
|
||||
.as_ref()
|
||||
.map(|meta| Self::apply_meta(&mut res, meta));
|
||||
}
|
||||
}
|
||||
for meta in metas.into_iter().filter_map(|m| m.require_list().ok()) {
|
||||
if meta.path.is_ident("visit") {
|
||||
if let Some(meta) = syn::parse2::<syn::Meta>(meta.tokens.clone())
|
||||
.ok()
|
||||
.as_ref()
|
||||
.and_then(|m| m.require_list().ok())
|
||||
{
|
||||
if meta.path.is_ident("ts") {
|
||||
syn::parse2::<syn::Meta>(meta.tokens.clone())
|
||||
.ok()
|
||||
.as_ref()
|
||||
.map(|meta| Self::apply_meta(&mut res, meta));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Visit<TSVisitor> for Variant<'a, Static<T>>
|
||||
where
|
||||
T: TS,
|
||||
T: VisitVariantFieldsStaticNamed<TSVisitor> + VisitVariantFieldsStatic<TSVisitor>,
|
||||
{
|
||||
fn visit(&self, visitor: &mut TSVisitor) -> <TSVisitor as Visitor>::Result {
|
||||
// TODO: handle serde tagging
|
||||
let tag = Some(SerdeTag {
|
||||
tag: None,
|
||||
contents: None,
|
||||
});
|
||||
|
||||
if T::DATA.variant_count > 1 {
|
||||
visitor.ts.push('|');
|
||||
}
|
||||
visit_struct_impl(
|
||||
&self.info,
|
||||
|name, visitor| {
|
||||
if name {
|
||||
T::visit_variant_fields_static_named(&self.info, visitor).for_each(drop);
|
||||
} else {
|
||||
T::visit_variant_fields_static(&self.info, visitor).for_each(drop);
|
||||
}
|
||||
},
|
||||
visitor,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LiteralTS(Cow<'static, str>);
|
||||
impl Visit<TSVisitor> for LiteralTS {
|
||||
fn visit(&self, visitor: &mut TSVisitor) -> <TSVisitor as Visitor>::Result {
|
||||
@@ -347,22 +441,44 @@ impl_ts!(u64,u128,i64,i128 => "bigint");
|
||||
impl_ts!(Unknown,imbl_value::Value,serde_json::Value,serde_cbor::Value => "unknown");
|
||||
impl_ts!(Never => "never");
|
||||
|
||||
pub fn visit_struct<T>(visitor: &mut TSVisitor)
|
||||
where
|
||||
T: VisitFieldsStaticNamed<TSVisitor>,
|
||||
{
|
||||
if T::NAMED_FIELDS {
|
||||
fn visit_struct_impl(
|
||||
info: &StructInfoData,
|
||||
fields: impl FnOnce(bool, &mut TSVisitor),
|
||||
visitor: &mut TSVisitor,
|
||||
) {
|
||||
if !info.named_fields && info.field_count == 1 {
|
||||
fields(false, visitor)
|
||||
} else {
|
||||
if info.named_fields {
|
||||
visitor.ts.push_str("{");
|
||||
} else {
|
||||
visitor.ts.push_str("[");
|
||||
}
|
||||
T::visit_fields_static_named(visitor).for_each(drop);
|
||||
if T::NAMED_FIELDS {
|
||||
fields(true, visitor);
|
||||
if info.named_fields {
|
||||
visitor.ts.push_str("}");
|
||||
} else {
|
||||
visitor.ts.push_str("]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_struct<T>(visitor: &mut TSVisitor)
|
||||
where
|
||||
T: VisitFieldsStaticNamed<TSVisitor> + VisitFieldsStatic<TSVisitor>,
|
||||
{
|
||||
visit_struct_impl(
|
||||
&T::DATA,
|
||||
|named, visitor| {
|
||||
if named {
|
||||
T::visit_fields_static_named(visitor).for_each(drop);
|
||||
} else {
|
||||
T::visit_fields_static(visitor).for_each(drop);
|
||||
}
|
||||
},
|
||||
visitor,
|
||||
);
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_ts_struct {
|
||||
@@ -376,6 +492,17 @@ macro_rules! impl_ts_struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn visit_enum<T>(visitor: &mut TSVisitor)
|
||||
where
|
||||
T: VisitVariantsStatic<TSVisitor>,
|
||||
{
|
||||
if T::DATA.variant_count == 0 {
|
||||
visitor.append_type::<Never>()
|
||||
} else {
|
||||
T::visit_variants_static(visitor).for_each(drop)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_map<K, V>(visitor: &mut TSVisitor)
|
||||
where
|
||||
K: TS,
|
||||
|
||||
Reference in New Issue
Block a user