Add pop to string.

This commit is contained in:
Stephen Chung 2021-09-20 16:25:23 +08:00
parent 71e8cf727d
commit 6e7fbfa66f
3 changed files with 35 additions and 1 deletions

View File

@ -40,6 +40,7 @@ Enhancements
### String Values ### String Values
* `SmartString` now uses `LazyCompact` instead of `Compact` to minimize allocations. * `SmartString` now uses `LazyCompact` instead of `Compact` to minimize allocations.
* Added `pop` for strings.
### `Scope` API ### `Scope` API

View File

@ -14,7 +14,7 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
#[export_module] #[export_module]
mod string_functions { mod string_functions {
use crate::ImmutableString; use crate::{ImmutableString, SmartString};
#[rhai_fn(name = "+", name = "append")] #[rhai_fn(name = "+", name = "append")]
pub fn add_append( pub fn add_append(
@ -99,6 +99,34 @@ mod string_functions {
*string = trimmed.to_string().into(); *string = trimmed.to_string().into();
} }
} }
#[rhai_fn(return_raw)]
pub fn pop(string: &mut ImmutableString) -> Result<char, Box<EvalAltResult>> {
match string.make_mut().pop() {
Some(c) => Ok(c.into()),
None => EvalAltResult::ErrorStringBounds(0, 0, Position::NONE).into(),
}
}
#[rhai_fn(name = "pop")]
pub fn pop_string(
ctx: NativeCallContext,
string: &mut ImmutableString,
len: INT,
) -> ImmutableString {
if len <= 0 {
return ctx.engine().empty_string.clone();
}
let mut chars = StaticVec::<char>::with_capacity(len as usize);
for _ in 0..len {
match string.make_mut().pop() {
Some(c) => chars.push(c),
None => break,
}
}
chars.into_iter().rev().collect::<SmartString>().into()
}
pub fn to_upper(string: &str) -> ImmutableString { pub fn to_upper(string: &str) -> ImmutableString {
string.to_uppercase().into() string.to_uppercase().into()

View File

@ -100,6 +100,11 @@ fn test_string_mut() -> Result<(), Box<EvalAltResult>> {
engine.register_fn("bar", |s: String| s.len() as INT); engine.register_fn("bar", |s: String| s.len() as INT);
engine.register_fn("baz", |s: &mut String| s.len()); engine.register_fn("baz", |s: &mut String| s.len());
assert_eq!(engine.eval::<char>(r#"pop("hello")"#)?, 'o');
assert_eq!(engine.eval::<String>(r#"pop("hello", 3)"#)?, "llo");
assert_eq!(engine.eval::<String>(r#"pop("hello", 10)"#)?, "hello");
assert_eq!(engine.eval::<String>(r#"pop("hello", -42)"#)?, "");
assert_eq!(engine.eval::<INT>(r#"foo("hello")"#)?, 5); assert_eq!(engine.eval::<INT>(r#"foo("hello")"#)?, 5);
assert_eq!(engine.eval::<INT>(r#"bar("hello")"#)?, 5); assert_eq!(engine.eval::<INT>(r#"bar("hello")"#)?, 5);
assert!( assert!(