✨🧪♻️➕ vanth, vanth_derive: Add derive macro for Vanth
trait implementation
- Added `vanth_derive` crate with a procedural macro to automatically implement the `Vanth` trait for structs, including generics. - Refactored `vanth` crate by removing obsolete `vanth.rs` file. - Implemented `PartialEq` for `Ty` to enable comparisons with string values and another `Ty`. - Added integration tests for deriving `Vanth` with generic parameters. - Updated dependencies: added `quote`, `syn`, and `proc-macro2` crates.
This commit is contained in:
parent
94105daca1
commit
b36f178999
9 changed files with 119 additions and 23 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -1009,6 +1009,7 @@ dependencies = [
|
|||
"digest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"vanth_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1019,6 +1020,15 @@ dependencies = [
|
|||
"vanth",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vanth_derive"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "variadics_please"
|
||||
version = "1.1.0"
|
||||
|
|
|
@ -15,3 +15,6 @@ serde = { version = "1.0.219", features = ["derive"] }
|
|||
serde_json = "1.0.140"
|
||||
digest = "0.10.7"
|
||||
blake3 = { version = "1.8.2", features = ["traits-preview"] }
|
||||
quote = "1.0"
|
||||
syn = { version = "2.0", features = ["full"] }
|
||||
proc-macro2 = "1.0"
|
|
@ -13,3 +13,4 @@ digest.workspace = true
|
|||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
blake3.workspace = true
|
||||
vanth_derive = { path = "../vanth_derive" }
|
||||
|
|
|
@ -12,6 +12,7 @@ pub mod entity;
|
|||
pub mod hashing_serializer;
|
||||
|
||||
pub use hashing_serializer::hash;
|
||||
pub use vanth_derive::Vanth;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
|
@ -77,10 +78,22 @@ pub struct Value {
|
|||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Ty {
|
||||
path: Vec<String>,
|
||||
pub path: Vec<String>,
|
||||
}
|
||||
|
||||
pub trait Vanth: Serialize + DeserializeOwned {
|
||||
impl PartialEq for Ty {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.path == other.path
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: AsRef<str>> PartialEq<T> for Ty {
|
||||
fn eq(&self, other: &T) -> bool {
|
||||
self.path.join("::") == *other.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Vanth {
|
||||
fn ty() -> Ty;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
#![allow(unused)]
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct Value {}
|
||||
|
||||
pub struct Ty {}
|
||||
|
||||
pub enum Primitive {
|
||||
Bool(bool),
|
||||
Int(i32),
|
||||
Float(f32),
|
||||
String(String),
|
||||
Path(PathBuf),
|
||||
Char(char),
|
||||
Byte(u8),
|
||||
ByteArray(Vec<u8>),
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
use bevy_ecs::component::Component;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use vanth::Vanth;
|
||||
|
||||
// TODO: derive `Vanth`
|
||||
|
@ -10,5 +10,29 @@ struct Foo {
|
|||
|
||||
#[test]
|
||||
fn test_derive() {
|
||||
println!("yeet");
|
||||
#[derive(Deserialize, Serialize, Vanth)]
|
||||
struct Foo<T: Vanth> {
|
||||
field_a: i32,
|
||||
field_b: String,
|
||||
inner: T,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Vanth)]
|
||||
struct Bar {
|
||||
field_a: i32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Vanth)]
|
||||
struct Qux<T: Vanth, S: Vanth> {
|
||||
field_a: i32,
|
||||
field_b: String,
|
||||
inner: T,
|
||||
inner_2: S,
|
||||
}
|
||||
|
||||
let base = "integration::derive::";
|
||||
|
||||
assert_eq!(Bar::ty(), format!("{base}Bar"));
|
||||
assert_eq!(Foo::<Bar>::ty(), format!("{base}Foo<{base}Bar>"));
|
||||
assert_eq!(Qux::<Bar, Foo<Bar>>::ty(), format!("{base}Qux<{base}Bar,{base}Foo<{base}Bar>>"));
|
||||
}
|
||||
|
|
12
crates/vanth_derive/Cargo.toml
Normal file
12
crates/vanth_derive/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "vanth_derive"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote.workspace = true
|
||||
syn.workspace = true
|
||||
proc-macro2.workspace = true
|
51
crates/vanth_derive/src/lib.rs
Normal file
51
crates/vanth_derive/src/lib.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, DeriveInput, GenericParam, Generics};
|
||||
use syn::parse_quote;
|
||||
|
||||
#[proc_macro_derive(Vanth)]
|
||||
pub fn vanth_derive(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let name = input.ident.clone();
|
||||
|
||||
let mut generics = input.generics.clone();
|
||||
|
||||
let type_params: Vec<syn::Ident> = generics.params.iter().filter_map(|param| {
|
||||
if let GenericParam::Type(type_param) = param {
|
||||
Some(type_param.ident.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect();
|
||||
|
||||
let mut where_clause = generics.where_clause.clone().unwrap_or_else(|| parse_quote!(where ));
|
||||
for tp in &type_params {
|
||||
where_clause.predicates.push(parse_quote!(#tp : vanth::Vanth));
|
||||
}
|
||||
|
||||
let (impl_generics, ty_generics, _) = generics.split_for_impl();
|
||||
|
||||
let generics_code = if type_params.is_empty() {
|
||||
quote! { String::new() }
|
||||
} else {
|
||||
quote! {
|
||||
format!("<{}>", [#(#type_params::ty().path.join("::")),*].join(","))
|
||||
}
|
||||
};
|
||||
|
||||
let expanded = quote! {
|
||||
impl #impl_generics vanth::Vanth for #name #ty_generics #where_clause {
|
||||
fn ty() -> vanth::Ty {
|
||||
let module_path = module_path!();
|
||||
let mut path: Vec<String> = module_path.split("::").map(|s| s.to_string()).collect();
|
||||
let base_name = stringify!(#name);
|
||||
let generics_str = #generics_code;
|
||||
path.push(format!("{}{}", base_name, generics_str));
|
||||
vanth::Ty { path }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue