From ac3d8e35d4a4ca4311d938ac46af9bb649c0b8f2 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 23 Feb 2021 11:56:04 +0800 Subject: [PATCH] Add splitn, rsplit and rsplitn equivalents to strings. --- RELEASES.md | 1 + src/engine.rs | 2 +- src/packages/string_more.rs | 59 ++++++++++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 0e1c7177..15c54c99 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -29,6 +29,7 @@ Enhancements * Error position in `eval` statements is now wrapped in an `EvalAltResult::ErrorInFunctionCall`. * `Position` now implements `Add` and `AddAssign`. * `Scope` now implements `IntoIterator`. +* Strings now have the `split_rev` method and variations of `split` with maximum number of segments. Version 0.19.12 diff --git a/src/engine.rs b/src/engine.rs index ee54e8bd..0444e875 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -627,7 +627,7 @@ pub struct Limits { /// Context of a script evaluation process. #[derive(Debug)] -pub struct EvalContext<'e, 'x, 'px: 'x, 'a, 's, 'm, 't, 'pt: 't> { +pub struct EvalContext<'e, 'x, 'px, 'a, 's, 'm, 't, 'pt> { pub(crate) engine: &'e Engine, pub(crate) scope: &'x mut Scope<'px>, pub(crate) mods: &'a mut Imports, diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index 65032da2..427627fb 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -360,7 +360,8 @@ mod string_functions { #[cfg(not(feature = "no_index"))] pub mod arrays { - use crate::Array; + use crate::stdlib::vec; + use crate::{Array, ImmutableString}; #[rhai_fn(name = "+")] pub fn append(string: &str, array: Array) -> String { @@ -370,13 +371,69 @@ mod string_functions { pub fn prepend(array: &mut Array, string: &str) -> String { format!("{:?}{}", array, string) } + #[rhai_fn(name = "split")] + pub fn split_at(string: ImmutableString, start: INT) -> Array { + if start <= 0 { + vec!["".into(), string.into()] + } else { + let prefix: String = string.chars().take(start as usize).collect(); + let prefix_len = prefix.len(); + vec![prefix.into(), string[prefix_len..].into()] + } + } pub fn split(string: &str, delimiter: &str) -> Array { string.split(delimiter).map(Into::::into).collect() } #[rhai_fn(name = "split")] + pub fn splitn(string: &str, delimiter: &str, segments: INT) -> Array { + let pieces: usize = if segments < 1 { 1 } else { segments as usize }; + string + .splitn(pieces, delimiter) + .map(Into::::into) + .collect() + } + #[rhai_fn(name = "split")] pub fn split_char(string: &str, delimiter: char) -> Array { string.split(delimiter).map(Into::::into).collect() } + #[rhai_fn(name = "split")] + pub fn splitn_char(string: &str, delimiter: char, segments: INT) -> Array { + let pieces: usize = if segments < 1 { 1 } else { segments as usize }; + string + .splitn(pieces, delimiter) + .map(Into::::into) + .collect() + } + #[rhai_fn(name = "split_rev")] + pub fn rsplit(string: &str, delimiter: &str) -> Array { + string + .rsplit(delimiter) + .map(Into::::into) + .collect() + } + #[rhai_fn(name = "split_rev")] + pub fn rsplitn(string: &str, delimiter: &str, segments: INT) -> Array { + let pieces: usize = if segments < 1 { 1 } else { segments as usize }; + string + .rsplitn(pieces, delimiter) + .map(Into::::into) + .collect() + } + #[rhai_fn(name = "split_rev")] + pub fn rsplit_char(string: &str, delimiter: char) -> Array { + string + .rsplit(delimiter) + .map(Into::::into) + .collect() + } + #[rhai_fn(name = "split_rev")] + pub fn rsplitn_char(string: &str, delimiter: char, segments: INT) -> Array { + let pieces: usize = if segments < 1 { 1 } else { segments as usize }; + string + .rsplitn(pieces, delimiter) + .map(Into::::into) + .collect() + } } #[cfg(not(feature = "no_object"))]