This is an automated email from the ASF dual-hosted git repository.
pjfanning pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko.git
The following commit(s) were added to refs/heads/main by this push:
new 1736d7f845 Fix early-exit bound in indexOf(elem, from, to) (#2876)
1736d7f845 is described below
commit 1736d7f845c776def1a96028be4b3c5cfdb5efee
Author: PJ Fanning <[email protected]>
AuthorDate: Sun Apr 19 11:50:27 2026 +0200
Fix early-exit bound in indexOf(elem, from, to) (#2876)
* Fix early-exit check in indexOf(elem, from, to) to use toIndex instead of
length
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko/sessions/cdacea49-406f-4241-8331-ba4fcc4d68ef
Co-authored-by: pjfanning <[email protected]>
* Add tests for indexOf early-exit with toIndex < length and tail-only
search range
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko/sessions/cdacea49-406f-4241-8331-ba4fcc4d68ef
Co-authored-by: pjfanning <[email protected]>
* scalafmt
---------
Co-authored-by: copilot-swe-agent[bot]
<[email protected]>
Co-authored-by: pjfanning <[email protected]>
---
.../scala/org/apache/pekko/util/ByteStringSpec.scala | 20 ++++++++++++++++++++
.../scala/org/apache/pekko/util/ByteString.scala | 4 ++--
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git
a/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
b/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
index b9d0f2f28f..ffdc3e4e8d 100644
--- a/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
+++ b/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
@@ -1141,6 +1141,26 @@ class ByteStringSpec extends AnyWordSpec with Matchers
with Checkers {
byteStringLong.indexOf('z', 2, 26) should ===(25)
byteStringLong.indexOf('z', 2, 24) should ===(-1)
byteStringLong.indexOf('a', 2, 24) should ===(-1)
+
+ // Early-exit optimization: toIndex < length and searchLength < 8
(tail-only, longCount == 0)
+ // ByteString1C (compact): length=26, search range [0,5) has
searchLength=5 < 8
+ val bsCompact =
ByteString1.fromString("abcdefghijklmnopqrstuvwxyz").compact
+ bsCompact.indexOf('a'.toByte, 0, 5) should ===(0) // found within range
+ bsCompact.indexOf('e'.toByte, 0, 5) should ===(4) // found at last
position in range
+ bsCompact.indexOf('f'.toByte, 0, 5) should ===(-1) // at toIndex, not in
[0,5)
+ bsCompact.indexOf('z'.toByte, 0, 5) should ===(-1) // beyond toIndex,
not in [0,5)
+ bsCompact.indexOf('c'.toByte, 2, 5) should ===(2) // found, from in
middle of tail
+ bsCompact.indexOf('a'.toByte, 2, 5) should ===(-1) // before fromIndex,
not in [2,5)
+
+ // ByteString1 with startIndex > 0: length=26, search range [0,5) has
searchLength=5 < 8
+ val arrayLong = ("xyz" + "abcdefghijklmnopqrstuvwxyz").getBytes("UTF-8")
+ val bs1 = ByteString1(arrayLong, 3, 26)
+ bs1.indexOf('a'.toByte, 0, 5) should ===(0) // found within range
+ bs1.indexOf('e'.toByte, 0, 5) should ===(4) // found at last position in
range
+ bs1.indexOf('f'.toByte, 0, 5) should ===(-1) // at toIndex, not in [0,5)
+ bs1.indexOf('z'.toByte, 0, 5) should ===(-1) // beyond toIndex, not in
[0,5)
+ bs1.indexOf('c'.toByte, 2, 5) should ===(2) // found, from in middle of
tail
+ bs1.indexOf('a'.toByte, 2, 5) should ===(-1) // before fromIndex, not in
[2,5)
}
"copyToArray" in {
val byteString = ByteString(1, 2) ++ ByteString(3) ++ ByteString(4)
diff --git a/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
b/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
index ef46e00ff9..4ca63a598e 100644
--- a/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
+++ b/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
@@ -286,7 +286,7 @@ object ByteString {
val index = unrolledFirstIndexOf(fromIndex, byteCount, elem)
if (index != -1) return index
offset += byteCount
- if (offset == length) return -1
+ if (offset >= toIndex) return -1
}
val longCount = searchLength >>> 3
val pattern = if (longCount > 0) SWARUtil.compilePattern(elem) else 0L
@@ -669,7 +669,7 @@ object ByteString {
val index = unrolledFirstIndexOf(fromIndex + startIndex, byteCount,
elem)
if (index != -1) return index - startIndex
offset += byteCount
- if (offset == length) return -1
+ if (offset >= toIndex) return -1
}
val longCount = searchLength >>> 3
val pattern = if (longCount > 0) SWARUtil.compilePattern(elem) else 0L
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]