Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Bug fixes
---------

* `Engine::compact_script` now properly compacts scripts with custom syntax that uses `$raw$` (thanks [`@yuvalrakavy`](https://github.com/yuvalrakavy) [`#1079`](https://github.com/rhaiscript/rhai/pull/1079)).
* The string methods `split`, `split_rev` and their variants are now marked pure so they can be called on `const` strings ([`#1081`](https://github.com/rhaiscript/rhai/issues/1081)).

New features
------------
Expand Down
19 changes: 10 additions & 9 deletions src/packages/string_more.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1490,7 +1490,7 @@ mod string_functions {
///
/// print(text.split(-99)); // prints ["", "hello, world!"]
/// ```
#[rhai_fn(name = "split")]
#[rhai_fn(name = "split", pure)]
pub fn split_at(ctx: NativeCallContext, string: &mut ImmutableString, index: INT) -> Array {
if index <= 0 {
let Ok(abs_index) = usize::try_from(index.unsigned_abs()) else {
Expand Down Expand Up @@ -1549,7 +1549,7 @@ mod string_functions {
///
/// print(text.split()); // prints ["hello,", "world!", "hello,", "foo!"]
/// ```
#[rhai_fn(name = "split")]
#[rhai_fn(name = "split", pure)]
pub fn split_whitespace(string: &mut ImmutableString) -> Array {
if string.is_empty() {
vec![string.clone().into()]
Expand All @@ -1566,6 +1566,7 @@ mod string_functions {
///
/// print(text.split("ll")); // prints ["he", "o, world! he", "o, foo!"]
/// ```
#[rhai_fn(pure)]
pub fn split(string: &mut ImmutableString, delimiter: &str) -> Array {
if string.is_empty() || (!delimiter.is_empty() && !string.contains(delimiter)) {
vec![string.clone().into()]
Expand All @@ -1585,7 +1586,7 @@ mod string_functions {
///
/// print(text.split("ll", 2)); // prints ["he", "o, world! hello, foo!"]
/// ```
#[rhai_fn(name = "split")]
#[rhai_fn(name = "split", pure)]
pub fn splitn(string: &mut ImmutableString, delimiter: &str, segments: INT) -> Array {
if segments <= 1
|| string.is_empty()
Expand All @@ -1606,7 +1607,7 @@ mod string_functions {
///
/// print(text.split('l')); // prints ["he", "", "o, wor", "d! he", "", "o, foo!"]
/// ```
#[rhai_fn(name = "split")]
#[rhai_fn(name = "split", pure)]
pub fn split_char(string: &mut ImmutableString, delimiter: char) -> Array {
if string.is_empty() || !string.contains(delimiter) {
vec![string.clone().into()]
Expand All @@ -1626,7 +1627,7 @@ mod string_functions {
///
/// print(text.split('l', 3)); // prints ["he", "", "o, world! hello, foo!"]
/// ```
#[rhai_fn(name = "split")]
#[rhai_fn(name = "split", pure)]
pub fn splitn_char(string: &mut ImmutableString, delimiter: char, segments: INT) -> Array {
if segments <= 1 || string.is_empty() || !string.contains(delimiter) {
[string.clone().into()].into()
Expand All @@ -1645,7 +1646,7 @@ mod string_functions {
///
/// print(text.split_rev("ll")); // prints ["o, foo!", "o, world! he", "he"]
/// ```
#[rhai_fn(name = "split_rev")]
#[rhai_fn(name = "split_rev", pure)]
pub fn rsplit(string: &mut ImmutableString, delimiter: &str) -> Array {
if string.is_empty() || (!delimiter.is_empty() && !string.contains(delimiter)) {
vec![string.clone().into()]
Expand All @@ -1665,7 +1666,7 @@ mod string_functions {
///
/// print(text.split_rev("ll", 2)); // prints ["o, foo!", "hello, world! he"]
/// ```
#[rhai_fn(name = "split_rev")]
#[rhai_fn(name = "split_rev", pure)]
pub fn rsplitn(string: &mut ImmutableString, delimiter: &str, segments: INT) -> Array {
if segments <= 1
|| string.is_empty()
Expand All @@ -1690,7 +1691,7 @@ mod string_functions {
///
/// print(text.split_rev('l')); // prints ["o, foo!", "", "d! he", "o, wor", "", "he"]
/// ```
#[rhai_fn(name = "split_rev")]
#[rhai_fn(name = "split_rev", pure)]
pub fn rsplit_char(string: &mut ImmutableString, delimiter: char) -> Array {
if string.is_empty() || !string.contains(delimiter) {
vec![string.clone().into()]
Expand All @@ -1710,7 +1711,7 @@ mod string_functions {
///
/// print(text.split('l', 3)); // prints ["o, foo!", "", "hello, world! he"
/// ```
#[rhai_fn(name = "split_rev")]
#[rhai_fn(name = "split_rev", pure)]
pub fn rsplitn_char(string: &mut ImmutableString, delimiter: char, segments: INT) -> Array {
if segments <= 1 || string.is_empty() || !string.contains(delimiter) {
[string.clone().into()].into()
Expand Down
12 changes: 12 additions & 0 deletions tests/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,18 @@ fn test_string_split() {

assert_eq!(engine.eval::<INT>(r#"let x = "\u2764\u2764\u2764 hello! \u2764\u2764\u2764"; x.split(' ').len"#).unwrap(), 3);
assert_eq!(engine.eval::<INT>(r#"let x = "\u2764\u2764\u2764 hello! \u2764\u2764\u2764"; x.split("hello").len"#).unwrap(), 2);

// Verify that split/split_rev work on const strings (regression test for issue #1081).
assert_eq!(engine.eval::<INT>(r#"const x = "a,b,c"; x.split(",").len"#).unwrap(), 3);
assert_eq!(engine.eval::<INT>(r#"const x = "a,b,c"; x.split(",", 2).len"#).unwrap(), 2);
assert_eq!(engine.eval::<INT>(r#"const x = "a,b,c"; x.split(',').len"#).unwrap(), 3);
assert_eq!(engine.eval::<INT>(r#"const x = "a,b,c"; x.split(',', 2).len"#).unwrap(), 2);
assert_eq!(engine.eval::<INT>(r#"const x = "a b c"; x.split().len"#).unwrap(), 3);
assert_eq!(engine.eval::<INT>(r#"const x = "a,b,c"; x.split(3).len"#).unwrap(), 2);
assert_eq!(engine.eval::<INT>(r#"const x = "a,b,c"; x.split_rev(",").len"#).unwrap(), 3);
assert_eq!(engine.eval::<INT>(r#"const x = "a,b,c"; x.split_rev(",", 2).len"#).unwrap(), 2);
assert_eq!(engine.eval::<INT>(r#"const x = "a,b,c"; x.split_rev(',').len"#).unwrap(), 3);
assert_eq!(engine.eval::<INT>(r#"const x = "a,b,c"; x.split_rev(',', 2).len"#).unwrap(), 2);
}

#[test]
Expand Down
Loading