Use SmartString inside ImmutableString.

This commit is contained in:
Stephen Chung 2021-04-23 19:10:10 +08:00
parent fc782c5563
commit 335ab64a2c
3 changed files with 53 additions and 65 deletions

View File

@ -2,7 +2,7 @@
use crate::fn_native::SendSync; use crate::fn_native::SendSync;
use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast}; 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")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
use std::{ use std::{
@ -900,6 +900,12 @@ impl Dynamic {
.deref() .deref()
.into(); .into();
} }
if TypeId::of::<T>() == TypeId::of::<SmartString>() {
return <dyn Any>::downcast_ref::<SmartString>(&value)
.unwrap()
.clone()
.into();
}
if TypeId::of::<T>() == TypeId::of::<()>() { if TypeId::of::<T>() == TypeId::of::<()>() {
return ().into(); return ().into();
} }
@ -1173,13 +1179,13 @@ impl Dynamic {
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn clone_cast<T: Any + Clone>(&self) -> T { pub fn clone_cast<T: Any + Clone>(&self) -> T {
self.read_lock::<T>().unwrap().clone() self.flatten_clone().cast::<T>()
} }
/// Flatten the [`Dynamic`] and clone it. /// Flatten the [`Dynamic`] and clone it.
/// ///
/// If the [`Dynamic`] is not a shared value, it returns a cloned copy. /// 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)] #[inline(always)]
pub fn flatten_clone(&self) -> Self { pub fn flatten_clone(&self) -> Self {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
@ -1361,7 +1367,7 @@ impl Dynamic {
/// ///
/// Returns [`None`] if the cast fails, or if the value is shared. /// Returns [`None`] if the cast fails, or if the value is shared.
#[inline(always)] #[inline(always)]
pub(crate) fn downcast_ref<T: Any + Clone>(&self) -> Option<&T> { pub(crate) fn downcast_ref<T: Any + Clone + ?Sized>(&self) -> Option<&T> {
// Coded this way in order to maximally leverage potentials for dead-code removal. // Coded this way in order to maximally leverage potentials for dead-code removal.
if TypeId::of::<T>() == TypeId::of::<INT>() { if TypeId::of::<T>() == TypeId::of::<INT>() {
@ -1396,12 +1402,6 @@ impl Dynamic {
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<String>() {
return match &self.0 {
Union::Str(value, _) => <dyn Any>::downcast_ref::<T>(value.as_ref() as &String),
_ => None,
};
}
if TypeId::of::<T>() == TypeId::of::<char>() { if TypeId::of::<T>() == TypeId::of::<char>() {
return match &self.0 { return match &self.0 {
Union::Char(value, _) => <dyn Any>::downcast_ref::<T>(value), Union::Char(value, _) => <dyn Any>::downcast_ref::<T>(value),
@ -1720,7 +1720,7 @@ impl From<&ImmutableString> for Dynamic {
value.clone().into() value.clone().into()
} }
} }
#[cfg(not(feature = "no_smartstring"))] #[cfg(not(feature = "no_smartstring_for_identifier"))]
impl From<&crate::Identifier> for Dynamic { impl From<&crate::Identifier> for Dynamic {
#[inline(always)] #[inline(always)]
fn from(value: &crate::Identifier) -> Self { fn from(value: &crate::Identifier) -> Self {

View File

@ -140,11 +140,11 @@ pub use utils::ImmutableString;
/// An identifier in Rhai. [`SmartString`](https://crates.io/crates/smartstring) is used because most /// 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. /// identifiers are ASCII and short, fewer than 23 characters, so they can be stored inline.
#[cfg(not(feature = "no_smartstring"))] #[cfg(not(feature = "no_smartstring_for_identifier"))]
pub type Identifier = smartstring::SmartString<smartstring::Compact>; pub type Identifier = SmartString;
/// An identifier in Rhai. /// An identifier in Rhai.
#[cfg(feature = "no_smartstring")] #[cfg(feature = "no_smartstring_for_identifier")]
pub type Identifier = ImmutableString; pub type Identifier = ImmutableString;
/// A trait to enable registering Rust functions. /// A trait to enable registering Rust functions.
@ -305,6 +305,12 @@ type StaticVec<T> = smallvec::SmallVec<[T; 4]>;
#[cfg(feature = "internals")] #[cfg(feature = "internals")]
pub type StaticVec<T> = smallvec::SmallVec<[T; 4]>; pub type StaticVec<T> = smallvec::SmallVec<[T; 4]>;
#[cfg(not(feature = "internals"))]
pub(crate) type SmartString = smartstring::SmartString<smartstring::Compact>;
#[cfg(feature = "internals")]
pub type SmartString = smartstring::SmartString<smartstring::Compact>;
// Compiler guards against mutually-exclusive feature flags // Compiler guards against mutually-exclusive feature flags
#[cfg(feature = "no_float")] #[cfg(feature = "no_float")]

View File

@ -1,7 +1,7 @@
//! Module containing various utility types and functions. //! Module containing various utility types and functions.
use crate::fn_native::{shared_make_mut, shared_take}; use crate::fn_native::{shared_make_mut, shared_take};
use crate::{Identifier, Shared}; use crate::{Identifier, Shared, SmartString};
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
use std::{ use std::{
@ -141,10 +141,10 @@ pub(crate) fn combine_hashes(a: u64, b: u64) -> u64 {
/// assert_eq!(s, "hello, world!"); /// assert_eq!(s, "hello, world!");
/// ``` /// ```
#[derive(Clone, Eq, Ord, Hash, Default)] #[derive(Clone, Eq, Ord, Hash, Default)]
pub struct ImmutableString(Shared<String>); pub struct ImmutableString(Shared<SmartString>);
impl Deref for ImmutableString { impl Deref for ImmutableString {
type Target = String; type Target = SmartString;
#[inline(always)] #[inline(always)]
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@ -152,9 +152,9 @@ impl Deref for ImmutableString {
} }
} }
impl AsRef<String> for ImmutableString { impl AsRef<SmartString> for ImmutableString {
#[inline(always)] #[inline(always)]
fn as_ref(&self) -> &String { fn as_ref(&self) -> &SmartString {
&self.0 &self.0
} }
} }
@ -166,9 +166,9 @@ impl AsRef<str> for ImmutableString {
} }
} }
impl Borrow<String> for ImmutableString { impl Borrow<SmartString> for ImmutableString {
#[inline(always)] #[inline(always)]
fn borrow(&self) -> &String { fn borrow(&self) -> &SmartString {
&self.0 &self.0
} }
} }
@ -183,33 +183,31 @@ impl Borrow<str> for ImmutableString {
impl From<&str> for ImmutableString { impl From<&str> for ImmutableString {
#[inline(always)] #[inline(always)]
fn from(value: &str) -> Self { fn from(value: &str) -> Self {
Self(value.to_string().into()) Self(Into::<SmartString>::into(value).into())
} }
} }
impl From<&String> for ImmutableString { impl From<&String> for ImmutableString {
#[inline(always)] #[inline(always)]
fn from(value: &String) -> Self { fn from(value: &String) -> Self {
Self(value.to_string().into()) Self(Into::<SmartString>::into(value).into())
} }
} }
impl From<String> for ImmutableString { impl From<String> for ImmutableString {
#[inline(always)] #[inline(always)]
fn from(value: String) -> Self { fn from(value: String) -> Self {
Self(Into::<SmartString>::into(value).into())
}
}
impl From<SmartString> for ImmutableString {
#[inline(always)]
fn from(value: SmartString) -> Self {
Self(value.into()) Self(value.into())
} }
} }
impl From<ImmutableString> for SmartString {
impl From<Box<String>> for ImmutableString {
#[inline(always)] #[inline(always)]
fn from(value: Box<String>) -> Self { fn from(mut value: ImmutableString) -> Self {
Self(value.into()) std::mem::take(shared_make_mut(&mut value.0))
}
}
impl From<ImmutableString> for String {
#[inline(always)]
fn from(value: ImmutableString) -> Self {
value.into_owned()
} }
} }
@ -218,35 +216,35 @@ impl FromStr for ImmutableString {
#[inline(always)] #[inline(always)]
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(s.to_string().into())) Ok(Self(Into::<SmartString>::into(s).into()))
} }
} }
impl FromIterator<char> for ImmutableString { impl FromIterator<char> for ImmutableString {
#[inline(always)] #[inline(always)]
fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
Self(iter.into_iter().collect::<String>().into()) Self(iter.into_iter().collect::<SmartString>().into())
} }
} }
impl<'a> FromIterator<&'a char> for ImmutableString { impl<'a> FromIterator<&'a char> for ImmutableString {
#[inline(always)] #[inline(always)]
fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
Self(iter.into_iter().cloned().collect::<String>().into()) Self(iter.into_iter().cloned().collect::<SmartString>().into())
} }
} }
impl<'a> FromIterator<&'a str> for ImmutableString { impl<'a> FromIterator<&'a str> for ImmutableString {
#[inline(always)] #[inline(always)]
fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
Self(iter.into_iter().collect::<String>().into()) Self(iter.into_iter().collect::<SmartString>().into())
} }
} }
impl<'a> FromIterator<String> for ImmutableString { impl<'a> FromIterator<String> for ImmutableString {
#[inline(always)] #[inline(always)]
fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
Self(iter.into_iter().collect::<String>().into()) Self(iter.into_iter().collect::<SmartString>().into())
} }
} }
@ -466,7 +464,7 @@ impl SubAssign<&ImmutableString> for ImmutableString {
if self.is_empty() { if self.is_empty() {
self.0 = rhs.0.clone(); self.0 = rhs.0.clone();
} else { } else {
self.0 = self.replace(rhs.as_str(), "").into(); self.0 = Into::<SmartString>::into(self.replace(rhs.as_str(), "")).into();
} }
} }
} }
@ -479,7 +477,7 @@ impl SubAssign<ImmutableString> for ImmutableString {
if self.is_empty() { if self.is_empty() {
self.0 = rhs.0; self.0 = rhs.0;
} else { } else {
self.0 = self.replace(rhs.as_str(), "").into(); self.0 = Into::<SmartString>::into(self.replace(rhs.as_str(), "")).into();
} }
} }
} }
@ -518,7 +516,7 @@ impl Sub<String> for &ImmutableString {
impl SubAssign<String> for ImmutableString { impl SubAssign<String> for ImmutableString {
#[inline(always)] #[inline(always)]
fn sub_assign(&mut self, rhs: String) { fn sub_assign(&mut self, rhs: String) {
self.0 = self.replace(&rhs, "").into(); self.0 = Into::<SmartString>::into(self.replace(&rhs, "")).into();
} }
} }
@ -543,7 +541,7 @@ impl Sub<char> for &ImmutableString {
impl SubAssign<char> for ImmutableString { impl SubAssign<char> for ImmutableString {
#[inline(always)] #[inline(always)]
fn sub_assign(&mut self, rhs: char) { fn sub_assign(&mut self, rhs: char) {
self.0 = self.replace(rhs, "").into(); self.0 = Into::<SmartString>::into(self.replace(rhs, "")).into();
} }
} }
@ -588,34 +586,18 @@ impl PartialOrd<ImmutableString> for String {
} }
} }
#[cfg(not(feature = "no_smartstring"))]
impl From<ImmutableString> for Identifier {
#[inline(always)]
fn from(value: ImmutableString) -> Self {
value.into_owned().into()
}
}
#[cfg(not(feature = "no_smartstring"))]
impl From<Identifier> for ImmutableString {
#[inline(always)]
fn from(value: Identifier) -> Self {
value.to_string().into()
}
}
impl ImmutableString { impl ImmutableString {
/// Consume the [`ImmutableString`] and convert it into a [`String`]. /// Consume the [`ImmutableString`] and convert it into a [`String`].
/// If there are other references to the same string, a cloned copy is returned. /// If there are other references to the same string, a cloned copy is returned.
#[inline(always)] #[inline(always)]
pub fn into_owned(mut self) -> String { pub fn into_owned(mut self) -> String {
self.make_mut(); // Make sure it is unique reference 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). /// 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)] #[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) shared_make_mut(&mut self.0)
} }
} }
@ -630,17 +612,17 @@ impl ImmutableString {
/// yet interned. /// yet interned.
#[derive(Debug, Clone, Default, Hash)] #[derive(Debug, Clone, Default, Hash)]
pub struct IdentifierBuilder( pub struct IdentifierBuilder(
#[cfg(feature = "no_smartstring")] std::collections::BTreeSet<Identifier>, #[cfg(feature = "no_smartstring_for_identifier")] std::collections::BTreeSet<Identifier>,
); );
impl IdentifierBuilder { impl IdentifierBuilder {
/// Get an identifier from a text string. /// Get an identifier from a text string.
#[inline(always)] #[inline(always)]
pub fn get(&mut self, text: impl AsRef<str> + Into<Identifier>) -> Identifier { pub fn get(&mut self, text: impl AsRef<str> + Into<Identifier>) -> Identifier {
#[cfg(not(feature = "no_smartstring"))] #[cfg(not(feature = "no_smartstring_for_identifier"))]
return text.as_ref().into(); 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(|| { return self.0.get(text.as_ref()).cloned().unwrap_or_else(|| {
let s: Identifier = text.into(); let s: Identifier = text.into();
self.0.insert(s.clone()); self.0.insert(s.clone());