Skip to content

Commit 37dc1fd

Browse files
committed
Implement Unsafe API to iterate over segments and access its data
1 parent c923ad2 commit 37dc1fd

10 files changed

+955
-9
lines changed

core/api/kotlinx-io-core.api

+32
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public final class kotlinx/io/Buffer : kotlinx/io/Sink, kotlinx/io/Source {
4343
public fun writeShort (S)V
4444
}
4545

46+
public final class kotlinx/io/BufferKt {
47+
public static final synthetic fun seek (Lkotlinx/io/Buffer;JLkotlin/jvm/functions/Function2;)Ljava/lang/Object;
48+
}
49+
4650
public final class kotlinx/io/BuffersJvmKt {
4751
public static final fun asByteChannel (Lkotlinx/io/Buffer;)Ljava/nio/channels/ByteChannel;
4852
public static final fun copyTo (Lkotlinx/io/Buffer;Ljava/io/OutputStream;JJ)V
@@ -106,11 +110,13 @@ public final class kotlinx/io/Segment {
106110
public final synthetic fun getLimit ()I
107111
public final synthetic fun getNext ()Lkotlinx/io/Segment;
108112
public final synthetic fun getPos ()I
113+
public final synthetic fun getPrev ()Lkotlinx/io/Segment;
109114
public final synthetic fun getRemainingCapacity ()I
110115
public final synthetic fun getSize ()I
111116
public final synthetic fun setLimit (I)V
112117
public final synthetic fun setNext (Lkotlinx/io/Segment;)V
113118
public final synthetic fun setPos (I)V
119+
public final synthetic fun setPrev (Lkotlinx/io/Segment;)V
114120
public final synthetic fun writeBackData ([BI)V
115121
}
116122

@@ -282,12 +288,31 @@ public final class kotlinx/io/files/PathsKt {
282288
public static final fun sourceDeprecated (Lkotlinx/io/files/Path;)Lkotlinx/io/Source;
283289
}
284290

291+
public abstract interface class kotlinx/io/unsafe/BufferIterationContext : kotlinx/io/unsafe/SegmentReadContext {
292+
public abstract fun next (Lkotlinx/io/Segment;)Lkotlinx/io/Segment;
293+
}
294+
295+
public abstract interface class kotlinx/io/unsafe/SegmentReadContext {
296+
public abstract fun getUnchecked (Lkotlinx/io/Segment;I)B
297+
}
298+
299+
public abstract interface class kotlinx/io/unsafe/SegmentWriteContext {
300+
public abstract fun setUnchecked (Lkotlinx/io/Segment;IB)V
301+
public abstract fun setUnchecked (Lkotlinx/io/Segment;IBB)V
302+
public abstract fun setUnchecked (Lkotlinx/io/Segment;IBBB)V
303+
public abstract fun setUnchecked (Lkotlinx/io/Segment;IBBBB)V
304+
}
305+
285306
public final class kotlinx/io/unsafe/UnsafeBufferOperations {
286307
public static final field INSTANCE Lkotlinx/io/unsafe/UnsafeBufferOperations;
287308
public static final field maxSafeWriteCapacity I
309+
public final fun iterate (Lkotlinx/io/Buffer;JLkotlin/jvm/functions/Function3;)V
310+
public final fun iterate (Lkotlinx/io/Buffer;Lkotlin/jvm/functions/Function2;)V
288311
public final fun moveToTail (Lkotlinx/io/Buffer;[BII)V
289312
public static synthetic fun moveToTail$default (Lkotlinx/io/unsafe/UnsafeBufferOperations;Lkotlinx/io/Buffer;[BIIILjava/lang/Object;)V
313+
public final fun readFromHead (Lkotlinx/io/Buffer;Lkotlin/jvm/functions/Function2;)V
290314
public final fun readFromHead (Lkotlinx/io/Buffer;Lkotlin/jvm/functions/Function3;)V
315+
public final fun writeToTail (Lkotlinx/io/Buffer;ILkotlin/jvm/functions/Function2;)V
291316
public final fun writeToTail (Lkotlinx/io/Buffer;ILkotlin/jvm/functions/Function3;)V
292317
}
293318

@@ -297,3 +322,10 @@ public final class kotlinx/io/unsafe/UnsafeBufferOperationsJvmKt {
297322
public static final fun writeToTail (Lkotlinx/io/unsafe/UnsafeBufferOperations;Lkotlinx/io/Buffer;ILkotlin/jvm/functions/Function1;)V
298323
}
299324

325+
public final class kotlinx/io/unsafe/UnsafeBufferOperationsKt {
326+
public static final synthetic fun getBufferIterationContextImpl ()Lkotlinx/io/unsafe/BufferIterationContext;
327+
public static final synthetic fun getSegmentReadContextImpl ()Lkotlinx/io/unsafe/SegmentReadContext;
328+
public static final synthetic fun getSegmentWriteContextImpl ()Lkotlinx/io/unsafe/SegmentWriteContext;
329+
public static final synthetic fun withData (Lkotlinx/io/unsafe/SegmentReadContext;Lkotlinx/io/Segment;Lkotlin/jvm/functions/Function3;)V
330+
}
331+

core/api/kotlinx-io-core.klib.api

+27
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@
77
// - Show declarations: true
88

99
// Library unique name: <org.jetbrains.kotlinx:kotlinx-io-core>
10+
abstract interface kotlinx.io.unsafe/BufferIterationContext : kotlinx.io.unsafe/SegmentReadContext { // kotlinx.io.unsafe/BufferIterationContext|null[0]
11+
abstract fun next(kotlinx.io/Segment): kotlinx.io/Segment? // kotlinx.io.unsafe/BufferIterationContext.next|next(kotlinx.io.Segment){}[0]
12+
}
13+
abstract interface kotlinx.io.unsafe/SegmentReadContext { // kotlinx.io.unsafe/SegmentReadContext|null[0]
14+
abstract fun getUnchecked(kotlinx.io/Segment, kotlin/Int): kotlin/Byte // kotlinx.io.unsafe/SegmentReadContext.getUnchecked|getUnchecked(kotlinx.io.Segment;kotlin.Int){}[0]
15+
}
16+
abstract interface kotlinx.io.unsafe/SegmentWriteContext { // kotlinx.io.unsafe/SegmentWriteContext|null[0]
17+
abstract fun setUnchecked(kotlinx.io/Segment, kotlin/Int, kotlin/Byte) // kotlinx.io.unsafe/SegmentWriteContext.setUnchecked|setUnchecked(kotlinx.io.Segment;kotlin.Int;kotlin.Byte){}[0]
18+
abstract fun setUnchecked(kotlinx.io/Segment, kotlin/Int, kotlin/Byte, kotlin/Byte) // kotlinx.io.unsafe/SegmentWriteContext.setUnchecked|setUnchecked(kotlinx.io.Segment;kotlin.Int;kotlin.Byte;kotlin.Byte){}[0]
19+
abstract fun setUnchecked(kotlinx.io/Segment, kotlin/Int, kotlin/Byte, kotlin/Byte, kotlin/Byte) // kotlinx.io.unsafe/SegmentWriteContext.setUnchecked|setUnchecked(kotlinx.io.Segment;kotlin.Int;kotlin.Byte;kotlin.Byte;kotlin.Byte){}[0]
20+
abstract fun setUnchecked(kotlinx.io/Segment, kotlin/Int, kotlin/Byte, kotlin/Byte, kotlin/Byte, kotlin/Byte) // kotlinx.io.unsafe/SegmentWriteContext.setUnchecked|setUnchecked(kotlinx.io.Segment;kotlin.Int;kotlin.Byte;kotlin.Byte;kotlin.Byte;kotlin.Byte){}[0]
21+
}
1022
abstract interface kotlinx.io/RawSink : kotlin/AutoCloseable { // kotlinx.io/RawSink|null[0]
1123
abstract fun close() // kotlinx.io/RawSink.close|close(){}[0]
1224
abstract fun flush() // kotlinx.io/RawSink.flush|flush(){}[0]
@@ -100,6 +112,9 @@ final class kotlinx.io/Segment { // kotlinx.io/Segment|null[0]
100112
final var pos // kotlinx.io/Segment.pos|{}pos[0]
101113
final fun <get-pos>(): kotlin/Int // kotlinx.io/Segment.pos.<get-pos>|<get-pos>(){}[0]
102114
final fun <set-pos>(kotlin/Int) // kotlinx.io/Segment.pos.<set-pos>|<set-pos>(kotlin.Int){}[0]
115+
final var prev // kotlinx.io/Segment.prev|{}prev[0]
116+
final fun <get-prev>(): kotlinx.io/Segment? // kotlinx.io/Segment.prev.<get-prev>|<get-prev>(){}[0]
117+
final fun <set-prev>(kotlinx.io/Segment?) // kotlinx.io/Segment.prev.<set-prev>|<set-prev>(kotlinx.io.Segment?){}[0]
103118
}
104119
final fun (kotlinx.io.files/Path).kotlinx.io.files/sink(): kotlinx.io/Sink // kotlinx.io.files/sink|sink@kotlinx.io.files.Path(){}[0]
105120
final fun (kotlinx.io.files/Path).kotlinx.io.files/source(): kotlinx.io/Source // kotlinx.io.files/source|source@kotlinx.io.files.Path(){}[0]
@@ -163,12 +178,18 @@ final fun kotlinx.io.files/Path(kotlin/String): kotlinx.io.files/Path // kotlinx
163178
final fun kotlinx.io.files/Path(kotlin/String, kotlin/Array<out kotlin/String>...): kotlinx.io.files/Path // kotlinx.io.files/Path|Path(kotlin.String;kotlin.Array<out|kotlin.String>...){}[0]
164179
final fun kotlinx.io.files/Path(kotlinx.io.files/Path, kotlin/Array<out kotlin/String>...): kotlinx.io.files/Path // kotlinx.io.files/Path|Path(kotlinx.io.files.Path;kotlin.Array<out|kotlin.String>...){}[0]
165180
final fun kotlinx.io/discardingSink(): kotlinx.io/RawSink // kotlinx.io/discardingSink|discardingSink(){}[0]
181+
final inline fun (kotlinx.io.unsafe/SegmentReadContext).kotlinx.io.unsafe/withData(kotlinx.io/Segment, kotlin/Function3<kotlin/ByteArray, kotlin/Int, kotlin/Int, kotlin/Unit>) // kotlinx.io.unsafe/withData|withData@kotlinx.io.unsafe.SegmentReadContext(kotlinx.io.Segment;kotlin.Function3<kotlin.ByteArray,kotlin.Int,kotlin.Int,kotlin.Unit>){}[0]
166182
final inline fun (kotlinx.io/Sink).kotlinx.io/writeToInternalBuffer(kotlin/Function1<kotlinx.io/Buffer, kotlin/Unit>) // kotlinx.io/writeToInternalBuffer|writeToInternalBuffer@kotlinx.io.Sink(kotlin.Function1<kotlinx.io.Buffer,kotlin.Unit>){}[0]
183+
final inline fun <#A: kotlin/Any?> (kotlinx.io/Buffer).kotlinx.io/seek(kotlin/Long, kotlin/Function2<kotlinx.io/Segment?, kotlin/Long, #A>): #A // kotlinx.io/seek|seek@kotlinx.io.Buffer(kotlin.Long;kotlin.Function2<kotlinx.io.Segment?,kotlin.Long,0:0>){0§<kotlin.Any?>}[0]
167184
final object kotlinx.io.unsafe/UnsafeBufferOperations { // kotlinx.io.unsafe/UnsafeBufferOperations|null[0]
168185
final const val maxSafeWriteCapacity // kotlinx.io.unsafe/UnsafeBufferOperations.maxSafeWriteCapacity|{}maxSafeWriteCapacity[0]
169186
final fun <get-maxSafeWriteCapacity>(): kotlin/Int // kotlinx.io.unsafe/UnsafeBufferOperations.maxSafeWriteCapacity.<get-maxSafeWriteCapacity>|<get-maxSafeWriteCapacity>(){}[0]
170187
final fun moveToTail(kotlinx.io/Buffer, kotlin/ByteArray, kotlin/Int =..., kotlin/Int =...) // kotlinx.io.unsafe/UnsafeBufferOperations.moveToTail|moveToTail(kotlinx.io.Buffer;kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0]
188+
final inline fun iterate(kotlinx.io/Buffer, kotlin/Function2<kotlinx.io.unsafe/BufferIterationContext, kotlinx.io/Segment?, kotlin/Unit>) // kotlinx.io.unsafe/UnsafeBufferOperations.iterate|iterate(kotlinx.io.Buffer;kotlin.Function2<kotlinx.io.unsafe.BufferIterationContext,kotlinx.io.Segment?,kotlin.Unit>){}[0]
189+
final inline fun iterate(kotlinx.io/Buffer, kotlin/Long, kotlin/Function3<kotlinx.io.unsafe/BufferIterationContext, kotlinx.io/Segment?, kotlin/Long, kotlin/Unit>) // kotlinx.io.unsafe/UnsafeBufferOperations.iterate|iterate(kotlinx.io.Buffer;kotlin.Long;kotlin.Function3<kotlinx.io.unsafe.BufferIterationContext,kotlinx.io.Segment?,kotlin.Long,kotlin.Unit>){}[0]
190+
final inline fun readFromHead(kotlinx.io/Buffer, kotlin/Function2<kotlinx.io.unsafe/SegmentReadContext, kotlinx.io/Segment, kotlin/Int>) // kotlinx.io.unsafe/UnsafeBufferOperations.readFromHead|readFromHead(kotlinx.io.Buffer;kotlin.Function2<kotlinx.io.unsafe.SegmentReadContext,kotlinx.io.Segment,kotlin.Int>){}[0]
171191
final inline fun readFromHead(kotlinx.io/Buffer, kotlin/Function3<kotlin/ByteArray, kotlin/Int, kotlin/Int, kotlin/Int>) // kotlinx.io.unsafe/UnsafeBufferOperations.readFromHead|readFromHead(kotlinx.io.Buffer;kotlin.Function3<kotlin.ByteArray,kotlin.Int,kotlin.Int,kotlin.Int>){}[0]
192+
final inline fun writeToTail(kotlinx.io/Buffer, kotlin/Int, kotlin/Function2<kotlinx.io.unsafe/SegmentWriteContext, kotlinx.io/Segment, kotlin/Int>) // kotlinx.io.unsafe/UnsafeBufferOperations.writeToTail|writeToTail(kotlinx.io.Buffer;kotlin.Int;kotlin.Function2<kotlinx.io.unsafe.SegmentWriteContext,kotlinx.io.Segment,kotlin.Int>){}[0]
172193
final inline fun writeToTail(kotlinx.io/Buffer, kotlin/Int, kotlin/Function3<kotlin/ByteArray, kotlin/Int, kotlin/Int, kotlin/Int>) // kotlinx.io.unsafe/UnsafeBufferOperations.writeToTail|writeToTail(kotlinx.io.Buffer;kotlin.Int;kotlin.Function3<kotlin.ByteArray,kotlin.Int,kotlin.Int,kotlin.Int>){}[0]
173194
}
174195
final val kotlinx.io.files/SystemFileSystem // kotlinx.io.files/SystemFileSystem|{}SystemFileSystem[0]
@@ -177,6 +198,12 @@ final val kotlinx.io.files/SystemPathSeparator // kotlinx.io.files/SystemPathSep
177198
final fun <get-SystemPathSeparator>(): kotlin/Char // kotlinx.io.files/SystemPathSeparator.<get-SystemPathSeparator>|<get-SystemPathSeparator>(){}[0]
178199
final val kotlinx.io.files/SystemTemporaryDirectory // kotlinx.io.files/SystemTemporaryDirectory|{}SystemTemporaryDirectory[0]
179200
final fun <get-SystemTemporaryDirectory>(): kotlinx.io.files/Path // kotlinx.io.files/SystemTemporaryDirectory.<get-SystemTemporaryDirectory>|<get-SystemTemporaryDirectory>(){}[0]
201+
final val kotlinx.io.unsafe/BufferIterationContextImpl // kotlinx.io.unsafe/BufferIterationContextImpl|<get-BufferIterationContextImpl>(){}[0]
202+
final fun <get-BufferIterationContextImpl>(): kotlinx.io.unsafe/BufferIterationContext // kotlinx.io.unsafe/BufferIterationContextImpl.<get-BufferIterationContextImpl>|<get-BufferIterationContextImpl>(){}[0]
203+
final val kotlinx.io.unsafe/SegmentReadContextImpl // kotlinx.io.unsafe/SegmentReadContextImpl|<get-SegmentReadContextImpl>(){}[0]
204+
final fun <get-SegmentReadContextImpl>(): kotlinx.io.unsafe/SegmentReadContext // kotlinx.io.unsafe/SegmentReadContextImpl.<get-SegmentReadContextImpl>|<get-SegmentReadContextImpl>(){}[0]
205+
final val kotlinx.io.unsafe/SegmentWriteContextImpl // kotlinx.io.unsafe/SegmentWriteContextImpl|<get-SegmentWriteContextImpl>(){}[0]
206+
final fun <get-SegmentWriteContextImpl>(): kotlinx.io.unsafe/SegmentWriteContext // kotlinx.io.unsafe/SegmentWriteContextImpl.<get-SegmentWriteContextImpl>|<get-SegmentWriteContextImpl>(){}[0]
180207
open annotation class kotlinx.io/DelicateIoApi : kotlin/Annotation { // kotlinx.io/DelicateIoApi|null[0]
181208
constructor <init>() // kotlinx.io/DelicateIoApi.<init>|<init>(){}[0]
182209
}

core/common/src/Buffer.kt

+2
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,8 @@ public class Buffer : Source, Sink {
709709
* Invoke `lambda` with the segment and offset at `fromIndex`. Searches from the front or the back
710710
* depending on what's closer to `fromIndex`.
711711
*/
712+
@PublishedApi
713+
@JvmSynthetic
712714
internal inline fun <T> Buffer.seek(
713715
fromIndex: Long,
714716
lambda: (Segment?, Long) -> T

core/common/src/Segment.kt

+35-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ public class Segment {
7373
internal var next: Segment? = null
7474

7575
/** Previous segment in the list, or null. */
76-
@JvmField
76+
@PublishedApi
77+
@get:JvmSynthetic
78+
@set:JvmSynthetic
7779
internal var prev: Segment? = null
7880

7981
private constructor() {
@@ -239,6 +241,38 @@ public class Segment {
239241
@Suppress("UNUSED_PARAMETER")
240242
internal fun writeBackData(data: ByteArray, bytesToCommit: Int): Unit = Unit
241243

244+
internal fun getUnchecked(index: Int): Byte {
245+
return data[pos + index]
246+
}
247+
248+
internal fun setUnchecked(index: Int, value: Byte) {
249+
data[limit + index] = value
250+
}
251+
252+
internal fun setUnchecked(index: Int, b0: Byte, b1: Byte) {
253+
val d = data
254+
val l = limit
255+
d[l + index] = b0
256+
d[l + index + 1] = b1
257+
}
258+
259+
internal fun setUnchecked(index: Int, b0: Byte, b1: Byte, b2: Byte) {
260+
val d = data
261+
val l = limit
262+
d[l + index] = b0
263+
d[l + index + 1] = b1
264+
d[l + index + 2] = b2
265+
}
266+
267+
internal fun setUnchecked(index: Int, b0: Byte, b1: Byte, b2: Byte, b3: Byte) {
268+
val d = data
269+
val l = limit
270+
d[l + index] = b0
271+
d[l + index + 1] = b1
272+
d[l + index + 2] = b2
273+
d[l + index + 3] = b3
274+
}
275+
242276
internal companion object {
243277
/** The size of all segments in bytes. */
244278
internal const val SIZE = 8192

0 commit comments

Comments
 (0)