From dc8c4ed8f41e66f9483598250d9ea00a30f6db3b Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Thu, 17 Mar 2022 17:00:48 +0800 Subject: [PATCH] Improve string functions. --- src/func/native.rs | 10 +++++++++- src/packages/string_more.rs | 32 +++++++++++++++++++++++--------- src/types/immutable_string.rs | 10 +++++++++- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/func/native.rs b/src/func/native.rs index 91756290..d3e1e3a7 100644 --- a/src/func/native.rs +++ b/src/func/native.rs @@ -344,7 +344,7 @@ impl<'a> NativeCallContext<'a> { } } -/// Consume a [`Shared`] resource and return a mutable reference to the wrapped value. +/// Return a mutable reference to the wrapped value of a [`Shared`] resource. /// If the resource is shared (i.e. has other outstanding references), a cloned copy is used. #[inline(always)] #[must_use] @@ -353,6 +353,14 @@ pub fn shared_make_mut(value: &mut Shared) -> &mut T { Shared::make_mut(value) } +/// Return a mutable reference to the wrapped value of a [`Shared`] resource. +#[inline(always)] +#[must_use] +#[allow(dead_code)] +pub fn shared_get_mut(value: &mut Shared) -> Option<&mut T> { + Shared::get_mut(value) +} + /// Consume a [`Shared`] resource if is unique (i.e. not shared), or clone it otherwise. #[inline] #[must_use] diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index 79e392c9..182ee743 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -193,7 +193,11 @@ mod string_functions { /// Clear the string, making it empty. pub fn clear(string: &mut ImmutableString) { if !string.is_empty() { - string.make_mut().clear(); + if let Some(s) = string.get_mut() { + s.clear(); + } else { + *string = ImmutableString::new(); + } } } /// Cut off the string at the specified number of characters. @@ -220,8 +224,8 @@ mod string_functions { let copy = string.make_mut(); copy.clear(); copy.extend(chars.into_iter().take(len as usize)); - } else if !string.is_empty() { - string.make_mut().clear(); + } else { + clear(string); } } /// Remove whitespace characters from both ends of the string. @@ -231,13 +235,23 @@ mod string_functions { /// ```rhai /// let text = " hello "; /// - /// print(text.trim()); // prints "hello" + /// text.trim(); + /// + /// print(text); // prints "hello" /// ``` pub fn trim(string: &mut ImmutableString) { - let trimmed = string.trim(); + if let Some(s) = string.get_mut() { + let trimmed = s.trim(); - if trimmed.len() < string.len() { - *string = trimmed.to_string().into(); + if trimmed != s { + *s = trimmed.into(); + } + } else { + let trimmed = string.trim(); + + if trimmed != string { + *string = trimmed.into(); + } } } /// Remove the last character from the string and return it. @@ -313,7 +327,7 @@ mod string_functions { /// ``` #[rhai_fn(pure)] pub fn to_upper(string: &mut ImmutableString) -> ImmutableString { - if string.is_empty() || string.chars().all(char::is_uppercase) { + if string.chars().all(char::is_uppercase) { string.clone() } else { string.to_uppercase().into() @@ -366,7 +380,7 @@ mod string_functions { /// print(text); // prints "hello, world!"; /// ``` pub fn make_lower(string: &mut ImmutableString) { - if !string.is_empty() && string.chars().any(|ch| !ch.is_lowercase()) { + if string.chars().any(|ch| !ch.is_lowercase()) { *string = string.to_lowercase().into(); } } diff --git a/src/types/immutable_string.rs b/src/types/immutable_string.rs index 1df41b4d..e959b83c 100644 --- a/src/types/immutable_string.rs +++ b/src/types/immutable_string.rs @@ -1,6 +1,6 @@ //! The `ImmutableString` type. -use crate::func::native::{shared_make_mut, shared_take}; +use crate::func::native::{shared_get_mut, shared_make_mut, shared_take}; use crate::{Shared, SmartString}; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -580,6 +580,7 @@ impl ImmutableString { Self(SmartString::new_const().into()) } /// Consume the [`ImmutableString`] and convert it into a [`String`]. + /// /// If there are other references to the same string, a cloned copy is returned. #[inline] pub fn into_owned(mut self) -> String { @@ -588,10 +589,17 @@ impl ImmutableString { } /// Make sure that the [`ImmutableString`] is unique (i.e. no other outstanding references). /// Then return a mutable reference to the [`SmartString`]. + /// + /// If there are other references to the same string, a cloned copy is used. #[inline(always)] pub(crate) fn make_mut(&mut self) -> &mut SmartString { shared_make_mut(&mut self.0) } + /// Return a mutable reference to the [`SmartString`] wrapped by the [`ImmutableString`]. + #[inline(always)] + pub(crate) fn get_mut(&mut self) -> Option<&mut SmartString> { + shared_get_mut(&mut self.0) + } /// Returns `true` if the two [`ImmutableString`]'s point to the same allocation. /// /// # Example