12 个版本 (6 个破坏性更新)

0.6.0 2021 年 10 月 6 日
0.5.0 2021 年 10 月 5 日
0.4.1 2021 年 10 月 5 日
0.3.3 2021 年 10 月 5 日
0.0.0 2021 年 9 月 30 日

#666 in 内存管理

Apache-2.0

48KB
1K SLoC

RaTTIsh

rattish 允许在不同的特质对象之间进行动态转换。

此功能需要运行时类型信息,这些信息不是由 Rust 编译器自动创建的,因此必须手动生成。

rattish 目前仅处于实验阶段,并依赖于不稳定编译器功能,包括 generic_associated_typesptr_metadataunsizeonce_cellDB(通过 global 功能启用)使用。因此,需要 nightly 工具链。

示例

#![feature(generic_associated_types, once_cell)]

use rattish::{coercible_trait, rtti_global, GlobalDynCast};
use std::{any::Any, cell::RefCell, fmt, rc::Rc};

// Casting from an object of trait Foo requires Foo to have
// super-trait Any..
trait Foo: Any {}
// ..and that Foo implements both Coercible and InnermostTypeId,
// for which there is a macro:
coercible_trait!(Foo);

// Casting to an object of trait Bar does not require anything
// special..
trait Bar {
    fn double(&self) -> i32;
}

struct Qux(i32);
impl Foo for Qux {}
impl Bar for Qux {
    fn double(&self) -> i32 {
        self.0 * 2
    }
}

fn main() {
    // ..except that Bar must be registered in the database with
    // each implementing (concrete) type that might underlie a
    // dynamic cast to one of its objects
    rtti_global! {
        Bar: Qux,

        // example of another trait with multiple implementations
        fmt::LowerExp: f32 i32 u32,
    }

    // Casting works transitively through any Coercible type.
    // Implementations are provided for all standard pointer and
    // wrapper types; here, for example, are Rc and RefCell:
    let foo: Rc<RefCell<dyn Foo>> = Rc::new(RefCell::new(Qux(123)));

    // Explicit type annotation not required; only shown here to
    // prove that we actually get an Rc<RefCell<dyn Bar>>
    let bar: Rc<RefCell<dyn Bar>>
        = foo.dyn_cast::<dyn Bar>().ok().unwrap();

    // Lo!  We have indeed casted between trait objects.
    assert_eq!(bar.borrow().double(), 246);

    // Enjoy that?  Have another, just for fun:
    let float: &dyn Any = &876.543f32;
    let exp = float.dyn_cast::<dyn fmt::LowerExp>().ok().unwrap();
    assert_eq!(format!("{:e}", exp), "8.76543e2");
}

扩展 rattish 以支持额外的指针/包装类型

您需要为您的类型实现 CoercibleInnermostTypeId;如果您的类型是指针类型(即,如果它是 Sized + Deref),则还需要实现 Pointer

依赖项

~200KB