Skip to content
Open
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
2 changes: 1 addition & 1 deletion common/values/string_value.cc
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ absl::StatusOr<absl::Cord> SubstringImpl(const absl::Cord& cord, uint64_t start,
}
if (size_code_points == end) {
return cord.Subcord(start_code_units,
size_code_points - start_code_units);
size_code_units - start_code_units);
}
char32_t code_point;
size_t code_units;
Expand Down
29 changes: 29 additions & 0 deletions common/values/string_value_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,35 @@ TEST_F(StringValueTest, CharAt) {
"<string>.charAt(<pos>): <pos> is less than 0")));
}

TEST_F(StringValueTest, Substring) {
using ::cel::test::ErrorValueIs;
using ::cel::test::StringValueIs;

// Each '€' is three bytes, so the cord built here is 18 bytes and is stored
// as a large (cord-backed) value. The substring length must be measured in
// code units, not code points, otherwise the cord overload truncates a
// multi-byte character or underflows the length.
StringValue unicode_cord = StringValue(absl::Cord("€€€€€€"));
StringValue unicode_view = StringValue("€€€€€€");

EXPECT_THAT(unicode_cord.Substring(0, 2), StringValueIs("€€"));
EXPECT_THAT(unicode_view.Substring(0, 2), StringValueIs("€€"));
EXPECT_THAT(unicode_cord.Substring(1, 2), StringValueIs("€"));
EXPECT_THAT(unicode_view.Substring(1, 2), StringValueIs("€"));
EXPECT_THAT(unicode_cord.Substring(2, 4), StringValueIs("€€"));
EXPECT_THAT(unicode_view.Substring(2, 4), StringValueIs("€€"));
EXPECT_THAT(unicode_cord.Substring(2), StringValueIs("€€€€"));
EXPECT_THAT(unicode_view.Substring(2), StringValueIs("€€€€"));

EXPECT_THAT(unicode_cord.Substring(0, 7),
ErrorValueIs(absl::InvalidArgumentError(
"<string>.substring(<start>, <end>): <start> or <end> is "
"greater than <string>.size()")));
EXPECT_THAT(unicode_cord.Substring(-1),
ErrorValueIs(absl::InvalidArgumentError(
"<string>.substring(<start>): <start> is less than 0")));
}

TEST_F(StringValueTest, Join) {
using ::cel::runtime_internal::CreateNoMatchingOverloadError;
using ::cel::test::ErrorValueIs;
Expand Down