From e963a7251cf734a527a1c5e0af0055305baf50f8 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 27 Sep 2021 11:09:19 +0800 Subject: [PATCH] Check if empty string came from global instance. --- CHANGELOG.md | 1 + src/engine.rs | 27 +++++++++++++-------------- src/immutable_string.rs | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3015f82d..e3bc1101 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/engine.rs b/src/engine.rs index d0be3696..ac22b5be 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -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")] diff --git a/src/immutable_string.rs b/src/immutable_string.rs index 54e9bf88..8c146897 100644 --- a/src/immutable_string.rs +++ b/src/immutable_string.rs @@ -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) + } }