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 7965d95b0d Make ByteString.copyToBuffer(buffer, offset) public, add
scaladoc and test coverage (#2946)
7965d95b0d is described below
commit 7965d95b0d45e3559372a91a65f2ded17f250289
Author: PJ Fanning <[email protected]>
AuthorDate: Fri May 8 17:11:12 2026 +0100
Make ByteString.copyToBuffer(buffer, offset) public, add scaladoc and test
coverage (#2946)
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko/sessions/09848a76-7cf9-49ad-b3a6-e466857fa140
Co-authored-by: copilot-swe-agent[bot]
<[email protected]>
Co-authored-by: pjfanning <[email protected]>
---
.../org/apache/pekko/util/ByteStringSpec.scala | 61 ++++++++++++++++++++++
.../scala/org/apache/pekko/util/ByteString.scala | 21 +++++---
2 files changed, 74 insertions(+), 8 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 f4075ec5a5..c596dcad6e 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
@@ -2604,6 +2604,67 @@ class ByteStringSpec extends AnyWordSpec with Matchers
with Checkers {
ByteString.empty.copyToBuffer(ByteBuffer.allocate(10)) should ===(0)
}
+ "copyToBuffer(buffer, offset) copies from the given offset for different
ByteString types" in {
+ import java.nio.ByteBuffer
+
+ // ByteString1C — copy from offset 2
+ val bs1c = ByteString1C(Array[Byte](1, 2, 3, 4, 5))
+ val buf1 = ByteBuffer.allocate(5)
+ bs1c.copyToBuffer(buf1, 2) should ===(3)
+ buf1.flip()
+ val result1 = new Array[Byte](3)
+ buf1.get(result1)
+ result1.toSeq should ===(Seq[Byte](3, 4, 5))
+
+ // ByteString1C — offset beyond length copies nothing
+ val buf2 = ByteBuffer.allocate(5)
+ bs1c.copyToBuffer(buf2, 10) should ===(0)
+
+ // ByteString1C — offset 0 copies all
+ val buf3 = ByteBuffer.allocate(5)
+ bs1c.copyToBuffer(buf3, 0) should ===(5)
+
+ // ByteString1 — copy from offset 1 (internal startIndex + user offset)
+ val bs1 = ByteString1(Array[Byte](0, 10, 20, 30, 40, 50), 1, 4) //
logical bytes [10, 20, 30, 40]
+ val buf4 = ByteBuffer.allocate(4)
+ bs1.copyToBuffer(buf4, 1) should ===(3)
+ buf4.flip()
+ val result4 = new Array[Byte](3)
+ buf4.get(result4)
+ result4.toSeq should ===(Seq[Byte](20, 30, 40))
+
+ // ByteString1 — offset 0 copies all logical bytes
+ val buf5 = ByteBuffer.allocate(4)
+ bs1.copyToBuffer(buf5, 0) should ===(4)
+ buf5.flip()
+ buf5.get() should ===(10.toByte)
+
+ // ByteStrings — copy from offset that skips first segment entirely
+ val bss = ByteStrings(ByteString1.fromString("abc"),
ByteString1.fromString("def"))
+ val buf6 = ByteBuffer.allocate(10)
+ bss.copyToBuffer(buf6, 3) should ===(3)
+ buf6.flip()
+ val result6 = new Array[Byte](3)
+ buf6.get(result6)
+ result6.toSeq should ===(Seq[Byte]('d', 'e', 'f'))
+
+ // ByteStrings — copy from offset mid-first-segment
+ val buf7 = ByteBuffer.allocate(10)
+ bss.copyToBuffer(buf7, 1) should ===(5)
+ buf7.flip()
+ val result7 = new Array[Byte](5)
+ buf7.get(result7)
+ result7.toSeq should ===(Seq[Byte]('b', 'c', 'd', 'e', 'f'))
+
+ // ByteStrings — offset 0 copies all
+ val buf8 = ByteBuffer.allocate(6)
+ bss.copyToBuffer(buf8, 0) should ===(6)
+
+ // ByteString.empty — any offset copies nothing
+ ByteString.empty.copyToBuffer(ByteBuffer.allocate(10), 0) should ===(0)
+ ByteString.empty.copyToBuffer(ByteBuffer.allocate(10), 5) should ===(0)
+ }
+
"copying chunks to an array" in {
val iterator = (ByteString("123") ++ ByteString("456")).iterator
val array = Array.ofDim[Byte](6)
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 42aa48d941..0d4984a2fa 100644
--- a/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
+++ b/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
@@ -433,8 +433,7 @@ object ByteString {
override def copyToBuffer(buffer: ByteBuffer): Int =
writeToBuffer(buffer, offset = 0)
- /** INTERNAL API: Specialized for internal use, copying from an offset
without slicing. */
- private[pekko] override def copyToBuffer(buffer: ByteBuffer, offset: Int):
Int =
+ override def copyToBuffer(buffer: ByteBuffer, offset: Int): Int =
writeToBuffer(buffer, offset)
/** INTERNAL API: Specialized for internal use, writing multiple
ByteString1C into the same ByteBuffer. */
@@ -576,8 +575,7 @@ object ByteString {
override def copyToBuffer(buffer: ByteBuffer): Int =
writeToBuffer(buffer, offset = 0)
- /** INTERNAL API: Specialized for internal use, copying from an offset
without slicing. */
- private[pekko] override def copyToBuffer(buffer: ByteBuffer, offset: Int):
Int =
+ override def copyToBuffer(buffer: ByteBuffer, offset: Int): Int =
writeToBuffer(buffer, offset)
/** INTERNAL API: Specialized for internal use, writing multiple
ByteString1C into the same ByteBuffer. */
@@ -993,8 +991,7 @@ object ByteString {
override def copyToBuffer(buffer: ByteBuffer): Int =
copyToBuffer(buffer, offset = 0)
- /** INTERNAL API: Specialized for internal use, copying from an offset
without slicing. */
- private[pekko] override def copyToBuffer(buffer: ByteBuffer, offset: Int):
Int = {
+ override def copyToBuffer(buffer: ByteBuffer, offset: Int): Int = {
var remainingOffset = offset
var written = 0
var i = 0
@@ -1899,8 +1896,16 @@ sealed abstract class ByteString
*/
def copyToBuffer(@nowarn("msg=never used") buffer: ByteBuffer): Int
- /** INTERNAL API: Copy bytes to a ByteBuffer from a ByteString offset
without allocating a slice. */
- private[pekko] def copyToBuffer(buffer: ByteBuffer, offset: Int): Int =
+ /**
+ * Copy as many bytes as possible to a ByteBuffer, starting from a given
offset within this ByteString
+ * and the buffer's current position. This method will not overflow the
buffer.
+ *
+ * @param buffer a ByteBuffer to copy bytes to
+ * @param offset the offset within this ByteString to start copying from
+ * @return the number of bytes actually copied
+ * @since 2.0.0
+ */
+ def copyToBuffer(buffer: ByteBuffer, offset: Int): Int =
if (offset <= 0) copyToBuffer(buffer)
else drop(offset).copyToBuffer(buffer)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]