rattish enables dynamic casting between different trait objects.
This functionality requires runtime type information that isn't automatically created by the Rust compiler and so must be generated manually.
rattish is presently only experimental, and depends on unstable compiler
features including [generic_associated_types
], [ptr_metadata
] and
[unsize
]. Accordingly, a nightly toolchain is required.
```rust use rattish::{coercibletrait, rttistatic, StaticDynCast}; 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 Coercible, for which there is a macro coercible_trait!(Foo);
// casting to an object of trait Bar does not require anything special.. trait Bar { fn bar(&self) -> i32; }
struct Qux(i32); impl Foo for Qux {} impl Bar for Qux { fn bar(&self) -> i32 { self.0 * 2 } }
// ..except that Bar must be registered in the database with every one of its // concrete types that might get dynamically cast to a Bar trait object rtti_static! { Bar: Qux,
// example of another trait with multiple implementations
fmt::LowerExp: u32 i32 f32,
}
// casting works through any type that implements Coercible
// implementations are provided for all standard pointer and wrapper types
// here, for example, are Rc and RefCell
let foo: Rc
// explicit type annotation not required; only included here for information
let bar: Rc
// enjoyed that? have another, just for fun
let exp = (&int as &dyn Any).dyncast::