Add no_smartstring to disable using SmartString.
This commit is contained in:
parent
2c0215ea3f
commit
d230f448c0
@ -13,6 +13,7 @@ New features
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
* Each `Dynamic` value can now contain arbitrary data (type `i16`) in the form of a _tag_. This is to use up otherwise wasted space in the `Dynamic` type.
|
* Each `Dynamic` value can now contain arbitrary data (type `i16`) in the form of a _tag_. This is to use up otherwise wasted space in the `Dynamic` type.
|
||||||
|
* A new internal feature `no_smartstring` to turn off `SmartString` for those rare cases that it is needed.
|
||||||
|
|
||||||
|
|
||||||
Version 0.20.1
|
Version 0.20.1
|
||||||
|
@ -48,6 +48,9 @@ no_std = ["no-std-compat", "num-traits/libm", "core-error", "libm", "ahash/compi
|
|||||||
wasm-bindgen = ["instant/wasm-bindgen"]
|
wasm-bindgen = ["instant/wasm-bindgen"]
|
||||||
stdweb = ["instant/stdweb"]
|
stdweb = ["instant/stdweb"]
|
||||||
|
|
||||||
|
# internal feature flags - volatile
|
||||||
|
no_smartstring = [] # Do not use SmartString
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = "fat"
|
lto = "fat"
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
@ -2096,7 +2096,10 @@ mod tests {
|
|||||||
assert_eq!(size_of::<Option<ast::Expr>>(), 16);
|
assert_eq!(size_of::<Option<ast::Expr>>(), 16);
|
||||||
assert_eq!(size_of::<ast::Stmt>(), 32);
|
assert_eq!(size_of::<ast::Stmt>(), 32);
|
||||||
assert_eq!(size_of::<Option<ast::Stmt>>(), 32);
|
assert_eq!(size_of::<Option<ast::Stmt>>(), 32);
|
||||||
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
assert_eq!(size_of::<FnPtr>(), 96);
|
assert_eq!(size_of::<FnPtr>(), 96);
|
||||||
|
#[cfg(feature = "no_smartstring")]
|
||||||
|
assert_eq!(size_of::<FnPtr>(), 80);
|
||||||
assert_eq!(size_of::<Scope>(), 288);
|
assert_eq!(size_of::<Scope>(), 288);
|
||||||
assert_eq!(size_of::<LexError>(), 56);
|
assert_eq!(size_of::<LexError>(), 56);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -106,7 +106,7 @@ fn main() {
|
|||||||
.compile(&contents)
|
.compile(&contents)
|
||||||
.map_err(|err| err.into())
|
.map_err(|err| err.into())
|
||||||
.and_then(|mut ast| {
|
.and_then(|mut ast| {
|
||||||
ast.set_source(filename.to_string_lossy());
|
ast.set_source(filename.to_string_lossy().to_string());
|
||||||
Module::eval_ast_as_new(Default::default(), &ast, &engine)
|
Module::eval_ast_as_new(Default::default(), &ast, &engine)
|
||||||
}) {
|
}) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -85,7 +85,7 @@ fn main() {
|
|||||||
.compile(contents)
|
.compile(contents)
|
||||||
.map_err(|err| Box::new(err.into()) as Box<EvalAltResult>)
|
.map_err(|err| Box::new(err.into()) as Box<EvalAltResult>)
|
||||||
.and_then(|mut ast| {
|
.and_then(|mut ast| {
|
||||||
ast.set_source(filename.to_string_lossy());
|
ast.set_source(filename.to_string_lossy().to_string());
|
||||||
engine.consume_ast(&ast)
|
engine.consume_ast(&ast)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
@ -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, SmartString, INT};
|
use crate::{FnPtr, ImmutableString, INT};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
@ -973,12 +973,6 @@ 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();
|
||||||
}
|
}
|
||||||
@ -1803,7 +1797,7 @@ impl From<&ImmutableString> for Dynamic {
|
|||||||
value.clone().into()
|
value.clone().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_smartstring_for_identifier"))]
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
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 {
|
||||||
|
@ -923,7 +923,7 @@ impl Engine {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
engine.global_namespace.set_internal(true);
|
engine.global_namespace.internal = true;
|
||||||
engine.register_global_module(StandardPackage::new().as_shared_module());
|
engine.register_global_module(StandardPackage::new().as_shared_module());
|
||||||
|
|
||||||
engine
|
engine
|
||||||
@ -980,7 +980,7 @@ impl Engine {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
engine.global_namespace.set_internal(true);
|
engine.global_namespace.internal = true;
|
||||||
|
|
||||||
engine
|
engine
|
||||||
}
|
}
|
||||||
@ -2610,18 +2610,15 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
if entry_type == AccessMode::ReadOnly && lib.iter().any(|&m| !m.is_empty()) {
|
if entry_type == AccessMode::ReadOnly && lib.iter().any(|&m| !m.is_empty()) {
|
||||||
let global = if let Some(index) = mods.find(KEYWORD_GLOBAL) {
|
let global = if let Some(index) = mods.find(KEYWORD_GLOBAL) {
|
||||||
let global = mods.get_mut(index).unwrap();
|
match mods.get_mut(index).unwrap() {
|
||||||
|
m if m.internal => Some(m),
|
||||||
if !global.is_internal() {
|
_ => None,
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(global)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Create automatic global module
|
// Create automatic global module
|
||||||
let mut global = Module::new();
|
let mut global = Module::new();
|
||||||
global.set_internal(true);
|
global.internal = true;
|
||||||
mods.push(crate::engine::KEYWORD_GLOBAL, global);
|
mods.push(KEYWORD_GLOBAL, global);
|
||||||
Some(mods.get_mut(mods.len() - 1).unwrap())
|
Some(mods.get_mut(mods.len() - 1).unwrap())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ use crate::engine::Imports;
|
|||||||
use crate::plugin::PluginFunction;
|
use crate::plugin::PluginFunction;
|
||||||
use crate::token::is_valid_identifier;
|
use crate::token::is_valid_identifier;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, Identifier, ImmutableString, Module,
|
calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, Identifier, Module, Position,
|
||||||
Position, RhaiResult, StaticVec,
|
RhaiResult, StaticVec,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -367,16 +367,17 @@ impl TryFrom<Identifier> for FnPtr {
|
|||||||
if is_valid_identifier(value.chars()) {
|
if is_valid_identifier(value.chars()) {
|
||||||
Ok(Self(value, Default::default()))
|
Ok(Self(value, Default::default()))
|
||||||
} else {
|
} else {
|
||||||
EvalAltResult::ErrorFunctionNotFound(value.into(), Position::NONE).into()
|
EvalAltResult::ErrorFunctionNotFound(value.to_string(), Position::NONE).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<ImmutableString> for FnPtr {
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
|
impl TryFrom<crate::ImmutableString> for FnPtr {
|
||||||
type Error = Box<EvalAltResult>;
|
type Error = Box<EvalAltResult>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn try_from(value: ImmutableString) -> Result<Self, Self::Error> {
|
fn try_from(value: crate::ImmutableString) -> Result<Self, Self::Error> {
|
||||||
let s: Identifier = value.into();
|
let s: Identifier = value.into();
|
||||||
Self::try_from(s)
|
Self::try_from(s)
|
||||||
}
|
}
|
||||||
|
@ -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_for_identifier"))]
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
pub type Identifier = SmartString;
|
pub type Identifier = SmartString;
|
||||||
|
|
||||||
/// An identifier in Rhai.
|
/// An identifier in Rhai.
|
||||||
#[cfg(feature = "no_smartstring_for_identifier")]
|
#[cfg(feature = "no_smartstring")]
|
||||||
pub type Identifier = ImmutableString;
|
pub type Identifier = ImmutableString;
|
||||||
|
|
||||||
/// A trait to enable registering Rust functions.
|
/// A trait to enable registering Rust functions.
|
||||||
@ -306,9 +306,14 @@ type StaticVec<T> = smallvec::SmallVec<[T; 4]>;
|
|||||||
pub type StaticVec<T> = smallvec::SmallVec<[T; 4]>;
|
pub type StaticVec<T> = smallvec::SmallVec<[T; 4]>;
|
||||||
|
|
||||||
#[cfg(not(feature = "internals"))]
|
#[cfg(not(feature = "internals"))]
|
||||||
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
pub(crate) type SmartString = smartstring::SmartString<smartstring::Compact>;
|
pub(crate) type SmartString = smartstring::SmartString<smartstring::Compact>;
|
||||||
|
|
||||||
|
#[cfg(feature = "no_smartstring")]
|
||||||
|
pub(crate) type SmartString = String;
|
||||||
|
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
pub type SmartString = smartstring::SmartString<smartstring::Compact>;
|
pub type SmartString = smartstring::SmartString<smartstring::Compact>;
|
||||||
|
|
||||||
// Compiler guards against mutually-exclusive feature flags
|
// Compiler guards against mutually-exclusive feature flags
|
||||||
|
@ -129,7 +129,7 @@ pub struct Module {
|
|||||||
/// ID identifying the module.
|
/// ID identifying the module.
|
||||||
id: Option<Identifier>,
|
id: Option<Identifier>,
|
||||||
/// Is this module internal?
|
/// Is this module internal?
|
||||||
internal: bool,
|
pub(crate) internal: bool,
|
||||||
/// Sub-modules.
|
/// Sub-modules.
|
||||||
modules: BTreeMap<Identifier, Shared<Module>>,
|
modules: BTreeMap<Identifier, Shared<Module>>,
|
||||||
/// [`Module`] variables.
|
/// [`Module`] variables.
|
||||||
@ -309,20 +309,6 @@ impl Module {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the [`Module`] internal?
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[inline(always)]
|
|
||||||
pub(crate) fn is_internal(&self) -> bool {
|
|
||||||
self.internal
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the internal status of the [`Module`].
|
|
||||||
#[inline(always)]
|
|
||||||
pub(crate) fn set_internal(&mut self, value: bool) -> &mut Self {
|
|
||||||
self.internal = value;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Is the [`Module`] empty?
|
/// Is the [`Module`] empty?
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -476,10 +462,7 @@ impl Module {
|
|||||||
/// If there is an existing function of the same name and number of arguments, it is replaced.
|
/// If there is an existing function of the same name and number of arguments, it is replaced.
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn set_script_fn(
|
pub fn set_script_fn(&mut self, fn_def: impl Into<Shared<crate::ast::ScriptFnDef>>) -> u64 {
|
||||||
&mut self,
|
|
||||||
fn_def: impl Into<Shared<crate::ast::ScriptFnDef>>,
|
|
||||||
) -> u64 {
|
|
||||||
let fn_def = fn_def.into();
|
let fn_def = fn_def.into();
|
||||||
|
|
||||||
// None + function name + number of arguments.
|
// None + function name + number of arguments.
|
||||||
|
15
src/utils.rs
15
src/utils.rs
@ -198,6 +198,7 @@ impl From<String> for ImmutableString {
|
|||||||
Self(Into::<SmartString>::into(value).into())
|
Self(Into::<SmartString>::into(value).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
impl From<SmartString> for ImmutableString {
|
impl From<SmartString> for ImmutableString {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: SmartString) -> Self {
|
fn from(value: SmartString) -> Self {
|
||||||
@ -248,6 +249,14 @@ impl<'a> FromIterator<String> for ImmutableString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
|
impl<'a> FromIterator<SmartString> for ImmutableString {
|
||||||
|
#[inline(always)]
|
||||||
|
fn from_iter<T: IntoIterator<Item = SmartString>>(iter: T) -> Self {
|
||||||
|
Self(iter.into_iter().collect::<SmartString>().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for ImmutableString {
|
impl fmt::Display for ImmutableString {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
@ -618,17 +627,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_for_identifier")] std::collections::BTreeSet<Identifier>,
|
#[cfg(feature = "no_smartstring")] 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_for_identifier"))]
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
return text.as_ref().into();
|
return text.as_ref().into();
|
||||||
|
|
||||||
#[cfg(feature = "no_smartstring_for_identifier")]
|
#[cfg(feature = "no_smartstring")]
|
||||||
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…
Reference in New Issue
Block a user