diff options
author | HampusM <hampus@hampusmat.com> | 2022-07-24 11:02:33 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2022-07-24 11:02:33 +0200 |
commit | 613cd7129439d04f576325bcf55d276847efb136 (patch) | |
tree | 3dc1c300b1b492fca1aeaa7410969347b54737fc | |
parent | bd70e925f773de338c93cfd2ff720ef11aaa0848 (diff) |
refactor: clean up intertrait lib
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | macros/src/libs/intertrait_macros/gen_caster.rs | 33 | ||||
-rw-r--r-- | src/libs/intertrait/cast_box.rs | 10 | ||||
-rw-r--r-- | src/libs/intertrait/cast_rc.rs | 10 | ||||
-rw-r--r-- | src/libs/intertrait/hasher.rs | 48 | ||||
-rw-r--r-- | src/libs/intertrait/mod.rs | 71 |
6 files changed, 63 insertions, 110 deletions
@@ -20,6 +20,7 @@ syrette_macros = { path = "./macros", version = "0.1.1" } linkme = "0.3.0" once_cell = "1.4" error-stack = "0.1.1" +ahash = "0.7.6" [dev_dependencies] mockall = "0.11.1" diff --git a/macros/src/libs/intertrait_macros/gen_caster.rs b/macros/src/libs/intertrait_macros/gen_caster.rs index 9126200..d77262a 100644 --- a/macros/src/libs/intertrait_macros/gen_caster.rs +++ b/macros/src/libs/intertrait_macros/gen_caster.rs @@ -11,8 +11,9 @@ * at your option. */ -use std::str::from_utf8_unchecked; +use std::str::from_utf8; +use proc_macro2::Ident; use proc_macro2::TokenStream; use quote::format_ident; use quote::quote; @@ -20,14 +21,16 @@ use quote::ToTokens; use uuid::adapter::Simple; use uuid::Uuid; -pub fn generate_caster(ty: &impl ToTokens, trait_: &impl ToTokens) -> TokenStream -{ - let mut fn_buf = [0u8; FN_BUF_LEN]; +const CASTER_FN_NAME_PREFIX: &[u8] = b"__"; + +const FN_BUF_LEN: usize = CASTER_FN_NAME_PREFIX.len() + Simple::LENGTH; - let fn_ident = format_ident!("{}", new_fn_name(&mut fn_buf)); +pub fn generate_caster(ty: &impl ToTokens, dst_trait: &impl ToTokens) -> TokenStream +{ + let fn_ident = create_caster_fn_ident(); let new_caster = quote! { - syrette::libs::intertrait::Caster::<dyn #trait_>::new( + syrette::libs::intertrait::Caster::<dyn #dst_trait>::new( |from| from.downcast::<#ty>().unwrap(), |from| from.downcast::<#ty>().unwrap(), ) @@ -42,14 +45,18 @@ pub fn generate_caster(ty: &impl ToTokens, trait_: &impl ToTokens) -> TokenStrea } } -const FN_PREFIX: &[u8] = b"__"; -const FN_BUF_LEN: usize = FN_PREFIX.len() + Simple::LENGTH; - -fn new_fn_name(buf: &mut [u8]) -> &str +fn create_caster_fn_ident() -> Ident { - buf[..FN_PREFIX.len()].copy_from_slice(FN_PREFIX); + let buf = &mut [0u8; FN_BUF_LEN]; + + buf[..CASTER_FN_NAME_PREFIX.len()].copy_from_slice(CASTER_FN_NAME_PREFIX); + Uuid::new_v4() .to_simple() - .encode_lower(&mut buf[FN_PREFIX.len()..]); - unsafe { from_utf8_unchecked(&buf[..FN_BUF_LEN]) } + .encode_lower(&mut buf[CASTER_FN_NAME_PREFIX.len()..]); + + let fn_name = + from_utf8(&buf[..FN_BUF_LEN]).expect("Created caster function name is not UTF-8"); + + format_ident!("{}", fn_name) } diff --git a/src/libs/intertrait/cast_box.rs b/src/libs/intertrait/cast_box.rs index 793efd0..b2ec77e 100644 --- a/src/libs/intertrait/cast_box.rs +++ b/src/libs/intertrait/cast_box.rs @@ -15,16 +15,16 @@ use crate::libs::intertrait::{caster, CastFrom}; pub trait CastBox { - /// Casts a box to this trait into that of type `T`. If fails, returns the receiver. - fn cast<T: ?Sized + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>>; + /// Casts a box to this trait into that of `Trait`. If fails, returns the receiver. + fn cast<Trait: ?Sized + 'static>(self: Box<Self>) -> Result<Box<Trait>, Box<Self>>; } /// A blanket implementation of `CastBox` for traits extending `CastFrom`. -impl<S: ?Sized + CastFrom> CastBox for S +impl<CastableFrom: ?Sized + CastFrom> CastBox for CastableFrom { - fn cast<T: ?Sized + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> + fn cast<Trait: ?Sized + 'static>(self: Box<Self>) -> Result<Box<Trait>, Box<Self>> { - match caster::<T>((*self).type_id()) { + match caster::<Trait>((*self).type_id()) { Some(caster) => Ok((caster.cast_box)(self.box_any())), None => Err(self), } diff --git a/src/libs/intertrait/cast_rc.rs b/src/libs/intertrait/cast_rc.rs index 79d8d60..5901b5e 100644 --- a/src/libs/intertrait/cast_rc.rs +++ b/src/libs/intertrait/cast_rc.rs @@ -17,16 +17,16 @@ use crate::libs::intertrait::{caster, CastFrom}; pub trait CastRc { - /// Casts an `Rc` for this trait into that for type `T`. - fn cast<T: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<T>, Rc<Self>>; + /// Casts an `Rc` for this trait into that for `Trait`. + fn cast<Trait: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<Trait>, Rc<Self>>; } /// A blanket implementation of `CastRc` for traits extending `CastFrom`. -impl<S: ?Sized + CastFrom> CastRc for S +impl<CastableFrom: ?Sized + CastFrom> CastRc for CastableFrom { - fn cast<T: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<T>, Rc<Self>> + fn cast<Trait: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<Trait>, Rc<Self>> { - match caster::<T>((*self).type_id()) { + match caster::<Trait>((*self).type_id()) { Some(caster) => Ok((caster.cast_rc)(self.rc_any())), None => Err(self), } diff --git a/src/libs/intertrait/hasher.rs b/src/libs/intertrait/hasher.rs deleted file mode 100644 index e7f110d..0000000 --- a/src/libs/intertrait/hasher.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![allow(clippy::module_name_repetitions)] - -/** - * Originally from Intertrait by CodeChain - * - * <https://github.com/CodeChain-io/intertrait> - * <https://crates.io/crates/intertrait/0.2.2> - * - * Licensed under either of - * - * Apache License, Version 2.0 (LICENSE-APACHE or <http://www.apache.org/licenses/LICENSE-2.0>) - * MIT license (LICENSE-MIT or <http://opensource.org/licenses/MIT>) - - * at your option. -*/ -use std::convert::TryInto; -use std::hash::{BuildHasherDefault, Hasher}; -use std::mem::size_of; - -/// A simple `Hasher` implementation tuned for performance. -#[derive(Default)] -pub struct FastHasher(u64); - -/// A `BuildHasher` for `FastHasher`. -pub type BuildFastHasher = BuildHasherDefault<FastHasher>; - -impl Hasher for FastHasher -{ - fn finish(&self) -> u64 - { - self.0 - } - - fn write(&mut self, bytes: &[u8]) - { - let mut bytes = bytes; - while bytes.len() > size_of::<u64>() { - let (u64_bytes, remaining) = bytes.split_at(size_of::<u64>()); - - self.0 ^= u64::from_ne_bytes(u64_bytes.try_into().unwrap()); - - bytes = remaining; - } - self.0 ^= bytes - .iter() - .fold(0u64, |result, b| (result << 8) | u64::from(*b)); - } -} 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> { |