Fixed Type Id
Nightly toolchain required.
Make your types have a fixed type id and stable type name between different builds.
The crate provides a trait and a procedural macro. By implementing [FixedTypeId],
other crates can use methods [FixedTypeId::ty_id()], [FixedTypeId::ty_name()] and [FixedTypeId::ty_version()] or
standalone functions [fixed_type_id::type_id], [fixed_type_id::type_name] and [fixed_type_id::type_version]
to get the type id, name and version about this type.
It use rapidhash to hash the type name you provided, with/without version hashed into the id. Then provide the hash as a fixed id for your type. So you can construct exact the same id from the same type name and version.
The purpose of this crate is to provide a fixed type id for simple types, which you may want to persist their metadata, like u8, i16, f32, str, String, bool, (u8,i16,f32), [u8; 3], [i16; 3], &[u8], etc. Or types frequently used in your structs, like HashMap<K, V>, Vec<T>, Box<T> etc.
It also support trait objects, which is used by trait_cast_rs to cast between different traits.
Note that the type name implemented by default for standard library types may be different from [core::any::type_name], you shouldn't compare it with [FixedTypeId::ty_name()].
Because of the orphan rule, if you want to implement [FixedTypeId] for types in other crates, you can submit a PR to add them.
Usage
The example usage:
#
use ;
use Hasher;
use *;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
If you want to define for your generic struct, you can use [implement_wrapper_fixed_type_id]:
#
use ;
use Add;
implement_wrapper_fixed_type_id!
assert_eq!;
Also, you can define this trait yoursellf:
#
use ;
use rapidhash;
;
assert_eq!;
assert_eq!;
assert_eq!;
There are standalone functions to get the type_name, type_id and type_version, like [std::any::type_name], [std::any::type_id]:
#
use ;
use ;
;
assert_eq!;
assert_eq!;
assert_eq!;
Notes
Specialization
You can enable specialization by feature flag specialization, default is disabled. When enabled, it will implement [FixedTypeId] for all types, with dummy type info, not only the types you defined. Make it more like [std::any::type_name], [std::any::type_id].
Currently, the dummy type info is:
type_name: "NOT_IMPLEMENTED"
type_id: FixedId::from_type_name("NOT_IMPLEMENTED", Some(FixedVersion::new(0,0,0)))
type_version: FixedVersion::new(0,0,0)
When you are working with extern crates's generic functions, these dummy type info may be useful.
Version
For standard libraries types, the version is always (0,0,0), in the future, it may be changed to rustc version you are using.
Currently, this crate implement [FixedTypeId] for these types:
(),InfallibleTfor all primitive types, likeu8,i16,f32,str,String,booletc.&T,&mut Tfor all primitive typesBox<T>,Vec<T>,HashMap<K, V>,PhantomData<T>,NonZero<T>,fn(T) -> R,fn() -> Rfor all generic types that implement [FixedTypeId](T,),(T,U),(T,U,V)...(T1,..., T16)for all generic types that implement [FixedTypeId][T; N]for allTthat implement [FixedTypeId], but there is a limit forN, onlyN <= 32or some special numbers(64,128,256,...,768,1024,2048,...,65535) are supported, other numbers will just leave it asN. If you know how to generate&strforconst N: usizein const context, you can submit a PR to add it.
Type Name Length
When you want to implement [FixedTypeId] for your types with generic parameters, you need to provide a dynamic generated &str as type name either 1. in const context or 2. store a &[&str] in const and then concat them at runtime.
If we choose to generate it in const context, because the only way i know to dynamically generate a &str in const context is to fill a fixed length array [u8;N], and this array will be persisted into the binary, so the length of the type name is limited by the binary size. Currently, the length can be configured by feature flags len64, len128 and len256, the default is len128, it means the max length of the type name is 128 bytes.
If we choose to store a &[&str] in const and then concat them at runtime, the return type of [FixedTypeId::ty_name()] will be String, it's different from the return type of [core::any::type_name], which is &'static str. It makes it difficult to just replace [core::any::type_name] with [type_name] or [FixedTypeId::ty_name()].
So currently we choose to generate it in const context.
Differences between fixed_type_id, fixed_type_id_without_version_hash and random_fixed_type_id
fixed_type_id: Generate a unique id for the type, with a [FixedId] that [rapidhash::rapidhash] the name you provided, the version is also hashed into the [FixedId]. Version defaults to(0,0,0), use#[FixedTypeIdVersion((0,1,0))]to change it. Use it when you want that different versions of your type have different ids.fixed_type_id_without_version_hash: Generate a unique id for the type, with a [FixedId] that [rapidhash::rapidhash] the name you provided, without version hashed into the [FixedId]. Use it when you want that different versions of your type have the same id.random_fixed_type_id: Generate a random id for the type, with a [FixedId] that random generated for each build.
All these macros can be used with:
#[FixedTypeIdVersion((x,y,z))]: Set the version to(x,y,z).#[FixedTypeIdFile("filename.toml")]: Store the type id into a file, so you can use it for debug, make sure the file already exists.#[FixedTypeIdEqualTo("other_type")]: Make the type id [FixedId] equal toother_type, so the two types have the same id, but different type names, and versions.
Erase Type Name
It can be configured by feature flag erase_name, default is disabled.
Currently, it only works for implementation of [FixedTypeId] by fixed_type_id and fixed_type_id_without_version_hash.