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::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::<T>() == TypeId::of::<SmartString>() {
return <dyn Any>::downcast_ref::<SmartString>(&value)
.unwrap()
.clone()
.into();
}
if TypeId::of::<T>() == TypeId::of::<()>() {
return ().into();
}
@ -1173,13 +1179,13 @@ impl Dynamic {
/// ```
#[inline(always)]
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.
///
/// 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<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.
if TypeId::of::<T>() == TypeId::of::<INT>() {
@ -1396,12 +1402,6 @@ impl Dynamic {
_ => 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>() {
return match &self.0 {
Union::Char(value, _) => <dyn Any>::downcast_ref::<T>(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 {

View File

@ -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<smartstring::Compact>;
#[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<T> = smallvec::SmallVec<[T; 4]>;
#[cfg(feature = "internals")]
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
#[cfg(feature = "no_float")]

View File

@ -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<String>);
pub struct ImmutableString(Shared<SmartString>);
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<String> for ImmutableString {
impl AsRef<SmartString> for ImmutableString {
#[inline(always)]
fn as_ref(&self) -> &String {
fn as_ref(&self) -> &SmartString {
&self.0
}
}
@ -166,9 +166,9 @@ impl AsRef<str> for ImmutableString {
}
}
impl Borrow<String> for ImmutableString {
impl Borrow<SmartString> for ImmutableString {
#[inline(always)]
fn borrow(&self) -> &String {
fn borrow(&self) -> &SmartString {
&self.0
}
}
@ -183,33 +183,31 @@ impl Borrow<str> for ImmutableString {
impl From<&str> for ImmutableString {
#[inline(always)]
fn from(value: &str) -> Self {
Self(value.to_string().into())
Self(Into::<SmartString>::into(value).into())
}
}
impl From<&String> for ImmutableString {
#[inline(always)]
fn from(value: &String) -> Self {
Self(value.to_string().into())
Self(Into::<SmartString>::into(value).into())
}
}
impl From<String> for ImmutableString {
#[inline(always)]
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())
}
}
impl From<Box<String>> for ImmutableString {
impl From<ImmutableString> for SmartString {
#[inline(always)]
fn from(value: Box<String>) -> Self {
Self(value.into())
}
}
impl From<ImmutableString> 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<Self, Self::Err> {
Ok(Self(s.to_string().into()))
Ok(Self(Into::<SmartString>::into(s).into()))
}
}
impl FromIterator<char> for ImmutableString {
#[inline(always)]
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 {
#[inline(always)]
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 {
#[inline(always)]
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 {
#[inline(always)]
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() {
self.0 = rhs.0.clone();
} 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() {
self.0 = rhs.0;
} 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 {
#[inline(always)]
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 {
#[inline(always)]
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 {
/// 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<Identifier>,
#[cfg(feature = "no_smartstring_for_identifier")] std::collections::BTreeSet<Identifier>,
);
impl IdentifierBuilder {
/// Get an identifier from a text string.
#[inline(always)]
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();
#[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());