use std::any::{Any,TypeId};
use std::sync::Arc;
-use downcast_rs::{DowncastSync, impl_downcast};
+use downcast_rs::{Downcast, DowncastSync, impl_downcast};
pub trait HasPseudoMethods: DowncastSync {
- fn cast_to_instance(&self, arc: &Arc<dyn HasPseudoMethods>, tp: TypeId) -> Option<Box<dyn Any>>;
+ fn get_caster(&self, tp: TypeId) -> Option<&'static dyn Any>;
}
impl_downcast!(sync HasPseudoMethods);
/*
// Note: if you wanted to be able to add more traits to Frog elsewhere, you would
// need a registry of cast-to-trait objects, similar to the existing dispatch
// table. I'm not sure if that's needed.
- fn cast_to_instance(&self, arc: &Arc<dyn HasPseudoMethods>, tp: TypeId) -> Option<Box<dyn Any>> {
- if tp == TypeId::of::<Arc<dyn HasFeet>>() {
- let arc: Arc<dyn Any + Send + Sync> = DowncastSync::into_any_arc(arc.clone());
+ fn get_caster(&self, tp: TypeId) -> Option<&'static dyn Any> {
+ if tp == TypeId::of::<
+ &'static dyn HasFeet
+ >() {
+/* let arc: Arc<dyn Any + Send + Sync> = DowncastSync::into_any_arc(arc.clone());
let arc: Arc<Frog> = Arc::downcast::<Frog>(arc).unwrap();
let arc: Arc<dyn HasFeet> = arc as _;
- return Some(Box::new(arc));
+ */
+ static CASTER: fn(&dyn HasPseudoMethods) -> &dyn HasFeet
+ = |self_| {
+ let self_: &dyn Any = Downcast::as_any(self_);
+ let self_: &Frog = self_.downcast_ref().unwrap();
+ let self_: &dyn HasFeet = self_ as _;
+ self_
+ };
+
+ return Some(&CASTER);
/* } else if tp == TypeId::of::<Arc<dyn EatsFood>>() {
let arc: Arc<dyn EatsFood> = self.clone();
return Some(Box::new(arc));
}
fn main() {
- let frog = Arc::new(Frog);
- let erased_frog: Arc<dyn HasPseudoMethods> = frog as _;
+ let frog = Arc::new(Frog);
+ let erased_frog: Arc<dyn HasPseudoMethods> = frog as _;
+ let erased_frog: &dyn HasPseudoMethods = &*erased_frog;
- let with_feet: Box<dyn Any> = erased_frog.cast_to_instance(
- &erased_frog,
- TypeId::of::<Arc<dyn HasFeet>>(),
- ).unwrap();
+ let caster: &'static dyn Any
+ = erased_frog.get_caster(TypeId::of::<&'static dyn HasFeet>()).unwrap();
- let with_feet: Box<Arc<dyn HasFeet>> = with_feet.downcast().unwrap();
+ let caster: &'static fn(&dyn HasPseudoMethods) -> &dyn HasFeet
+ = caster.downcast_ref().unwrap();
+ let with_feet: &dyn HasFeet = caster(erased_frog);
+
println!("A frog has {} feet and eats .",
with_feet.how_many_feet(),/*
eats_food.favorite_food()*/)