This is part of [**Silx**](https://crates.io/crates/silx) project `hashed-type-def-procmacro` contains the implementation of procedural macros for deriving type hashcode * The hashcode is generated as `u128` constant and as `Uuid` constant * The hashcode generated by the derive macro is built from the morphology of the type definition and does not depend on the rust version As the crate uses a procedural macro, however, the result could depend on the sequences generated by the parser (`syn`) and therefore on the evolution of this parser ## Notes: About version 0.1.2: * Dependencies are updated # Content Definition of procedural macros: * `#[derive(HashedTypeDef)]` : procedural macro for deriving `HashedTypeDef` * `add_hashed_type_def` : procedural macro for adding implementation of `HashedTypeDef` to existing type * `add_hashed_type_def_param` : procedural macro for adding implementation of `HashedTypeDef` to existing type * `build_hasher` : procedural macro for defining common hasher functions The regular way to implement `HashedTypeDef` is by using the procedural macro `#[derive(HashedTypeDef)]` The following example gives an overview of `hashed-type-def` features. # Example of type hashcode implementation ## Cargo.toml ```toml [package] name = "silx_hashed-type-def_examples" version = "0.1.2" edition = "2021" [dependencies] uuid = "1.7.0" hashed-type-def = { version = "0.1.2", features = ["derive"] } ``` ## main.rs ```rust use std::fmt::Debug; use hashed_type_def::{ HashedTypeDef, add_hashed_type_def_param, }; /// case 1: a named structure to be tested with procedural derivation /// * procedural macro `#[derive(HashedTypeDef)]` is the regular way to implement `HashedTypeDef` #[derive(Debug,HashedTypeDef)] struct MyStruct<'a,'b,T,U: Debug,const C1: usize, const C2: bool> where T: Into + 'b, 'a: 'b { #[allow(dead_code)] un: &'a String, #[allow(dead_code)] deux: T, #[allow(dead_code)] trois: &'b U, } pub mod instance0 { use hashed_type_def::HashedTypeDef; use std::fmt::Debug; /// case 2: a structure with same definition and procedural derivation as case 1 /// * type hash should be the same than case 1 #[derive(Debug,HashedTypeDef)] pub struct MyStruct<'a,'b,T,U: Debug,const C1: usize, const C2: bool> where T: Into + 'b, 'a: 'b { #[allow(dead_code)] un: &'a String, #[allow(dead_code)] deux: T, #[allow(dead_code)] trois: &'b U, } } pub mod instance1 { use hashed_type_def::{ add_hashed_type_def, HashedTypeDef, }; use std::fmt::Debug; /// case 3: a structure with same definition as case 1 and post derivation obtained by macro `add_hashed_type_def!` processing on the same definition /// * type hash should be the same than case 1 pub struct MyStruct<'a,'b,T,U: Debug,const C1: usize, const C2: bool> where T: Into + 'b, 'a: 'b { #[allow(dead_code)] un: &'a String, #[allow(dead_code)] deux: T, #[allow(dead_code)] trois: &'b U, } add_hashed_type_def!{ pub struct MyStruct<'a,'b,T,U: Debug,const C1: usize, const C2: bool> where T: Into + 'b, 'a: 'b { un: &'a String, deux: T, trois: &'b U, } } } pub mod instance2 { use hashed_type_def::HashedTypeDef; use std::fmt::Debug; /// case 4: a structure with procedural derivation and same definition as case 1 except a swap on lifetime names /// * type hash should be different than case 1 #[derive(Debug,HashedTypeDef)] pub struct MyStruct<'b,'a,T,U: Debug,const C1: usize, const C2: bool> where T: Into + 'a, 'b: 'a { #[allow(dead_code)] un: &'b String, #[allow(dead_code)] deux: T, #[allow(dead_code)] trois: &'a U, } } pub mod instance3 { use hashed_type_def::{ add_hashed_type_def, HashedTypeDef, }; use std::fmt::Debug; /// case 5: a structure with same definition as case 1 and post derivation obtained by macro `add_hashed_type_def!` processing on altered definition /// * type hash should be different than case 1 pub struct MyStruct<'a,'b,T,U: Debug,const C1: usize, const C2: bool> where T: Into + 'b, 'a: 'b { #[allow(dead_code)] un: &'a String, #[allow(dead_code)] deux: T, #[allow(dead_code)] trois: &'b U, } add_hashed_type_def!{ pub struct MyStruct<'a,'b,T,U: Debug,const C1: usize, const C2: bool> where T: Into + 'b, 'a: 'b { instance3_MyStruct: (), un: &'a String, deux: T, trois: &'b U, } } } pub mod instance4 { use hashed_type_def::HashedTypeDef; use std::fmt::Debug; /// case 6: a structure with procedural derivation and same definition as case 1 except conditions are moved to where clauses /// * type hash should be different than case 1 #[derive(Debug,HashedTypeDef)] pub struct MyStruct<'a,'b,T,U,const C1: usize, const C2: bool> where 'a: 'b, T: Into + 'b, U: Debug, { #[allow(dead_code)] un: &'a String, #[allow(dead_code)] deux: T, #[allow(dead_code)] trois: &'b U, } } pub mod instance5 { use hashed_type_def::HashedTypeDef; use std::fmt::Debug; /// case 7: a structure with procedural derivation and same definition as case 1 except conditions are moved from where clauses /// * type hash should be different than case 1 #[derive(Debug,HashedTypeDef)] pub struct MyStruct<'a: 'b,'b, T: Into + 'b, U: Debug, const C1: usize, const C2: bool> { #[allow(dead_code)] un: &'a String, #[allow(dead_code)] deux: T, #[allow(dead_code)] trois: &'b U, } } pub mod instance6 { use hashed_type_def::HashedTypeDef; use std::fmt::Debug; /// case 8: a structure with procedural derivation and same definition as case 1 except a conditions is removed from parameters list /// * type hash should be different than case 1 #[derive(Debug,HashedTypeDef)] pub struct MyStruct<'a,'b,T,U,const C1: usize, const C2: bool> where T: Into + 'b, 'a: 'b { #[allow(dead_code)] un: &'a String, #[allow(dead_code)] deux: T, #[allow(dead_code)] trois: &'b U, } } pub mod instance7 { use hashed_type_def::HashedTypeDef; use std::fmt::Debug; /// case 9: a structure with procedural derivation and same definition as case 1 except a condition is removed from where clauses /// * type hash should be different than case 1 #[derive(Debug,HashedTypeDef)] pub struct MyStruct<'a,'b,T,U: Debug,const C1: usize, const C2: bool> where T: Into + 'b, { #[allow(dead_code)] un: &'a String, #[allow(dead_code)] deux: T, #[allow(dead_code)] trois: &'b U, } } /// build type hash (Uuid format) of case 1 for specific lifetime /// * type hash should not change fn fn_type_hash<'a: 'b,'b>(_tmp1: &'a (), _tmp2: &'b ()) -> uuid::Uuid { MyStruct::<'a,'b,f32,f64,12,true>::UUID } /// case 10: a unnamed structure to be tested with procedural derivation #[derive(Debug,HashedTypeDef)] struct MyTupleStruct(String,T,U,) where T: Into; /// case 11: a unit structure to be tested with procedural derivation #[derive(Debug,HashedTypeDef)] struct MyEmptyStruct; /// case 12: enum to be tested with procedural derivation #[derive(Debug,HashedTypeDef)] enum MyEnum where T: Into { #[allow(dead_code)] Zero, #[allow(dead_code)] Un(String, T,), #[allow(dead_code)] Deux { double: f64, trois: U, }, #[allow(dead_code)] Trois, } /// case 13: empty enum to be tested with procedural derivation #[derive(Debug,HashedTypeDef)] enum MyEmptyEnum { } /// case 14: a struct to be tested with post derivation with parameter tag `(Option,[u128;24])` struct AnotherStruct where T: Default { #[allow(dead_code)] t: T } add_hashed_type_def_param!((Option,[u128;24]); struct AnotherStruct where T: Default { t: T }); /// Different cases of type hash derivation fn main() { // case 1 with `true` parameter println!("MyStruct::<'static,'static,f32,f64,12,true>::UUID -> {:x}", MyStruct::<'static,'static,f32,f64,12,true>::UUID); // case 1 with `true` parameter and different lifetime println!("MyStruct::<'a,'b,f32,f64,12,true>::UUID -> {:x}", { let a = (); { let b = (); fn_type_hash(&a,&b) } }); // case 1 with `false` parameter println!("MyStruct::<'static,'static,f32,f64,12,false>::UUID -> {:x}", MyStruct::<'static,'static,f32,f64,12,false>::UUID); // case 2 with `false` parameter println!("instance0::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> {:x}", instance0::MyStruct::<'static,'static,f32,f64,12,false>::UUID); // case 3 with `false` parameter println!("instance1::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> {:x}", instance1::MyStruct::<'static,'static,f32,f64,12,false>::UUID); // case 4 with `false` parameter println!("instance2::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> {:x}", instance2::MyStruct::<'static,'static,f32,f64,12,false>::UUID); // case 5 with `false` parameter println!("instance3::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> {:x}", instance3::MyStruct::<'static,'static,f32,f64,12,false>::UUID); // case 6 with `false` parameter println!("instance4::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> {:x}", instance4::MyStruct::<'static,'static,f32,f64,12,false>::UUID); // case 7 with `false` parameter println!("instance5::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> {:x}", instance5::MyStruct::<'static,'static,f32,f64,12,false>::UUID); // case 8 with `false` parameter println!("instance6::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> {:x}", instance6::MyStruct::<'static,'static,f32,f64,12,false>::UUID); // case 9 with `false` parameter println!("instance7::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> {:x}", instance7::MyStruct::<'static,'static,f32,f64,12,false>::UUID); // case 10 println!("MyTupleStruct::::UUID -> {:x}", MyTupleStruct::::UUID); // case 11 println!("MyEmptyStruct::UUID -> {:x}", MyEmptyStruct::UUID); // case 12 println!("MyEnum::::UUID -> {:x}", MyEnum::::UUID); // case 13 println!("MyEmptyEnum::UUID -> {:x}", MyEmptyEnum::UUID); // case 14 println!("AnotherStruct::>::UUID -> {:x}", AnotherStruct::>::UUID); } ``` ## Typical output ``` MyStruct::<'static,'static,f32,f64,12,true>::UUID -> bd84ac66-d0fa-5d1c-ae5e-25647a13dcb3 MyStruct::<'a,'b,f32,f64,12,true>::UUID -> bd84ac66-d0fa-5d1c-ae5e-25647a13dcb3 MyStruct::<'static,'static,f32,f64,12,false>::UUID -> 1a8a7365-1c9c-afed-cca3-983399a91fd8 instance0::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> 1a8a7365-1c9c-afed-cca3-983399a91fd8 instance1::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> 1a8a7365-1c9c-afed-cca3-983399a91fd8 instance2::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> bbe982ff-fcad-5390-86f0-cce2e7dbae6b instance3::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> 56d4f1b7-af31-d361-3afb-dc89e52c2ded instance4::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> 394096e5-5187-edf4-ac77-3f6edc052b72 instance5::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> e7e26201-4095-31d1-bfa3-fd4b62abc938 instance6::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> 0bee6197-ef3e-a446-890a-c34705c30cdd instance7::MyStruct::<'static,'static,f32,f64,12,false>::UUID -> f8f3fcc7-e4a5-e021-e200-763b4cf9df7a MyTupleStruct::::UUID -> ddd04a26-6807-0f27-67b2-227db8f17b75 MyEmptyStruct::UUID -> 4ede75e3-1bf7-5298-ae87-0ee1d57a1357 MyEnum::::UUID -> fcad4ca3-6cd0-6c7e-21ea-658a12369d9f MyEmptyEnum::UUID -> 9dec7519-c5f4-12b9-0509-b5b2ef1d521c AnotherStruct::>::UUID -> 933ae311-b69a-f600-7caa-030743cbb5e5 ```