12 个版本 (6 个破坏性更新)
0.6.0 | 2021 年 10 月 6 日 |
---|---|
0.5.0 | 2021 年 10 月 5 日 |
0.4.1 | 2021 年 10 月 5 日 |
0.3.3 |
|
0.0.0 | 2021 年 9 月 30 日 |
#666 in 内存管理
48KB
1K SLoC
RaTTIsh
rattish 允许在不同的特质对象之间进行动态转换。
此功能需要运行时类型信息,这些信息不是由 Rust 编译器自动创建的,因此必须手动生成。
rattish 目前仅处于实验阶段,并依赖于不稳定编译器功能,包括 generic_associated_types
、ptr_metadata
和 unsize
;once_cell
由 DB
(通过 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 以支持额外的指针/包装类型
您需要为您的类型实现 Coercible
和 InnermostTypeId
;如果您的类型是指针类型(即,如果它是 Sized + Deref
),则还需要实现 Pointer
。
依赖项
~200KB