Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: refactor TypeDependencies trait into ExportType trait #13

Merged
merged 1 commit into from
May 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/refactor-type-dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"qubit-macros": minor:refactor
"qubit": minor:refactor
---

refactor `TypeDependencies` trait into `ExportType` trait
6 changes: 3 additions & 3 deletions crates/qubit-macros/src/handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,12 +282,12 @@ impl From<Handler> for TokenStream {
#register_impl
}

fn add_dependencies(dependencies: &mut std::collections::BTreeMap<std::string::String, std::string::String>) {
fn export_types(registry: &mut std::collections::BTreeMap<std::string::String, std::string::String>) {
// Add dependencies for the parameters
#(<#param_tys as qubit::TypeDependencies>::get_deps(dependencies);)*
#(<#param_tys as qubit::ExportType>::export(registry);)*

// Add dependencies for the return type
<#return_type as qubit::TypeDependencies>::get_deps(dependencies);
<#return_type as qubit::ExportType>::export(registry);
}
}
}.into()
Expand Down
8 changes: 4 additions & 4 deletions crates/qubit-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ pub fn handler(
macros::handler(attr, input)
}

/// Derive [`qubit::TypeDependencies`] implementation for the attached struct. Will check to see if
/// Derive [`qubit::ExportType`] implementation for the attached struct. Will check to see if
/// the struct has been added before, and if not it will add it's own inline definition, and
/// recurse to add the types of any nested types.
#[proc_macro_derive(TypeDependencies)]
pub fn derive_type_dependencies(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
macros::derive_type_dependencies(input)
#[proc_macro_derive(ExportType)]
pub fn derive_export_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
macros::derive_export_type(input)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use quote::quote;
use syn::Item;

pub fn derive_type_dependencies(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
pub fn derive_export_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let s = syn::parse::<Item>(input).unwrap();

let (target_struct, fields) = match s {
Expand All @@ -13,18 +13,18 @@ pub fn derive_type_dependencies(input: proc_macro::TokenStream) -> proc_macro::T
};

quote! {
impl qubit::TypeDependencies for #target_struct {
fn get_deps(dependencies: &mut std::collections::BTreeMap<std::string::String, std::string::String>) {
impl qubit::ExportType for #target_struct {
fn export(registry: &mut std::collections::BTreeMap<std::string::String, std::string::String>) {
// Short circuit if this type has already been added
if dependencies.contains_key(&<Self as ts_rs::TS>::name()) {
if registry.contains_key(&<Self as ts_rs::TS>::name()) {
return;
}

// Insert this type
dependencies.insert(<Self as ts_rs::TS>::name(), <Self as ts_rs::TS>::inline());
registry.insert(<Self as ts_rs::TS>::name(), <Self as ts_rs::TS>::inline());

// Insert field types
#(<#fields as qubit::TypeDependencies>::get_deps(dependencies);)*
#(<#fields as qubit::ExportType>::export(registry);)*
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/qubit-macros/src/macros/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod derive_type_dependencies;
mod derive_export_type;
mod handler;

pub use derive_type_dependencies::derive_type_dependencies;
pub use derive_export_type::derive_export_type;
pub use handler::handler;
6 changes: 3 additions & 3 deletions examples/counter/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use qubit::*;
use axum::routing::get;
use serde::{Deserialize, Serialize};

#[derive(ts_rs::TS, Clone, Serialize, Deserialize, Debug, TypeDependencies)]
#[derive(ts_rs::TS, Clone, Serialize, Deserialize, Debug, ExportType)]
pub struct Metadata {
param_a: String,
param_b: u32,
Expand All @@ -22,7 +22,7 @@ pub struct Metadata {
more_metadata: Option<Box<Metadata>>,
}

#[derive(ts_rs::TS, Clone, Serialize, Deserialize, Debug, TypeDependencies)]
#[derive(ts_rs::TS, Clone, Serialize, Deserialize, Debug, ExportType)]
pub struct User {
name: String,
email: String,
Expand All @@ -31,7 +31,7 @@ pub struct User {
metadata: Metadata,
}

#[derive(ts_rs::TS, Clone, Serialize, Deserialize, Debug, TypeDependencies)]
#[derive(ts_rs::TS, Clone, Serialize, Deserialize, Debug, ExportType)]
pub struct Test {
a: usize,
b: bool,
Expand Down
8 changes: 4 additions & 4 deletions src/builder/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ pub trait Handler<AppCtx> {
/// Get the type of this handler, to generate the client.
fn get_type() -> HandlerType;

/// Get any dependencies required to use this [`HandlerType`] in the client.
fn add_dependencies(dependencies: &mut BTreeMap<String, String>);
/// Export any types required to use this [`HandlerType`] in the client.
fn export_types(registry: &mut BTreeMap<String, String>);
}

/// Wrapper struct to assist with erasure of concrete [`Handler`] type. Contains function pointers
Expand All @@ -51,7 +51,7 @@ pub(crate) struct HandlerCallbacks<Ctx> {

/// Function pointer to the implementation that will add any type dependencies for the handler
/// to the provided collection.
pub add_dependencies: fn(&mut BTreeMap<String, String>),
pub export_types: fn(&mut BTreeMap<String, String>),
}

impl<Ctx> HandlerCallbacks<Ctx>
Expand All @@ -65,7 +65,7 @@ where
Self {
register: H::register,
get_type: H::get_type,
add_dependencies: H::add_dependencies,
export_types: H::export_types,
}
}
}
82 changes: 0 additions & 82 deletions src/builder/ty/dependencies.rs

This file was deleted.

83 changes: 83 additions & 0 deletions src/builder/ty/export_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use std::collections::{BTreeMap, HashMap};

use ts_rs::TS;

/// Since macros cannot lookup other items in the source code, any user types must 'register'
/// themselves into a central repository so that their types can be collated, ensuring that they're
/// only inserted into the generated types once.
pub trait ExportType: TS {
#[allow(unused_variables)]
fn export(registry: &mut BTreeMap<String, String>) {}
}

macro_rules! impl_export_type {
($($t:ident<$($generic:ident),*>),*) => {
$(impl<$($generic),*> ExportType for $t<$($generic),*>
where $($generic: ts_rs::TS + crate::ExportType),*
{
fn export(register: &mut BTreeMap<String, String>) {
$(impl_export_type!(generic: $generic, register);)*
}
})*
};

($($t:ty),*) => {
$(impl ExportType for $t {})*
};

(tuple: $t:ident) => {
impl<$t> ExportType for ($t,)
where $t: ts_rs::TS + crate::ExportType,
{
fn export(register: &mut BTreeMap<String, String>) {
impl_export_type!(generic: $t, register);
}
}
};

(tuple: $t:ident $(, $t_other:ident)*) => {
impl<$t, $($t_other),*> ExportType for ($t, $($t_other),*)
where $t: ts_rs::TS + crate::ExportType,
$($t_other: ts_rs::TS + crate::ExportType),*
{
fn export(register: &mut BTreeMap<String, String>) {
impl_export_type!(generic: $t, register);
$(impl_export_type!(generic: $t_other, register);)*
}
}

impl_export_type!(tuple: $($t_other),*);
};

(generic: $generic:ident, $register:ident) => {
<$generic as ExportType>::export($register)
};
}

impl_export_type!(
u8,
u16,
u32,
u64,
u128,
usize,
i8,
i16,
i32,
i64,
i128,
isize,
String,
&'static str,
bool,
char,
()
);
impl_export_type!(
Vec<T>,
Box<T>,
Option<T>,
Result<T, E>,
HashMap<K, V>
);
impl_export_type!(tuple: T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
4 changes: 2 additions & 2 deletions src/builder/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Type generation specific functionality. There is no real need for this to be directly used,
//! [`qubit_macros::handler`] should handle it all.

mod dependencies;
mod export_type;

pub use dependencies::*;
pub use export_type::*;

/// Components used to construct the client type for this handler.
#[derive(Debug)]
Expand Down
2 changes: 1 addition & 1 deletion src/server/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ where
// Add all handler dependencies
self.handlers
.iter()
.for_each(|handler| (handler.add_dependencies)(dependencies));
.for_each(|handler| (handler.export_types)(dependencies));

// Add dependencies for nested routers
self.nested_routers
Expand Down
Loading