diff options
Diffstat (limited to 'src/libs/intertrait/mod.rs')
-rw-r--r-- | src/libs/intertrait/mod.rs | 71 |
1 files changed, 32 insertions, 39 deletions
diff --git a/src/libs/intertrait/mod.rs b/src/libs/intertrait/mod.rs index 1daca64..2cdc67d 100644 --- a/src/libs/intertrait/mod.rs +++ b/src/libs/intertrait/mod.rs @@ -12,64 +12,62 @@ * at your option. */ use std::any::{Any, TypeId}; -use std::collections::HashMap; use std::rc::Rc; -use std::sync::Arc; +use ahash::AHashMap; use linkme::distributed_slice; use once_cell::sync::Lazy; -mod hasher; - -use hasher::BuildFastHasher; - pub mod cast_box; pub mod cast_rc; pub type BoxedCaster = Box<dyn Any + Send + Sync>; +type CasterFn = fn() -> (TypeId, BoxedCaster); + #[distributed_slice] -pub static CASTERS: [fn() -> (TypeId, BoxedCaster)] = [..]; - -static CASTER_MAP: Lazy<HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher>> = - Lazy::new(|| { - CASTERS - .iter() - .map(|f| { - let (type_id, caster) = f(); - ((type_id, (*caster).type_id()), caster) - }) - .collect() - }); - -pub struct Caster<T: ?Sized + 'static> +pub static CASTERS: [CasterFn] = [..]; + +static CASTER_MAP: Lazy<AHashMap<(TypeId, TypeId), BoxedCaster>> = Lazy::new(|| { + CASTERS + .iter() + .map(|caster_fn| { + let (type_id, caster) = caster_fn(); + + ((type_id, (*caster).type_id()), caster) + }) + .collect() +}); + +pub struct Caster<Trait: ?Sized + 'static> { /// Casts a `Box` holding a trait object for `Any` to another `Box` holding a trait object - /// for trait `T`. - pub cast_box: fn(from: Box<dyn Any>) -> Box<T>, + /// for `Trait`. + pub cast_box: fn(from: Box<dyn Any>) -> Box<Trait>, /// Casts an `Rc` holding a trait object for `Any` to another `Rc` holding a trait object - /// for trait `T`. - pub cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>, + /// for `Trait`. + pub cast_rc: fn(from: Rc<dyn Any>) -> Rc<Trait>, } -impl<T: ?Sized + 'static> Caster<T> +impl<Trait: ?Sized + 'static> Caster<Trait> { pub fn new( - cast_box: fn(from: Box<dyn Any>) -> Box<T>, - cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>, - ) -> Caster<T> + cast_box: fn(from: Box<dyn Any>) -> Box<Trait>, + cast_rc: fn(from: Rc<dyn Any>) -> Rc<Trait>, + ) -> Caster<Trait> { - Caster::<T> { cast_box, cast_rc } + Caster::<Trait> { cast_box, cast_rc } } } -/// Returns a `Caster<S, T>` from a concrete type `S` to a trait `T` implemented by it. -fn caster<T: ?Sized + 'static>(type_id: TypeId) -> Option<&'static Caster<T>> +/// Returns a `Caster<Implementation, Trait>` from a concrete type `Implementation` +/// from inside `CASTER_MAP` to a `Trait` implemented by it. +fn caster<Trait: ?Sized + 'static>(type_id: TypeId) -> Option<&'static Caster<Trait>> { CASTER_MAP - .get(&(type_id, TypeId::of::<Caster<T>>())) - .and_then(|caster| caster.downcast_ref::<Caster<T>>()) + .get(&(type_id, TypeId::of::<Caster<Trait>>())) + .and_then(|caster| caster.downcast_ref::<Caster<Trait>>()) } /// `CastFrom` must be extended by a trait that wants to allow for casting into another trait. @@ -92,12 +90,7 @@ pub trait CastFrom: Any + 'static fn rc_any(self: Rc<Self>) -> Rc<dyn Any>; } -pub trait CastFromSync: CastFrom + Sync + Send + 'static -{ - fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>; -} - -impl<T: Sized + Any + 'static> CastFrom for T +impl<Trait: Sized + Any + 'static> CastFrom for Trait { fn box_any(self: Box<Self>) -> Box<dyn Any> { |