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 29b723f043 fix: eliminate it.isEmpty and double-traversal risk in
CompactByteString.apply(IterableOnce[Byte]) (#2875)
29b723f043 is described below
commit 29b723f043bf5343e10c1835dd83c96751e3e56c
Author: PJ Fanning <[email protected]>
AuthorDate: Mon Apr 20 10:33:30 2026 +0200
fix: eliminate it.isEmpty and double-traversal risk in
CompactByteString.apply(IterableOnce[Byte]) (#2875)
* fix: avoid it.isEmpty and double traversal in
CompactByteString.apply(IterableOnce[Byte]), add tests
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko/sessions/2f07e80b-5dd8-4504-9af4-8bcc5692f3d6
Co-authored-by: pjfanning <[email protected]>
* Optimize ByteString creation from IterableOnce
---------
Co-authored-by: copilot-swe-agent[bot]
<[email protected]>
Co-authored-by: pjfanning <[email protected]>
---
.../org/apache/pekko/util/ByteStringSpec.scala | 39 ++++++++++++++++++++++
.../scala/org/apache/pekko/util/ByteString.scala | 5 ++-
2 files changed, 41 insertions(+), 3 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 ffdc3e4e8d..fcfc4fcca7 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
@@ -491,6 +491,45 @@ class ByteStringSpec extends AnyWordSpec with Matchers
with Checkers {
verify(byteString.copyToArray(_, 3, 3))(0, 0, 0)
}
}
+ "CompactByteString.apply(IterableOnce[Byte])" must {
+ "return empty for an empty collection" in {
+ (CompactByteString(Seq.empty[Byte]) should
be).theSameInstanceAs(CompactByteString.empty)
+ (CompactByteString(List.empty[Byte]) should
be).theSameInstanceAs(CompactByteString.empty)
+ (CompactByteString(Iterator.empty[Byte]) should
be).theSameInstanceAs(CompactByteString.empty)
+ }
+ "return the correct bytes for a non-empty collection" in {
+ CompactByteString(Seq[Byte](1, 2, 3)) should ===(ByteString(1, 2, 3))
+ CompactByteString(List[Byte](10, 20)) should ===(ByteString(10, 20))
+ CompactByteString(Iterator.single(42.toByte)) should
===(ByteString(42.toByte))
+ }
+ "return a CompactByteString" in {
+ CompactByteString(Seq[Byte](1, 2)).isCompact should ===(true)
+ }
+ "traverse the iterator only once" in {
+ var traversalCount = 0
+ val singleUse = new IterableOnce[Byte] {
+ def iterator: Iterator[Byte] = {
+ traversalCount += 1
+ Iterator[Byte](1, 2, 3)
+ }
+ }
+ val result = CompactByteString(singleUse)
+ traversalCount should ===(1)
+ result should ===(ByteString(1, 2, 3))
+ }
+ "traverse an empty single-use IterableOnce only once" in {
+ var traversalCount = 0
+ val singleUse = new IterableOnce[Byte] {
+ def iterator: Iterator[Byte] = {
+ traversalCount += 1
+ Iterator.empty[Byte]
+ }
+ }
+ val result = CompactByteString(singleUse)
+ traversalCount should ===(1)
+ (result should be).theSameInstanceAs(CompactByteString.empty)
+ }
+ }
"ByteStrings" must {
"drop" in {
ByteStrings(ByteString1.fromString(""),
ByteString1.fromString("")).drop(Int.MinValue) should ===(ByteString(""))
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 4ca63a598e..a46e383334 100644
--- a/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
+++ b/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
@@ -2031,9 +2031,8 @@ object CompactByteString {
* Creates a new CompactByteString by traversing bytes.
*/
def apply(bytes: IterableOnce[Byte]): CompactByteString = {
- val it = bytes.iterator
- if (it.isEmpty) empty
- else ByteString.ByteString1C(it.toArray)
+ val iter = bytes.iterator
+ if (iter.hasNext) ByteString.ByteString1C(iter.toArray) else empty
}
/**
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]