diff --git a/src/dynamic.rs b/src/dynamic.rs index 19b71823..2414d31f 100644 --- a/src/dynamic.rs +++ b/src/dynamic.rs @@ -2,7 +2,7 @@ use crate::fn_native::SendSync; use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast}; -use crate::{FnPtr, ImmutableString, INT}; +use crate::{FnPtr, ImmutableString, SmartString, INT}; #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{ @@ -900,6 +900,12 @@ impl Dynamic { .deref() .into(); } + if TypeId::of::() == TypeId::of::() { + return ::downcast_ref::(&value) + .unwrap() + .clone() + .into(); + } if TypeId::of::() == TypeId::of::<()>() { return ().into(); } @@ -1173,13 +1179,13 @@ impl Dynamic { /// ``` #[inline(always)] pub fn clone_cast(&self) -> T { - self.read_lock::().unwrap().clone() + self.flatten_clone().cast::() } /// Flatten the [`Dynamic`] and clone it. /// /// If the [`Dynamic`] is not a shared value, it returns a cloned copy. /// - /// If the [`Dynamic`] is a shared value, it a cloned copy of the shared value. + /// If the [`Dynamic`] is a shared value, it returns a cloned copy of the shared value. #[inline(always)] pub fn flatten_clone(&self) -> Self { #[cfg(not(feature = "no_closure"))] @@ -1361,7 +1367,7 @@ impl Dynamic { /// /// Returns [`None`] if the cast fails, or if the value is shared. #[inline(always)] - pub(crate) fn downcast_ref(&self) -> Option<&T> { + pub(crate) fn downcast_ref(&self) -> Option<&T> { // Coded this way in order to maximally leverage potentials for dead-code removal. if TypeId::of::() == TypeId::of::() { @@ -1396,12 +1402,6 @@ impl Dynamic { _ => None, }; } - if TypeId::of::() == TypeId::of::() { - return match &self.0 { - Union::Str(value, _) => ::downcast_ref::(value.as_ref() as &String), - _ => None, - }; - } if TypeId::of::() == TypeId::of::() { return match &self.0 { Union::Char(value, _) => ::downcast_ref::(value), @@ -1720,7 +1720,7 @@ impl From<&ImmutableString> for Dynamic { value.clone().into() } } -#[cfg(not(feature = "no_smartstring"))] +#[cfg(not(feature = "no_smartstring_for_identifier"))] impl From<&crate::Identifier> for Dynamic { #[inline(always)] fn from(value: &crate::Identifier) -> Self { diff --git a/src/lib.rs b/src/lib.rs index 6ddb7aab..4b8633bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -140,11 +140,11 @@ pub use utils::ImmutableString; /// An identifier in Rhai. [`SmartString`](https://crates.io/crates/smartstring) is used because most /// identifiers are ASCII and short, fewer than 23 characters, so they can be stored inline. -#[cfg(not(feature = "no_smartstring"))] -pub type Identifier = smartstring::SmartString; +#[cfg(not(feature = "no_smartstring_for_identifier"))] +pub type Identifier = SmartString; /// An identifier in Rhai. -#[cfg(feature = "no_smartstring")] +#[cfg(feature = "no_smartstring_for_identifier")] pub type Identifier = ImmutableString; /// A trait to enable registering Rust functions. @@ -305,6 +305,12 @@ type StaticVec = smallvec::SmallVec<[T; 4]>; #[cfg(feature = "internals")] pub type StaticVec = smallvec::SmallVec<[T; 4]>; +#[cfg(not(feature = "internals"))] +pub(crate) type SmartString = smartstring::SmartString; + +#[cfg(feature = "internals")] +pub type SmartString = smartstring::SmartString; + // Compiler guards against mutually-exclusive feature flags #[cfg(feature = "no_float")] diff --git a/src/utils.rs b/src/utils.rs index 6b73aa64..98e381c5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,7 @@ //! Module containing various utility types and functions. use crate::fn_native::{shared_make_mut, shared_take}; -use crate::{Identifier, Shared}; +use crate::{Identifier, Shared, SmartString}; #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{ @@ -141,10 +141,10 @@ pub(crate) fn combine_hashes(a: u64, b: u64) -> u64 { /// assert_eq!(s, "hello, world!"); /// ``` #[derive(Clone, Eq, Ord, Hash, Default)] -pub struct ImmutableString(Shared); +pub struct ImmutableString(Shared); impl Deref for ImmutableString { - type Target = String; + type Target = SmartString; #[inline(always)] fn deref(&self) -> &Self::Target { @@ -152,9 +152,9 @@ impl Deref for ImmutableString { } } -impl AsRef for ImmutableString { +impl AsRef for ImmutableString { #[inline(always)] - fn as_ref(&self) -> &String { + fn as_ref(&self) -> &SmartString { &self.0 } } @@ -166,9 +166,9 @@ impl AsRef for ImmutableString { } } -impl Borrow for ImmutableString { +impl Borrow for ImmutableString { #[inline(always)] - fn borrow(&self) -> &String { + fn borrow(&self) -> &SmartString { &self.0 } } @@ -183,33 +183,31 @@ impl Borrow for ImmutableString { impl From<&str> for ImmutableString { #[inline(always)] fn from(value: &str) -> Self { - Self(value.to_string().into()) + Self(Into::::into(value).into()) } } impl From<&String> for ImmutableString { #[inline(always)] fn from(value: &String) -> Self { - Self(value.to_string().into()) + Self(Into::::into(value).into()) } } impl From for ImmutableString { #[inline(always)] fn from(value: String) -> Self { + Self(Into::::into(value).into()) + } +} +impl From for ImmutableString { + #[inline(always)] + fn from(value: SmartString) -> Self { Self(value.into()) } } - -impl From> for ImmutableString { +impl From for SmartString { #[inline(always)] - fn from(value: Box) -> Self { - Self(value.into()) - } -} - -impl From for String { - #[inline(always)] - fn from(value: ImmutableString) -> Self { - value.into_owned() + fn from(mut value: ImmutableString) -> Self { + std::mem::take(shared_make_mut(&mut value.0)) } } @@ -218,35 +216,35 @@ impl FromStr for ImmutableString { #[inline(always)] fn from_str(s: &str) -> Result { - Ok(Self(s.to_string().into())) + Ok(Self(Into::::into(s).into())) } } impl FromIterator for ImmutableString { #[inline(always)] fn from_iter>(iter: T) -> Self { - Self(iter.into_iter().collect::().into()) + 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()) + 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()) + 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()) + Self(iter.into_iter().collect::().into()) } } @@ -466,7 +464,7 @@ impl SubAssign<&ImmutableString> for ImmutableString { if self.is_empty() { self.0 = rhs.0.clone(); } else { - self.0 = self.replace(rhs.as_str(), "").into(); + self.0 = Into::::into(self.replace(rhs.as_str(), "")).into(); } } } @@ -479,7 +477,7 @@ impl SubAssign for ImmutableString { if self.is_empty() { self.0 = rhs.0; } else { - self.0 = self.replace(rhs.as_str(), "").into(); + self.0 = Into::::into(self.replace(rhs.as_str(), "")).into(); } } } @@ -518,7 +516,7 @@ impl Sub for &ImmutableString { impl SubAssign for ImmutableString { #[inline(always)] fn sub_assign(&mut self, rhs: String) { - self.0 = self.replace(&rhs, "").into(); + self.0 = Into::::into(self.replace(&rhs, "")).into(); } } @@ -543,7 +541,7 @@ impl Sub for &ImmutableString { impl SubAssign for ImmutableString { #[inline(always)] fn sub_assign(&mut self, rhs: char) { - self.0 = self.replace(rhs, "").into(); + self.0 = Into::::into(self.replace(rhs, "")).into(); } } @@ -588,34 +586,18 @@ impl PartialOrd for String { } } -#[cfg(not(feature = "no_smartstring"))] -impl From for Identifier { - #[inline(always)] - fn from(value: ImmutableString) -> Self { - value.into_owned().into() - } -} - -#[cfg(not(feature = "no_smartstring"))] -impl From for ImmutableString { - #[inline(always)] - fn from(value: Identifier) -> Self { - value.to_string().into() - } -} - impl ImmutableString { /// Consume the [`ImmutableString`] and convert it into a [`String`]. /// If there are other references to the same string, a cloned copy is returned. #[inline(always)] pub fn into_owned(mut self) -> String { self.make_mut(); // Make sure it is unique reference - shared_take(self.0) // Should succeed + shared_take(self.0).into() // Should succeed } /// Make sure that the [`ImmutableString`] is unique (i.e. no other outstanding references). - /// Then return a mutable reference to the [`String`]. + /// Then return a mutable reference to the [`SmartString`]. #[inline(always)] - pub fn make_mut(&mut self) -> &mut String { + pub(crate) fn make_mut(&mut self) -> &mut SmartString { shared_make_mut(&mut self.0) } } @@ -630,17 +612,17 @@ impl ImmutableString { /// yet interned. #[derive(Debug, Clone, Default, Hash)] pub struct IdentifierBuilder( - #[cfg(feature = "no_smartstring")] std::collections::BTreeSet, + #[cfg(feature = "no_smartstring_for_identifier")] std::collections::BTreeSet, ); impl IdentifierBuilder { /// Get an identifier from a text string. #[inline(always)] pub fn get(&mut self, text: impl AsRef + Into) -> Identifier { - #[cfg(not(feature = "no_smartstring"))] + #[cfg(not(feature = "no_smartstring_for_identifier"))] return text.as_ref().into(); - #[cfg(feature = "no_smartstring")] + #[cfg(feature = "no_smartstring_for_identifier")] return self.0.get(text.as_ref()).cloned().unwrap_or_else(|| { let s: Identifier = text.into(); self.0.insert(s.clone());