This crate provides trait HasTypeId
with associated constant TYPE_ID
and derive macro to implement it for your types.
There are 4 guarantees:
TYPE_ID
is a constant.- Size is 32 bit.
TypeId
cannot be zero which allows niche optimizations (size_of::<Option<TypeId>>()
is 4 bytes).- Most significant bit (MSB) is guaranteed to be zero:
- Allows users to use this bit to distinguish with some other kind of id in a union (e.g. Runtime types from some scripting engine).
- Does not allow niche optimizations on current version of Rust yet.
Those guarantees would never be removed (even in semver breaking releases) so you can update dependency on this crate without validating your code that rely on that guarantees.
Uniqueness of TypeIds
is enforced by running code before fn main()
using ctor
crate.
Comparison with std::any::TypeId
With std::any::TypeId
as at Rust 1.87.
TYPE_ID
is a constant.- Size of
small_type_id::TypeId
is guaranteed to be 32 bits. - Size of
small_type_id::TypeId
is significantly smaller(4 vs 16 bytes), allowing better performance due to less usage of CPU cache. small_type_id::TypeId
supports niche optimization forOption<small_type_id::TypeId>
.small_type_id::TypeId
guarantees that MSB is zero, allowing creating 32 bit identifiers by users usingunion
s:- Since user types would need to set MSB to 1, resulting value is still cannot be zero, allowing niche optimization.
small_type_id::HasTypeId
needs to be derived for supported types, it doesn't work automatically.small_type_id::HasTypeId
doesn't support generic types.
Comparison with typeid::ConstTypeId
With typeid
version 1.0.3
- Has smaller size (32 bit vs 64 bit on 64-bit targets).
- Has defined internal representation that can be utilized by users.
- Doesn't support every type.
Example:
use small_type_id::HasTypeId as _;
#[derive(small_type_id::HasTypeId)]
pub struct Struct {
pub a: u32,
pub b: usize,
}
#[derive(small_type_id::HasTypeId)]
pub enum Enum {
A(u32), B(String)
}
// Check that they are different:
assert_ne!(Struct::TYPE_ID, Enum::TYPE_ID);
// Or even in compile time:
const { assert!(Struct::TYPE_ID.as_u32() != Enum::TYPE_ID.as_u32()); };
More examples and implementation explanation are available in documentation.
Uniqueness is tested before running fn main()
(unless opt-out), so code can rely on type ids being unique.
Code is tested in CI on following platforms:
- macos
- Windows
- Linux with the following libc implementations:
- glibc
- musl
- eyra-libc
There is also some testing with Address-Sanitizer.
- Thanks to mmastrac for crate
ctor
used for implementing this crate. - Thanks to dtolnay for crate
linkme
which helped to learn me about using link sections for gathering statics. - Thanks to Raymond Chen for his explanations about linker sections.