diff --git a/CHANGELOG.md b/CHANGELOG.md index daa864c5..5b4c3e67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Enhancements ### String Values * `SmartString` now uses `LazyCompact` instead of `Compact` to minimize allocations. +* Added `pop` for strings. ### `Scope` API diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index 65980026..4947b620 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -14,7 +14,7 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str #[export_module] mod string_functions { - use crate::ImmutableString; + use crate::{ImmutableString, SmartString}; #[rhai_fn(name = "+", name = "append")] pub fn add_append( @@ -99,6 +99,34 @@ mod string_functions { *string = trimmed.to_string().into(); } } + #[rhai_fn(return_raw)] + pub fn pop(string: &mut ImmutableString) -> Result> { + 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::::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::().into() + } pub fn to_upper(string: &str) -> ImmutableString { string.to_uppercase().into() diff --git a/tests/string.rs b/tests/string.rs index d60be0dc..62f00b86 100644 --- a/tests/string.rs +++ b/tests/string.rs @@ -100,6 +100,11 @@ fn test_string_mut() -> Result<(), Box> { engine.register_fn("bar", |s: String| s.len() as INT); engine.register_fn("baz", |s: &mut String| s.len()); + assert_eq!(engine.eval::(r#"pop("hello")"#)?, 'o'); + assert_eq!(engine.eval::(r#"pop("hello", 3)"#)?, "llo"); + assert_eq!(engine.eval::(r#"pop("hello", 10)"#)?, "hello"); + assert_eq!(engine.eval::(r#"pop("hello", -42)"#)?, ""); + assert_eq!(engine.eval::(r#"foo("hello")"#)?, 5); assert_eq!(engine.eval::(r#"bar("hello")"#)?, 5); assert!(