Improve string functions.

This commit is contained in:
Stephen Chung 2022-03-17 17:00:48 +08:00
parent 6223e1a6f1
commit dc8c4ed8f4
3 changed files with 41 additions and 11 deletions

View File

@ -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. /// If the resource is shared (i.e. has other outstanding references), a cloned copy is used.
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
@ -353,6 +353,14 @@ pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T {
Shared::make_mut(value) 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<T: Clone>(value: &mut Shared<T>) -> Option<&mut T> {
Shared::get_mut(value)
}
/// Consume a [`Shared`] resource if is unique (i.e. not shared), or clone it otherwise. /// Consume a [`Shared`] resource if is unique (i.e. not shared), or clone it otherwise.
#[inline] #[inline]
#[must_use] #[must_use]

View File

@ -193,7 +193,11 @@ mod string_functions {
/// Clear the string, making it empty. /// Clear the string, making it empty.
pub fn clear(string: &mut ImmutableString) { pub fn clear(string: &mut ImmutableString) {
if !string.is_empty() { 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. /// Cut off the string at the specified number of characters.
@ -220,8 +224,8 @@ mod string_functions {
let copy = string.make_mut(); let copy = string.make_mut();
copy.clear(); copy.clear();
copy.extend(chars.into_iter().take(len as usize)); copy.extend(chars.into_iter().take(len as usize));
} else if !string.is_empty() { } else {
string.make_mut().clear(); clear(string);
} }
} }
/// Remove whitespace characters from both ends of the string. /// Remove whitespace characters from both ends of the string.
@ -231,13 +235,23 @@ mod string_functions {
/// ```rhai /// ```rhai
/// let text = " hello "; /// let text = " hello ";
/// ///
/// print(text.trim()); // prints "hello" /// text.trim();
///
/// print(text); // prints "hello"
/// ``` /// ```
pub fn trim(string: &mut ImmutableString) { 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() { if trimmed != s {
*string = trimmed.to_string().into(); *s = trimmed.into();
}
} else {
let trimmed = string.trim();
if trimmed != string {
*string = trimmed.into();
}
} }
} }
/// Remove the last character from the string and return it. /// Remove the last character from the string and return it.
@ -313,7 +327,7 @@ mod string_functions {
/// ``` /// ```
#[rhai_fn(pure)] #[rhai_fn(pure)]
pub fn to_upper(string: &mut ImmutableString) -> ImmutableString { 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() string.clone()
} else { } else {
string.to_uppercase().into() string.to_uppercase().into()
@ -366,7 +380,7 @@ mod string_functions {
/// print(text); // prints "hello, world!"; /// print(text); // prints "hello, world!";
/// ``` /// ```
pub fn make_lower(string: &mut ImmutableString) { 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(); *string = string.to_lowercase().into();
} }
} }

View File

@ -1,6 +1,6 @@
//! The `ImmutableString` type. //! 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}; use crate::{Shared, SmartString};
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
@ -580,6 +580,7 @@ impl ImmutableString {
Self(SmartString::new_const().into()) Self(SmartString::new_const().into())
} }
/// Consume the [`ImmutableString`] and convert it into a [`String`]. /// Consume the [`ImmutableString`] and convert it into a [`String`].
///
/// If there are other references to the same string, a cloned copy is returned. /// If there are other references to the same string, a cloned copy is returned.
#[inline] #[inline]
pub fn into_owned(mut self) -> String { 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). /// Make sure that the [`ImmutableString`] is unique (i.e. no other outstanding references).
/// Then return a mutable reference to the [`SmartString`]. /// Then return a mutable reference to the [`SmartString`].
///
/// If there are other references to the same string, a cloned copy is used.
#[inline(always)] #[inline(always)]
pub(crate) fn make_mut(&mut self) -> &mut SmartString { pub(crate) fn make_mut(&mut self) -> &mut SmartString {
shared_make_mut(&mut self.0) 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. /// Returns `true` if the two [`ImmutableString`]'s point to the same allocation.
/// ///
/// # Example /// # Example