#non-static #const #no-alloc #const-type-id

无 std typeid

常量 TypeId 和非静态 TypeId

4 个版本 (稳定版)

1.0.2 2024 年 8 月 17 日
1.0.0 2024 年 5 月 14 日
0.0.1 2024 年 5 月 13 日

#22无标准库

Download history 14992/week @ 2024-05-10 38303/week @ 2024-05-17 47151/week @ 2024-05-24 53751/week @ 2024-05-31 65827/week @ 2024-06-07 78180/week @ 2024-06-14 77128/week @ 2024-06-21 77833/week @ 2024-06-28 92575/week @ 2024-07-05 94508/week @ 2024-07-12 101247/week @ 2024-07-19 110976/week @ 2024-07-26 114415/week @ 2024-08-02 124065/week @ 2024-08-09 107681/week @ 2024-08-16

475,811 每月下载量
1,307 个 Crates 中使用 (直接使用 3 个)

MIT/Apache 协议

13KB
126

常量 TypeId 和非静态 TypeId

github crates.io docs.rs build status

常量 TypeId

此 crate 提供 ConstTypeId,它类似于 core::any::TypeId,但可以在稳定 Rust 的 const 中构建。 (标准库的 TypeId 只在 nightly 中可以用于 const 构建;关于此问题的跟踪问题是 rust#77125。)

能够在 const 中构建 ConstTypeId,使其适用于依赖于静态提升的使用场景

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

以及在关联常量中

use typeid::ConstTypeId;

pub trait GetTypeId {
    const TYPEID: ConstTypeId;
}

impl<T: 'static> GetTypeId for T {
    const TYPEID: ConstTypeId = ConstTypeId::of::<Self>();
}

非静态 TypeId

此 crate 提供 typeid::of,它接受一个任意非静态类型 T 并生成将 T 中所有生命周期替换为 'static(除了在 trait 对象中找到的更高秩生命周期之外)的类型 TypeId

例如,如果 T&'b dyn for<'a> Trait<'a, 'c>,则 typeid::of::<T>() 生成 &'static dyn for<'a> Trait<'a, 'static> 的 TypeId。

应该很明显,与标准库中的 TypeId 不同,typeid::of::<A>() == typeid::of::<B>() 并不意味着 AB 是同一类型。然而,有一种常见特殊情况,这种行为正是所需要的。如果

  • A 是一个任意的非 'static 类型参数,并且
  • B 是 'static,并且
  • 所有与 B 具有相同 id 的类型也是 'static

typeid::of::<A>() == typeid::of::<B>() 保证 AB 是同一类型。

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]) {/* ... */}

许可证

根据您的选择,在 Apache 许可证 2.0 版MIT 许可证 下许可。
除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交以包含在此软件包中的任何贡献,应如上所述双重许可,不得附加任何额外的条款或条件。

无运行时依赖