#hash #macro-derive #hashed #proc-macro #type #derive #id

hashed-type-def-core

基于哈希的简单类型标识符:基于类型定义计算哈希码

4 个版本

0.1.2 2024 年 3 月 4 日
0.1.1 2024 年 2 月 26 日
0.1.0 2024 年 2 月 20 日
0.0.0 2023 年 11 月 13 日

#1836 in 开发工具

29 每月下载量
4 个crate中使用(通过 hashed-type-def

Apache-2.0

88KB
1K SLoC

这是 Silx 项目的一部分

hashed-type-def-core 包含派生类型哈希码的核心定义和实现

  • 哈希码以 u128 常量和 Uuid 常量的形式生成
  • 由派生宏生成的哈希码由类型定义的形态构成,不依赖于 Rust 版本

然而,由于该crate使用过程宏,结果可能依赖于解析器(syn)生成的序列,因此依赖于该解析器的演变

备注

关于版本 0.1.2

  • HashedTypeUuid 已弃用,并由 HashedTypeMethods 取代
  • HashedTypeDef 中添加了字段 const UUID: uuid::Uuid
  • 依赖项已更新

内容

该crate提供两个特质 HashedTypeDefHashedTypeMethods

  • HashedTypeDef 特质是定义类型哈希码的基础
    • 它提供 u128Uuid 格式的哈希码的常量值
  • HashedTypeMethods 特质提供访问哈希码的附加方法

实现 HashedTypeDef 的常规方法是使用过程宏 #[derive(HashedTypeDef)]

以下示例概述了hashed-type-def的功能。

类型哈希码实现示例

Cargo.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

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);
}

典型输出

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

依赖项

~0.7–1.9MB
~38K SLoC