From 6c61445b3ff24204fde41867f231fa17df04d05d Mon Sep 17 00:00:00 2001 From: Anand Krishnamoorthi Date: Thu, 8 Aug 2024 09:39:12 -0700 Subject: [PATCH] fix: Match OPA behavior for split In case of empty delimiter, Rust's split returns leading and trailing empty strings whereas Golang's doesn't. Change behavior to match Golang/OPA. fixes #291 Signed-off-by: Anand Krishnamoorthi --- src/builtins/strings.rs | 31 ++++++++++++++++--- .../cases/builtins/strings/split.yaml | 17 ++++++++++ 2 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 tests/interpreter/cases/builtins/strings/split.yaml diff --git a/src/builtins/strings.rs b/src/builtins/strings.rs index 611d0028..15eb0ca1 100644 --- a/src/builtins/strings.rs +++ b/src/builtins/strings.rs @@ -146,11 +146,32 @@ fn split(span: &Span, params: &[Ref], args: &[Value], _strict: bool) -> Re let s = ensure_string(name, ¶ms[0], &args[0])?; let delimiter = ensure_string(name, ¶ms[1], &args[1])?; - Ok(Value::from_array( - s.split(delimiter.as_ref()) - .map(|s| Value::String(s.into())) - .collect(), - )) + let mut parts: Vec = s + .split(delimiter.as_ref()) + .map(|s| Value::String(s.into())) + .collect(); + + // Handle https://github.com/microsoft/regorus/issues/291 + // If delimiter is "", rust returns a leading and trailing "", Golang doesn't. + if delimiter.as_ref() == "" { + if parts.len() >= 2 { + if let ("", "") = ( + parts[0].as_string()?.as_ref(), + parts[parts.len() - 1].as_string()?.as_ref(), + ) { + // Remove trailing and leading "". + parts.pop(); + parts.remove(0); + return Ok(Value::from_array(parts)); + } + } + + bail!(span.error( + "split with empty delimiter did not return leading and trailing empty delimiters" + )); + } + + Ok(Value::from_array(parts)) } fn to_string(v: &Value, unescape: bool) -> String { diff --git a/tests/interpreter/cases/builtins/strings/split.yaml b/tests/interpreter/cases/builtins/strings/split.yaml new file mode 100644 index 00000000..a71444a3 --- /dev/null +++ b/tests/interpreter/cases/builtins/strings/split.yaml @@ -0,0 +1,17 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +cases: + - note: empty separator + data: {} + modules: [] + query: "x := split(\"test\", \"\")" + want_result: + x: ["t", "e", "s", "t"] + + - note: empty separator, empty string + data: {} + modules: [] + query: "x := split(\"\", \"\")" + want_result: + x: []