Use SmartString inside ImmutableString.
This commit is contained in:
parent
fc782c5563
commit
335ab64a2c
@ -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 {
|
||||||
|
12
src/lib.rs
12
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
|
/// 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")]
|
||||||
|
84
src/utils.rs
84
src/utils.rs
@ -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());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user