Check if empty string came from global instance.

This commit is contained in:
Stephen Chung 2021-09-27 11:09:19 +08:00
parent c4a00f5269
commit e963a7251c
3 changed files with 37 additions and 14 deletions

View File

@ -43,6 +43,7 @@ Enhancements
* `SmartString` now uses `LazyCompact` instead of `Compact` to minimize allocations.
* Added `pop` for strings.
* Added `ImmutableString::ptr_eq` to test if two strings point to the same allocation.
### `Scope` API

View File

@ -3044,24 +3044,23 @@ impl Engine {
}
/// Check a result to ensure that the data size is within allowable limit.
fn check_return_value(&self, result: RhaiResult) -> RhaiResult {
match result {
fn check_return_value(&self, mut result: RhaiResult) -> RhaiResult {
if let Ok(ref mut r) = result {
// Concentrate all empty strings into one instance to save memory
#[cfg(feature = "no_closure")]
Ok(r) if r.as_str_ref().map_or(false, &str::is_empty) => {
Ok(self.const_empty_string().into())
if let Dynamic(crate::dynamic::Union::Str(s, _, _)) = r {
if s.is_empty() {
if !s.ptr_eq(&self.constants.empty_string) {
*s = self.const_empty_string();
}
return result;
}
}
// Concentrate all empty strings into one instance to save memory
#[cfg(not(feature = "no_closure"))]
Ok(r) if !r.is_shared() && r.as_str_ref().map_or(false, &str::is_empty) => {
Ok(self.const_empty_string().into())
}
// Check data sizes
#[cfg(not(feature = "unchecked"))]
Ok(r) => self.check_data_size(&r).map(|_| r),
// Return all other results
_ => result,
self.check_data_size(&r)?;
}
result
}
#[cfg(feature = "unchecked")]

View File

@ -538,4 +538,27 @@ impl ImmutableString {
pub(crate) fn make_mut(&mut self) -> &mut SmartString {
shared_make_mut(&mut self.0)
}
/// Returns `true` if the two [`ImmutableString`]'s point to the same allocation.
///
/// # Example
///
/// ```
/// use rhai::ImmutableString;
///
/// let s1: ImmutableString = "hello".into();
/// let s2 = s1.clone();
/// let s3: ImmutableString = "hello".into();
///
/// assert_eq!(s1, s2);
/// assert_eq!(s1, s3);
/// assert_eq!(s2, s3);
///
/// assert!(s1.ptr_eq(&s2));
/// assert!(!s1.ptr_eq(&s3));
/// assert!(!s2.ptr_eq(&s3));
/// ```
#[inline(always)]
pub fn ptr_eq(&self, other: &Self) -> bool {
Shared::ptr_eq(&self.0, &other.0)
}
}