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.
|
||||
* A new internal feature `no_smartstring` to turn off `SmartString` for those rare cases that it is needed.
|
||||
|
||||
|
||||
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"]
|
||||
stdweb = ["instant/stdweb"]
|
||||
|
||||
# internal feature flags - volatile
|
||||
no_smartstring = [] # Do not use SmartString
|
||||
|
||||
[profile.release]
|
||||
lto = "fat"
|
||||
codegen-units = 1
|
||||
|
@ -2096,7 +2096,10 @@ mod tests {
|
||||
assert_eq!(size_of::<Option<ast::Expr>>(), 16);
|
||||
assert_eq!(size_of::<ast::Stmt>(), 32);
|
||||
assert_eq!(size_of::<Option<ast::Stmt>>(), 32);
|
||||
#[cfg(not(feature = "no_smartstring"))]
|
||||
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::<LexError>(), 56);
|
||||
assert_eq!(
|
||||
|
@ -106,7 +106,7 @@ fn main() {
|
||||
.compile(&contents)
|
||||
.map_err(|err| err.into())
|
||||
.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)
|
||||
}) {
|
||||
Err(err) => {
|
||||
|
@ -85,7 +85,7 @@ fn main() {
|
||||
.compile(contents)
|
||||
.map_err(|err| Box::new(err.into()) as Box<EvalAltResult>)
|
||||
.and_then(|mut ast| {
|
||||
ast.set_source(filename.to_string_lossy());
|
||||
ast.set_source(filename.to_string_lossy().to_string());
|
||||
engine.consume_ast(&ast)
|
||||
})
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::fn_native::SendSync;
|
||||
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")]
|
||||
use std::prelude::v1::*;
|
||||
use std::{
|
||||
@ -973,12 +973,6 @@ 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();
|
||||
}
|
||||
@ -1803,7 +1797,7 @@ impl From<&ImmutableString> for Dynamic {
|
||||
value.clone().into()
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "no_smartstring_for_identifier"))]
|
||||
#[cfg(not(feature = "no_smartstring"))]
|
||||
impl From<&crate::Identifier> for Dynamic {
|
||||
#[inline(always)]
|
||||
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
|
||||
@ -980,7 +980,7 @@ impl Engine {
|
||||
},
|
||||
};
|
||||
|
||||
engine.global_namespace.set_internal(true);
|
||||
engine.global_namespace.internal = true;
|
||||
|
||||
engine
|
||||
}
|
||||
@ -2610,18 +2610,15 @@ impl Engine {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
if entry_type == AccessMode::ReadOnly && lib.iter().any(|&m| !m.is_empty()) {
|
||||
let global = if let Some(index) = mods.find(KEYWORD_GLOBAL) {
|
||||
let global = mods.get_mut(index).unwrap();
|
||||
|
||||
if !global.is_internal() {
|
||||
None
|
||||
} else {
|
||||
Some(global)
|
||||
match mods.get_mut(index).unwrap() {
|
||||
m if m.internal => Some(m),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
// Create automatic global module
|
||||
let mut global = Module::new();
|
||||
global.set_internal(true);
|
||||
mods.push(crate::engine::KEYWORD_GLOBAL, global);
|
||||
global.internal = true;
|
||||
mods.push(KEYWORD_GLOBAL, global);
|
||||
Some(mods.get_mut(mods.len() - 1).unwrap())
|
||||
};
|
||||
|
||||
|
@ -5,8 +5,8 @@ use crate::engine::Imports;
|
||||
use crate::plugin::PluginFunction;
|
||||
use crate::token::is_valid_identifier;
|
||||
use crate::{
|
||||
calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, Identifier, ImmutableString, Module,
|
||||
Position, RhaiResult, StaticVec,
|
||||
calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, Identifier, Module, Position,
|
||||
RhaiResult, StaticVec,
|
||||
};
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
@ -367,16 +367,17 @@ impl TryFrom<Identifier> for FnPtr {
|
||||
if is_valid_identifier(value.chars()) {
|
||||
Ok(Self(value, Default::default()))
|
||||
} 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>;
|
||||
|
||||
#[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();
|
||||
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
|
||||
/// 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;
|
||||
|
||||
/// An identifier in Rhai.
|
||||
#[cfg(feature = "no_smartstring_for_identifier")]
|
||||
#[cfg(feature = "no_smartstring")]
|
||||
pub type Identifier = ImmutableString;
|
||||
|
||||
/// 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]>;
|
||||
|
||||
#[cfg(not(feature = "internals"))]
|
||||
#[cfg(not(feature = "no_smartstring"))]
|
||||
pub(crate) type SmartString = smartstring::SmartString<smartstring::Compact>;
|
||||
|
||||
#[cfg(feature = "no_smartstring")]
|
||||
pub(crate) type SmartString = String;
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
#[cfg(not(feature = "no_smartstring"))]
|
||||
pub type SmartString = smartstring::SmartString<smartstring::Compact>;
|
||||
|
||||
// Compiler guards against mutually-exclusive feature flags
|
||||
|
@ -129,7 +129,7 @@ pub struct Module {
|
||||
/// ID identifying the module.
|
||||
id: Option<Identifier>,
|
||||
/// Is this module internal?
|
||||
internal: bool,
|
||||
pub(crate) internal: bool,
|
||||
/// Sub-modules.
|
||||
modules: BTreeMap<Identifier, Shared<Module>>,
|
||||
/// [`Module`] variables.
|
||||
@ -309,20 +309,6 @@ impl Module {
|
||||
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?
|
||||
///
|
||||
/// # Example
|
||||
@ -476,10 +462,7 @@ impl Module {
|
||||
/// If there is an existing function of the same name and number of arguments, it is replaced.
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[inline]
|
||||
pub(crate) fn set_script_fn(
|
||||
&mut self,
|
||||
fn_def: impl Into<Shared<crate::ast::ScriptFnDef>>,
|
||||
) -> u64 {
|
||||
pub fn set_script_fn(&mut self, fn_def: impl Into<Shared<crate::ast::ScriptFnDef>>) -> u64 {
|
||||
let fn_def = fn_def.into();
|
||||
|
||||
// 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())
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "no_smartstring"))]
|
||||
impl From<SmartString> for ImmutableString {
|
||||
#[inline(always)]
|
||||
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 {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@ -618,17 +627,17 @@ impl ImmutableString {
|
||||
/// yet interned.
|
||||
#[derive(Debug, Clone, Default, Hash)]
|
||||
pub struct IdentifierBuilder(
|
||||
#[cfg(feature = "no_smartstring_for_identifier")] std::collections::BTreeSet<Identifier>,
|
||||
#[cfg(feature = "no_smartstring")] 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_for_identifier"))]
|
||||
#[cfg(not(feature = "no_smartstring"))]
|
||||
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(|| {
|
||||
let s: Identifier = text.into();
|
||||
self.0.insert(s.clone());
|
||||
|
Loading…
Reference in New Issue
Block a user