Skip to content

Commit

Permalink
Refine Source|Buffer.indexOf(ByteBuffer) contracts
Browse files Browse the repository at this point in the history
Closes #422
  • Loading branch information
fzhinkin committed Dec 4, 2024
1 parent a9325d9 commit 4ce136a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 7 deletions.
27 changes: 20 additions & 7 deletions core/common/src/ByteStrings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public fun Source.readByteString(byteCount: Int): ByteString {
* expands the source's buffer as necessary until [byteString] is found. This reads an unbounded number of
* bytes into the buffer. Returns `-1` if the stream is exhausted before the requested bytes are found.
*
* For empty byte strings this function always return `0`.
*
* @param byteString the sequence of bytes to find within the source.
* @param startIndex the index into the source to start searching from.
*
Expand All @@ -96,11 +98,9 @@ public fun Source.readByteString(byteCount: Int): ByteString {
*/
@OptIn(InternalIoApi::class, UnsafeByteStringApi::class)
public fun Source.indexOf(byteString: ByteString, startIndex: Long = 0): Long {
require(startIndex >= 0) { "startIndex: $startIndex" }
require(startIndex >= 0) { "startIndex should be non-negative, but was: $startIndex" }

if (byteString.isEmpty()) {
return 0
}
if (byteString.isEmpty()) return 0

var offset = startIndex
while (request(offset + byteString.size)) {
Expand All @@ -117,11 +117,24 @@ public fun Source.indexOf(byteString: ByteString, startIndex: Long = 0): Long {
return -1
}

/**
* Returns the index of the first match for [byteString] in the buffer at or after [startIndex].
* Returns `-1` if the stream is exhausted before the requested bytes are found.
*
* For empty byte strings this function always return `0`.
*
* @param byteString the sequence of bytes to find within the buffer.
* @param startIndex the index into the buffer to start searching from.
*
* @throws IllegalArgumentException if [startIndex] is negative or if it is greater of equal to buffer's [Buffer.size].
*
* @sample kotlinx.io.samples.ByteStringSamples.indexOfByteString
*/
@OptIn(UnsafeByteStringApi::class)
public fun Buffer.indexOf(byteString: ByteString, startIndex: Long = 0): Long {
require(startIndex <= size) {
"startIndex ($startIndex) should not exceed size ($size)"
}
require(startIndex <= size) { "startIndex ($startIndex) should not exceed size ($size)" }
require(startIndex >= 0) { "startIndex should be non-negative, but was: $startIndex" }

if (byteString.isEmpty()) return 0
if (startIndex > size - byteString.size) return -1L

Expand Down
16 changes: 16 additions & 0 deletions core/common/test/CommonBufferTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import kotlinx.io.bytestring.ByteString
import kotlinx.io.bytestring.encodeToByteString
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFails
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue

Expand Down Expand Up @@ -618,4 +619,19 @@ class CommonBufferTest {
assertEquals(null, dst.head?.prev)
assertEquals(null, dst.tail?.next)
}

@Test
fun indexOfByteString() {
val buffer = Buffer()
buffer.writeString("hello")

assertFailsWith<IllegalArgumentException> { buffer.indexOf(ByteString(1, 2, 3), -1) }
assertFailsWith<IllegalArgumentException> { buffer.indexOf(ByteString(1, 2, 3), 10) }

assertEquals(2, buffer.indexOf("ll".encodeToByteString()))
assertEquals(2, buffer.indexOf("ll".encodeToByteString(), 2))
assertEquals(-1, buffer.indexOf("ll".encodeToByteString(), 3))
assertEquals(-1, buffer.indexOf("hello world".encodeToByteString()))
assertEquals(0, buffer.indexOf(ByteString()))
}
}
1 change: 1 addition & 0 deletions core/jvm/test/BufferTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/
package kotlinx.io

import kotlinx.io.bytestring.ByteString
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
Expand Down

0 comments on commit 4ce136a

Please sign in to comment.