@@ -10,6 +10,7 @@ import kotlinx.io.bytestring.isEmpty
1010import kotlinx.io.bytestring.unsafe.UnsafeByteStringApi
1111import kotlinx.io.bytestring.unsafe.UnsafeByteStringOperations
1212import kotlinx.io.unsafe.UnsafeBufferOperations
13+ import kotlin.math.max
1314import kotlin.math.min
1415
1516/* *
@@ -85,21 +86,26 @@ public fun Source.readByteString(byteCount: Int): ByteString {
8586 * expands the source's buffer as necessary until [byteString] is found. This reads an unbounded number of
8687 * bytes into the buffer. Returns `-1` if the stream is exhausted before the requested bytes are found.
8788 *
89+ * For empty byte strings this function returns [startIndex] if it lays within underlying buffer's bounds,
90+ * `0` if [startIndex] was negative and the size of the underlying buffer if [startIndex] exceeds its size.
91+ * If the [startIndex] value was greater than the underlying buffer's size, the data will be fetched and buffered
92+ * despite the [byteString] is empty.
93+ *
8894 * @param byteString the sequence of bytes to find within the source.
8995 * @param startIndex the index into the source to start searching from.
9096 *
91- * @throws IllegalArgumentException if [startIndex] is negative.
9297 * @throws IllegalStateException if the source is closed.
9398 * @throws IOException when some I/O error occurs.
9499 *
95100 * @sample kotlinx.io.samples.ByteStringSamples.indexOfByteString
96101 */
97102@OptIn(InternalIoApi ::class , UnsafeByteStringApi ::class )
98103public fun Source.indexOf (byteString : ByteString , startIndex : Long = 0): Long {
99- require( startIndex >= 0 ) { " startIndex: $startIndex " }
104+ val startIndex = max( 0 , startIndex)
100105
101106 if (byteString.isEmpty()) {
102- return 0
107+ request(startIndex)
108+ return min(startIndex, buffer.size)
103109 }
104110
105111 var offset = startIndex
@@ -117,12 +123,22 @@ public fun Source.indexOf(byteString: ByteString, startIndex: Long = 0): Long {
117123 return - 1
118124}
119125
126+ /* *
127+ * Returns the index of the first match for [byteString] in the buffer at or after [startIndex].
128+ *
129+ * For empty byte strings this function returns [startIndex] if it lays within buffer's bounds,
130+ * `0` if [startIndex] was negative and [Buffer.size] if it was greater or equal to [Buffer.size].
131+ *
132+ * @param byteString the sequence of bytes to find within the buffer.
133+ * @param startIndex the index into the buffer to start searching from.
134+ *
135+ * @sample kotlinx.io.samples.ByteStringSamples.indexOfByteString
136+ */
120137@OptIn(UnsafeByteStringApi ::class )
121138public fun Buffer.indexOf (byteString : ByteString , startIndex : Long = 0): Long {
122- require(startIndex <= size) {
123- " startIndex ($startIndex ) should not exceed size ($size )"
124- }
125- if (byteString.isEmpty()) return 0
139+ val startIndex = max(0 , min(startIndex, size))
140+
141+ if (byteString.isEmpty()) return startIndex
126142 if (startIndex > size - byteString.size) return - 1L
127143
128144 UnsafeByteStringOperations .withByteArrayUnsafe(byteString) { byteStringData ->
0 commit comments