diff --git a/src/any.rs b/src/any.rs index 8ff20298..897bc922 100644 --- a/src/any.rs +++ b/src/any.rs @@ -203,6 +203,7 @@ impl Dynamic { } /// Map the name of a standard type into a friendly form. +#[inline] pub(crate) fn map_std_type_name(name: &str) -> &str { if name == type_name::() { "string" @@ -340,30 +341,47 @@ impl Dynamic { /// assert_eq!(new_result.type_name(), "string"); /// assert_eq!(new_result.to_string(), "hello"); /// ``` + #[inline(always)] pub fn from(value: T) -> Self { - if let Some(result) = ::downcast_ref::<()>(&value) { - return result.clone().into(); - } else if let Some(result) = ::downcast_ref::(&value) { - return result.clone().into(); - } else if let Some(result) = ::downcast_ref::(&value) { - return result.clone().into(); - } else if let Some(result) = ::downcast_ref::(&value) { - return result.clone().into(); - } else if let Some(result) = ::downcast_ref::(&value) { - return result.clone().into(); - } + let type_id = TypeId::of::(); + if type_id == TypeId::of::() { + return ::downcast_ref::(&value) + .unwrap() + .clone() + .into(); + } #[cfg(not(feature = "no_float"))] - if let Some(result) = ::downcast_ref::(&value) { - return result.clone().into(); + if type_id == TypeId::of::() { + return ::downcast_ref::(&value) + .unwrap() + .clone() + .into(); + } + if type_id == TypeId::of::() { + return ::downcast_ref::(&value) + .unwrap() + .clone() + .into(); + } + if type_id == TypeId::of::() { + return ::downcast_ref::(&value) + .unwrap() + .clone() + .into(); + } + if type_id == TypeId::of::() { + return ::downcast_ref::(&value) + .unwrap() + .clone() + .into(); + } + if type_id == TypeId::of::<()>() { + return ().into(); } let mut boxed = Box::new(value); - boxed = match unsafe_cast_box::<_, Dynamic>(boxed) { - Ok(d) => return *d, - Err(val) => val, - }; boxed = match unsafe_cast_box::<_, String>(boxed) { Ok(s) => return (*s).into(), Err(val) => val, @@ -384,6 +402,11 @@ impl Dynamic { } } + boxed = match unsafe_cast_box::<_, Dynamic>(boxed) { + Ok(d) => return *d, + Err(val) => val, + }; + Self(Union::Variant(Box::new(boxed))) } @@ -401,30 +424,80 @@ impl Dynamic { /// /// assert_eq!(x.try_cast::().unwrap(), 42); /// ``` + #[inline(always)] pub fn try_cast(self) -> Option { let type_id = TypeId::of::(); + if type_id == TypeId::of::() { + return match self.0 { + Union::Int(value) => unsafe_try_cast(value), + _ => None, + }; + } + #[cfg(not(feature = "no_float"))] + if type_id == TypeId::of::() { + return match self.0 { + Union::Float(value) => unsafe_try_cast(value), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match self.0 { + Union::Bool(value) => unsafe_try_cast(value), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match self.0 { + Union::Str(value) => unsafe_try_cast(value), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match self.0 { + Union::Str(value) => unsafe_try_cast(value.into_owned()), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match self.0 { + Union::Char(value) => unsafe_try_cast(value), + _ => None, + }; + } + #[cfg(not(feature = "no_index"))] + if type_id == TypeId::of::() { + return match self.0 { + Union::Array(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v), + _ => None, + }; + } + #[cfg(not(feature = "no_object"))] + if type_id == TypeId::of::() { + return match self.0 { + Union::Map(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match self.0 { + Union::FnPtr(value) => unsafe_try_cast(value), + _ => None, + }; + } + if type_id == TypeId::of::<()>() { + return match self.0 { + Union::Unit(value) => unsafe_try_cast(value), + _ => None, + }; + } if type_id == TypeId::of::() { return unsafe_cast_box::<_, T>(Box::new(self)).ok().map(|v| *v); } match self.0 { - Union::Unit(value) => unsafe_try_cast(value), - Union::Bool(value) => unsafe_try_cast(value), - Union::Str(value) if type_id == TypeId::of::() => { - unsafe_try_cast(value) - } - Union::Str(value) => unsafe_try_cast(value.into_owned()), - Union::Char(value) => unsafe_try_cast(value), - Union::Int(value) => unsafe_try_cast(value), - #[cfg(not(feature = "no_float"))] - Union::Float(value) => unsafe_try_cast(value), - #[cfg(not(feature = "no_index"))] - Union::Array(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v), - #[cfg(not(feature = "no_object"))] - Union::Map(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v), - Union::FnPtr(value) => unsafe_try_cast(value), Union::Variant(value) => (*value).as_box_any().downcast().map(|x| *x).ok(), + _ => None, } } @@ -444,81 +517,162 @@ impl Dynamic { /// /// assert_eq!(x.cast::(), 42); /// ``` + #[inline(always)] pub fn cast(self) -> T { - let type_id = TypeId::of::(); - - if type_id == TypeId::of::() { - return *unsafe_cast_box::<_, T>(Box::new(self)).unwrap(); - } - - match self.0 { - Union::Unit(value) => unsafe_try_cast(value).unwrap(), - Union::Bool(value) => unsafe_try_cast(value).unwrap(), - Union::Str(value) if type_id == TypeId::of::() => { - unsafe_try_cast(value).unwrap() - } - Union::Str(value) => unsafe_try_cast(value.into_owned()).unwrap(), - Union::Char(value) => unsafe_try_cast(value).unwrap(), - Union::Int(value) => unsafe_try_cast(value).unwrap(), - #[cfg(not(feature = "no_float"))] - Union::Float(value) => unsafe_try_cast(value).unwrap(), - #[cfg(not(feature = "no_index"))] - Union::Array(value) => *unsafe_cast_box::<_, T>(value).unwrap(), - #[cfg(not(feature = "no_object"))] - Union::Map(value) => *unsafe_cast_box::<_, T>(value).unwrap(), - Union::FnPtr(value) => unsafe_try_cast(value).unwrap(), - Union::Variant(value) => (*value).as_box_any().downcast().map(|x| *x).unwrap(), - } + self.try_cast::().unwrap() } /// Get a reference of a specific type to the `Dynamic`. /// Casting to `Dynamic` just returns a reference to it. /// Returns `None` if the cast fails. + #[inline(always)] pub fn downcast_ref(&self) -> Option<&T> { - if TypeId::of::() == TypeId::of::() { + let type_id = TypeId::of::(); + + if type_id == TypeId::of::() { + return match &self.0 { + Union::Int(value) => ::downcast_ref::(value), + _ => None, + }; + } + #[cfg(not(feature = "no_float"))] + if type_id == TypeId::of::() { + return match &self.0 { + Union::Float(value) => ::downcast_ref::(value), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match &self.0 { + Union::Bool(value) => ::downcast_ref::(value), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match &self.0 { + Union::Str(value) => ::downcast_ref::(value), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match &self.0 { + Union::Str(value) => ::downcast_ref::(value.as_ref()), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match &self.0 { + Union::Char(value) => ::downcast_ref::(value), + _ => None, + }; + } + #[cfg(not(feature = "no_index"))] + if type_id == TypeId::of::() { + return match &self.0 { + Union::Array(value) => ::downcast_ref::(value.as_ref()), + _ => None, + }; + } + #[cfg(not(feature = "no_object"))] + if type_id == TypeId::of::() { + return match &self.0 { + Union::Map(value) => ::downcast_ref::(value.as_ref()), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match &self.0 { + Union::FnPtr(value) => ::downcast_ref::(value), + _ => None, + }; + } + if type_id == TypeId::of::<()>() { + return match &self.0 { + Union::Unit(value) => ::downcast_ref::(value), + _ => None, + }; + } + if type_id == TypeId::of::() { return ::downcast_ref::(self); } match &self.0 { - Union::Unit(value) => ::downcast_ref::(value), - Union::Bool(value) => ::downcast_ref::(value), - Union::Str(value) => ::downcast_ref::(value) - .or_else(|| ::downcast_ref::(value.as_ref())), - Union::Char(value) => ::downcast_ref::(value), - Union::Int(value) => ::downcast_ref::(value), - #[cfg(not(feature = "no_float"))] - Union::Float(value) => ::downcast_ref::(value), - #[cfg(not(feature = "no_index"))] - Union::Array(value) => ::downcast_ref::(value.as_ref()), - #[cfg(not(feature = "no_object"))] - Union::Map(value) => ::downcast_ref::(value.as_ref()), - Union::FnPtr(value) => ::downcast_ref::(value), Union::Variant(value) => value.as_ref().as_ref().as_any().downcast_ref::(), + _ => None, } } /// Get a mutable reference of a specific type to the `Dynamic`. /// Casting to `Dynamic` just returns a mutable reference to it. /// Returns `None` if the cast fails. + #[inline(always)] pub fn downcast_mut(&mut self) -> Option<&mut T> { - if TypeId::of::() == TypeId::of::() { + let type_id = TypeId::of::(); + + if type_id == TypeId::of::() { + return match &mut self.0 { + Union::Int(value) => ::downcast_mut::(value), + _ => None, + }; + } + #[cfg(not(feature = "no_float"))] + if type_id == TypeId::of::() { + return match &mut self.0 { + Union::Float(value) => ::downcast_mut::(value), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match &mut self.0 { + Union::Bool(value) => ::downcast_mut::(value), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match &mut self.0 { + Union::Str(value) => ::downcast_mut::(value), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match &mut self.0 { + Union::Char(value) => ::downcast_mut::(value), + _ => None, + }; + } + #[cfg(not(feature = "no_index"))] + if type_id == TypeId::of::() { + return match &mut self.0 { + Union::Array(value) => ::downcast_mut::(value.as_mut()), + _ => None, + }; + } + #[cfg(not(feature = "no_object"))] + if type_id == TypeId::of::() { + return match &mut self.0 { + Union::Map(value) => ::downcast_mut::(value.as_mut()), + _ => None, + }; + } + if type_id == TypeId::of::() { + return match &mut self.0 { + Union::FnPtr(value) => ::downcast_mut::(value), + _ => None, + }; + } + if type_id == TypeId::of::<()>() { + return match &mut self.0 { + Union::Unit(value) => ::downcast_mut::(value), + _ => None, + }; + } + if type_id == TypeId::of::() { return ::downcast_mut::(self); } match &mut self.0 { - Union::Unit(value) => ::downcast_mut::(value), - Union::Bool(value) => ::downcast_mut::(value), - Union::Str(value) => ::downcast_mut::(value), - Union::Char(value) => ::downcast_mut::(value), - Union::Int(value) => ::downcast_mut::(value), - #[cfg(not(feature = "no_float"))] - Union::Float(value) => ::downcast_mut::(value), - #[cfg(not(feature = "no_index"))] - Union::Array(value) => ::downcast_mut::(value.as_mut()), - #[cfg(not(feature = "no_object"))] - Union::Map(value) => ::downcast_mut::(value.as_mut()), - Union::FnPtr(value) => ::downcast_mut::(value), Union::Variant(value) => value.as_mut().as_mut_any().downcast_mut::(), + _ => None, } } diff --git a/src/unsafe.rs b/src/unsafe.rs index fa5b271f..86c571f1 100644 --- a/src/unsafe.rs +++ b/src/unsafe.rs @@ -12,6 +12,7 @@ use crate::stdlib::{ }; /// Cast a type into another type. +#[inline(always)] pub fn unsafe_try_cast(a: A) -> Option { if TypeId::of::() == a.type_id() { // SAFETY: Just checked we have the right type. We explicitly forget the @@ -28,6 +29,7 @@ pub fn unsafe_try_cast(a: A) -> Option { } /// Cast a Boxed type into another type. +#[inline(always)] pub fn unsafe_cast_box(item: Box) -> Result, Box> { // Only allow casting to the exact same type if TypeId::of::() == TypeId::of::() { @@ -51,6 +53,7 @@ pub fn unsafe_cast_box(item: Box) -> Result, B /// /// Force-casting a local variable's lifetime to the current `Scope`'s larger lifetime saves /// on allocations and string cloning, thus avoids us having to maintain a chain of `Scope`'s. +#[inline] pub fn unsafe_cast_var_name_to_lifetime<'s>(name: &str, state: &State) -> Cow<'s, str> { // If not at global level, we can force-cast if state.scope_level > 0 { diff --git a/src/utils.rs b/src/utils.rs index 01fdd26b..12add69d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -36,11 +36,9 @@ use ahash::AHasher; pub struct StraightHasher(u64); impl Hasher for StraightHasher { - #[inline(always)] fn finish(&self) -> u64 { self.0 } - #[inline] fn write(&mut self, bytes: &[u8]) { let mut key = [0_u8; 8]; key.copy_from_slice(&bytes[..8]); // Panics if fewer than 8 bytes @@ -50,7 +48,6 @@ impl Hasher for StraightHasher { impl StraightHasher { /// Create a `StraightHasher`. - #[inline(always)] pub fn new() -> Self { Self(0) } @@ -63,7 +60,6 @@ pub struct StraightHasherBuilder; impl BuildHasher for StraightHasherBuilder { type Hasher = StraightHasher; - #[inline(always)] fn build_hasher(&self) -> Self::Hasher { StraightHasher::new() } @@ -150,7 +146,6 @@ pub struct StaticVec { const MAX_STATIC_VEC: usize = 4; impl Drop for StaticVec { - #[inline(always)] fn drop(&mut self) { self.clear(); } @@ -233,7 +228,6 @@ impl IntoIterator for StaticVec { impl StaticVec { /// Create a new `StaticVec`. - #[inline(always)] pub fn new() -> Self { Default::default() } @@ -249,7 +243,6 @@ impl StaticVec { self.len = 0; } /// Extract a `MaybeUninit` into a concrete initialized type. - #[inline(always)] fn extract(value: MaybeUninit) -> T { unsafe { value.assume_init() } } @@ -311,7 +304,6 @@ impl StaticVec { ); } /// Is data stored in fixed-size storage? - #[inline(always)] fn is_fixed_storage(&self) -> bool { self.len <= MAX_STATIC_VEC } @@ -418,12 +410,10 @@ impl StaticVec { } } /// Get the number of items in this `StaticVec`. - #[inline(always)] pub fn len(&self) -> usize { self.len } /// Is this `StaticVec` empty? - #[inline(always)] pub fn is_empty(&self) -> bool { self.len == 0 } @@ -664,48 +654,41 @@ pub struct ImmutableString(Shared); impl Deref for ImmutableString { type Target = String; - #[inline(always)] fn deref(&self) -> &Self::Target { &self.0 } } impl AsRef for ImmutableString { - #[inline(always)] fn as_ref(&self) -> &String { &self.0 } } impl Borrow for ImmutableString { - #[inline(always)] fn borrow(&self) -> &str { self.0.as_str() } } impl From<&str> for ImmutableString { - #[inline(always)] fn from(value: &str) -> Self { Self(value.to_string().into()) } } impl From for ImmutableString { - #[inline(always)] fn from(value: String) -> Self { Self(value.into()) } } impl From> for ImmutableString { - #[inline(always)] fn from(value: Box) -> Self { Self(value.into()) } } impl From for String { - #[inline(always)] fn from(value: ImmutableString) -> Self { value.into_owned() } @@ -714,49 +697,42 @@ impl From for String { impl FromStr for ImmutableString { type Err = (); - #[inline(always)] fn from_str(s: &str) -> Result { Ok(Self(s.to_string().into())) } } impl FromIterator for ImmutableString { - #[inline(always)] fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect::().into()) } } impl<'a> FromIterator<&'a char> for ImmutableString { - #[inline(always)] fn from_iter>(iter: T) -> Self { Self(iter.into_iter().cloned().collect::().into()) } } impl<'a> FromIterator<&'a str> for ImmutableString { - #[inline(always)] fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect::().into()) } } impl<'a> FromIterator for ImmutableString { - #[inline(always)] fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect::().into()) } } impl fmt::Display for ImmutableString { - #[inline(always)] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self.0.as_str(), f) } } impl fmt::Debug for ImmutableString { - #[inline(always)] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(self.0.as_str(), f) } @@ -891,7 +867,6 @@ impl Add for &ImmutableString { } impl AddAssign for ImmutableString { - #[inline(always)] fn add_assign(&mut self, rhs: char) { self.make_mut().push(rhs); } @@ -906,7 +881,6 @@ impl ImmutableString { } /// Make sure that the `ImmutableString` is unique (i.e. no other outstanding references). /// Then return a mutable reference to the `String`. - #[inline(always)] pub fn make_mut(&mut self) -> &mut String { shared_make_mut(&mut self.0) }