Crates.io | typeid |
lib.rs | typeid |
version | 1.0.2 |
source | src |
created_at | 2024-05-13 10:52:11.529794 |
updated_at | 2024-08-17 05:39:10.063255 |
description | Const TypeId and non-'static TypeId |
homepage | |
repository | https://github.com/dtolnay/typeid |
max_upload_size | |
id | 1238282 |
size | 26,693 |
TypeId
and non-'static TypeId
TypeId
This crate provides ConstTypeId
, which is like core::any::TypeId
but is
constructible in const in stable Rust. (The standard library's TypeId's is
nightly-only to construct in const; the tracking issue for this is
rust#77125.)
Being able to construct ConstTypeId
in const makes it suitable for use cases
that rely on static promotion:
use std::fmt::{self, Debug, Display};
use std::ptr;
use typeid::ConstTypeId;
pub struct ObjectVTable {
type_id: ConstTypeId,
drop_in_place: unsafe fn(*mut ()),
display: unsafe fn(*const (), &mut fmt::Formatter) -> fmt::Result,
debug: unsafe fn(*const (), &mut fmt::Formatter) -> fmt::Result,
}
impl ObjectVTable {
pub const fn new<T: Display + Debug>() -> &'static Self {
&ObjectVTable {
type_id: const { ConstTypeId::of::<T>() },
drop_in_place: |ptr| unsafe { ptr::drop_in_place(ptr.cast::<T>()) },
display: |ptr, f| unsafe { Display::fmt(&*ptr.cast::<T>(), f) },
debug: |ptr, f| unsafe { Debug::fmt(&*ptr.cast::<T>(), f) },
}
}
}
and in associated constants:
use typeid::ConstTypeId;
pub trait GetTypeId {
const TYPEID: ConstTypeId;
}
impl<T: 'static> GetTypeId for T {
const TYPEID: ConstTypeId = ConstTypeId::of::<Self>();
}
TypeId
This crate provides typeid::of
, which takes an arbitrary non-'static type
T
and produces the TypeId
for the type obtained by replacing all lifetimes
in T
by 'static
, other than higher-rank lifetimes found in trait objects.
For example if T
is &'b dyn for<'a> Trait<'a, 'c>
, then typeid::of::<T>()
produces the TypeId of &'static dyn for<'a> Trait<'a, 'static>
.
It should be obvious that unlike with the standard library's TypeId,
typeid::of::<A>() == typeid::of::<B>()
does not mean that A
and B
are
the same type. However, there is a common special case where this behavior is
exactly what is needed. If:
A
is an arbitrary non-'static type parameter, andB
is 'static, andB
are also 'staticthen typeid::of::<A>() == typeid::of::<B>()
guarantees that A
and B
are
the same type.
use core::any::TypeId;
use core::slice;
pub fn example<T>(slice: &[T]) {
// T is arbitrary and non-'static.
if typeid::of::<T>() == TypeId::of::<u8>() {
// T is definitely u8
let bytes = unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) };
process_bytes(bytes);
} else {
for t in slice {
process(t);
}
}
}
fn process<T>(_: &T) {/* ... */}
fn process_bytes(_: &[u8]) {/* ... */}