proc-macro for TypeUuidProvider

- allows to add `#[type_uuid(id = "15a8ecd6-a09f-4c5d-b9f9-b7f0e8a44ac9")]` attribute to types that `#[derive(TypeUuidProvider)]`
This commit is contained in:
Dmitry Stepanov
2024-01-09 12:31:22 +03:00
parent 99619dd9bc
commit 85d264c3e2
6 changed files with 123 additions and 63 deletions
+10
View File
@@ -1,4 +1,5 @@
mod reflect;
mod uuid;
mod visit;
use darling::FromDeriveInput;
@@ -43,3 +44,12 @@ pub fn impl_reflect(input: TokenStream) -> TokenStream {
TokenStream::from(reflect_impl)
}
/// Implements `TypeUuidProvider` trait
///
/// User has to import `TypeUuidProvider` trait to use this macro.
#[proc_macro_derive(TypeUuidProvider, attributes(type_uuid))]
pub fn type_uuid(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
TokenStream::from(uuid::impl_type_uuid_provider(ast))
}
+28
View File
@@ -0,0 +1,28 @@
use darling::*;
use proc_macro2::TokenStream as TokenStream2;
use quote::*;
use syn::*;
#[derive(FromDeriveInput)]
#[darling(attributes(type_uuid), supports(struct_any, enum_any))]
pub struct TypeArgs {
pub ident: Ident,
pub generics: Generics,
pub id: String,
}
pub fn impl_type_uuid_provider(ast: DeriveInput) -> TokenStream2 {
let ty_args = TypeArgs::from_derive_input(&ast).unwrap();
let ty_ident = &ty_args.ident;
let id = &ty_args.id;
let (impl_generics, ty_generics, where_clause) = ty_args.generics.split_for_impl();
quote! {
impl #impl_generics TypeUuidProvider for #ty_ident #ty_generics #where_clause {
fn type_uuid() -> Uuid {
uuid!(#id)
}
}
}
}
+1
View File
@@ -6,4 +6,5 @@
// trace_macros!(true);
pub mod reflect;
pub mod uuid;
pub mod visit;
+12
View File
@@ -0,0 +1,12 @@
use fyrox_core::type_traits::prelude::*;
use std::marker::PhantomData;
#[derive(TypeUuidProvider)]
#[type_uuid(id = "5fb10a22-4ea9-4a13-a58c-82f2734aefd8")]
struct Foo {}
#[derive(TypeUuidProvider)]
#[type_uuid(id = "5fb10a22-4ea9-4a13-a58c-82f2734aefd9")]
struct Bar<T> {
phantom: PhantomData<T>,
}
+3 -63
View File
@@ -45,6 +45,7 @@ pub mod reflect;
pub mod sparse;
pub mod sstorage;
pub mod task;
pub mod type_traits;
pub mod variable;
pub mod visitor;
pub mod watcher;
@@ -58,7 +59,6 @@ pub use notify;
pub use js_sys;
use std::iter::FromIterator;
use std::marker::PhantomData;
use uuid::Uuid;
#[cfg(target_arch = "wasm32")]
pub use wasm_bindgen;
#[cfg(target_arch = "wasm32")]
@@ -66,6 +66,8 @@ pub use wasm_bindgen_futures;
#[cfg(target_arch = "wasm32")]
pub use web_sys;
pub use type_traits::prelude::*;
/// Defines as_(variant), as_mut_(variant) and is_(variant) methods.
#[macro_export]
macro_rules! define_is_as {
@@ -298,68 +300,6 @@ pub fn make_relative_path<P: AsRef<Path>>(path: P) -> Result<PathBuf, std::io::E
}
}
/// A trait for an entity that has unique type identifier.
pub trait TypeUuidProvider: Sized {
/// Return type UUID.
fn type_uuid() -> Uuid;
}
#[macro_export]
macro_rules! uuid_provider {
($type:ident $(<$($generics:tt),*>)? = $uuid:expr) => {
impl$(<$($generics),*>)? $crate::TypeUuidProvider for $type $(<$($generics),*>)? {
fn type_uuid() -> $crate::uuid::Uuid {
$crate::uuid::uuid!($uuid)
}
}
};
}
#[macro_export]
macro_rules! stub_uuid_provider {
($type:ty) => {
impl $crate::TypeUuidProvider for $type {
fn type_uuid() -> $crate::uuid::Uuid {
unimplemented!()
}
}
};
}
uuid_provider!(u8 = "7a8c337c-0219-466b-92b5-81460fa9c836");
uuid_provider!(i8 = "3036f00e-5986-4ac3-8763-19e51d0889d7");
uuid_provider!(u16 = "c662169d-cc3b-453c-bdf3-e0104ac3b966");
uuid_provider!(i16 = "abce35a9-5e7b-4f7e-a729-2620a9806a6b");
uuid_provider!(u32 = "8c4d2541-76a5-4dd8-9eb1-10222d2d6912");
uuid_provider!(i32 = "7413ddd4-71ce-484d-a808-4f3479f5712d");
uuid_provider!(u64 = "d1a45bd5-5066-4b28-b103-95c59c230e77");
uuid_provider!(i64 = "35b89368-805f-486d-b3b1-fd3e86b5d645");
uuid_provider!(f32 = "479e29c6-85fd-4bb8-b311-7b98793b8bf6");
uuid_provider!(f64 = "dac09d54-d069-47f4-aa0e-aa0057cc2b52");
uuid_provider!(usize = "620e24e3-fb51-48c6-a885-91d65135c5c9");
uuid_provider!(isize = "0a06591a-1c66-4299-ba6f-2b205b795575");
uuid_provider!(bool = "3b104074-9d39-4a2b-b974-da8cc1759fe8");
impl<T: TypeUuidProvider> TypeUuidProvider for Option<T> {
fn type_uuid() -> Uuid {
combine_uuids(
uuid::uuid!("ffe06d3b-0d07-42cd-886b-5248f6ca7f7d"),
T::type_uuid(),
)
}
}
#[inline]
pub fn combine_uuids(a: Uuid, b: Uuid) -> Uuid {
let mut combined_bytes = a.into_bytes();
for (src, dest) in b.into_bytes().into_iter().zip(combined_bytes.iter_mut()) {
*dest ^= src;
}
Uuid::from_bytes(combined_bytes)
}
/// "Transmutes" array of any sized type to a slice of bytes.
pub fn array_as_u8_slice<T: Sized>(v: &[T]) -> &'_ [u8] {
// SAFETY: It is safe to reinterpret data to read it.
+69
View File
@@ -0,0 +1,69 @@
pub use fyrox_core_derive::TypeUuidProvider;
use uuid::Uuid;
pub mod prelude {
pub use super::{combine_uuids, TypeUuidProvider};
pub use uuid::{uuid, Uuid};
}
/// A trait for an entity that has unique type identifier.
pub trait TypeUuidProvider: Sized {
/// Return type UUID.
fn type_uuid() -> Uuid;
}
#[macro_export]
macro_rules! uuid_provider {
($type:ident $(<$($generics:tt),*>)? = $uuid:expr) => {
impl$(<$($generics),*>)? $crate::type_traits::TypeUuidProvider for $type $(<$($generics),*>)? {
fn type_uuid() -> $crate::uuid::Uuid {
$crate::uuid::uuid!($uuid)
}
}
};
}
#[macro_export]
macro_rules! stub_uuid_provider {
($type:ty) => {
impl $crate::TypeUuidProvider for $type {
fn type_uuid() -> $crate::uuid::Uuid {
unimplemented!()
}
}
};
}
uuid_provider!(u8 = "7a8c337c-0219-466b-92b5-81460fa9c836");
uuid_provider!(i8 = "3036f00e-5986-4ac3-8763-19e51d0889d7");
uuid_provider!(u16 = "c662169d-cc3b-453c-bdf3-e0104ac3b966");
uuid_provider!(i16 = "abce35a9-5e7b-4f7e-a729-2620a9806a6b");
uuid_provider!(u32 = "8c4d2541-76a5-4dd8-9eb1-10222d2d6912");
uuid_provider!(i32 = "7413ddd4-71ce-484d-a808-4f3479f5712d");
uuid_provider!(u64 = "d1a45bd5-5066-4b28-b103-95c59c230e77");
uuid_provider!(i64 = "35b89368-805f-486d-b3b1-fd3e86b5d645");
uuid_provider!(f32 = "479e29c6-85fd-4bb8-b311-7b98793b8bf6");
uuid_provider!(f64 = "dac09d54-d069-47f4-aa0e-aa0057cc2b52");
uuid_provider!(usize = "620e24e3-fb51-48c6-a885-91d65135c5c9");
uuid_provider!(isize = "0a06591a-1c66-4299-ba6f-2b205b795575");
uuid_provider!(bool = "3b104074-9d39-4a2b-b974-da8cc1759fe8");
impl<T: TypeUuidProvider> TypeUuidProvider for Option<T> {
fn type_uuid() -> Uuid {
combine_uuids(
uuid::uuid!("ffe06d3b-0d07-42cd-886b-5248f6ca7f7d"),
T::type_uuid(),
)
}
}
#[inline]
pub fn combine_uuids(a: Uuid, b: Uuid) -> Uuid {
let mut combined_bytes = a.into_bytes();
for (src, dest) in b.into_bytes().into_iter().zip(combined_bytes.iter_mut()) {
*dest ^= src;
}
Uuid::from_bytes(combined_bytes)
}