1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
//! This is part of [**Silx**](https://crates.io/crates/silx) project  
//!   
//! `hashed-type-def` contains components and macros for deriving, at compile time, type hashcode to identify a type:
//! * 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
//! 
//! # Content
//! The crate provides two traits `HashedTypeDef` and `HashedTypeMethods`
//! * the `HashedTypeDef` trait is the basis for defining a type's hashcode
//!   * It provides constant value of the hashcode under `u128` and `Uuid` formats
//! * the `HashedTypeMethods` trait provides additional methods for accessing the hashcode  
//! 
//! 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
//! ```text
//! 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<U> + '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<U> + '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<U> + '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<U> + '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<U> + '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<U> + '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<U> + '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<U> + '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<U> + '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<U> + '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<U> + '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<T,U: Debug>(String,T,U,) where T: Into<U>;
//! 
//! /// 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<T,U: Debug> where T: Into<U> {
//!     #[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<u32>,[u128;24])`
//! struct AnotherStruct<T: Debug> where T: Default { #[allow(dead_code)] t: T }
//! 
//! add_hashed_type_def_param!((Option<u32>,[u128;24]); struct AnotherStruct<T: Debug> 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::<f32,f64>::UUID -> {:x}", MyTupleStruct::<f32,f64>::UUID);
//!     // case 11
//!     println!("MyEmptyStruct::UUID -> {:x}", MyEmptyStruct::UUID);
//!     // case 12
//!     println!("MyEnum::<f32,f64,>::UUID -> {:x}", MyEnum::<f32,f64,>::UUID);
//!     // case 13
//!     println!("MyEmptyEnum::UUID -> {:x}", MyEmptyEnum::UUID);
//!     // case 14
//!     println!("AnotherStruct::<Vec<u16>>::UUID -> {:x}", AnotherStruct::<Vec<u16>>::UUID);
//! }
//! ```
//! ## Typical output
//! ```txt
//! 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::<f32,f64>::UUID -> ddd04a26-6807-0f27-67b2-227db8f17b75
//! MyEmptyStruct::UUID -> 4ede75e3-1bf7-5298-ae87-0ee1d57a1357
//! MyEnum::<f32,f64,>::UUID -> fcad4ca3-6cd0-6c7e-21ea-658a12369d9f
//! MyEmptyEnum::UUID -> 9dec7519-c5f4-12b9-0509-b5b2ef1d521c
//! AnotherStruct::<Vec<u16>>::UUID -> 933ae311-b69a-f600-7caa-030743cbb5e5
//! ```


pub use hashed_type_def_core::{ HashedTypeDef, HashedTypeMethods, add_hash_fnv1a, start_hash_fnv1a, };
#[allow(deprecated)]
pub use hashed_type_def_core::HashedTypeUuid;
#[cfg(feature = "derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate hashed_type_def_procmacro;

#[cfg(feature = "derive")]
#[doc(hidden)]
pub use hashed_type_def_procmacro::{ HashedTypeDef, add_hashed_type_def, add_hashed_type_def_param, };

#[doc(hidden)]
/// Probes for testing features activation
pub mod probes;