Skip to content

[PR 3/5] Implement Unsafe API to iterate over segments and access its data #336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions core/api/kotlinx-io-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public final class kotlinx/io/Buffer : kotlinx/io/Sink, kotlinx/io/Source {
public fun writeShort (S)V
}

public final class kotlinx/io/BufferKt {
public static final synthetic fun seek (Lkotlinx/io/Buffer;JLkotlin/jvm/functions/Function2;)Ljava/lang/Object;
}

public final class kotlinx/io/BuffersJvmKt {
public static final fun asByteChannel (Lkotlinx/io/Buffer;)Ljava/nio/channels/ByteChannel;
public static final fun copyTo (Lkotlinx/io/Buffer;Ljava/io/OutputStream;JJ)V
Expand Down Expand Up @@ -106,11 +110,13 @@ public final class kotlinx/io/Segment {
public final synthetic fun getLimit ()I
public final synthetic fun getNext ()Lkotlinx/io/Segment;
public final synthetic fun getPos ()I
public final synthetic fun getPrev ()Lkotlinx/io/Segment;
public final synthetic fun getRemainingCapacity ()I
public final synthetic fun getSize ()I
public final synthetic fun setLimit (I)V
public final synthetic fun setNext (Lkotlinx/io/Segment;)V
public final synthetic fun setPos (I)V
public final synthetic fun setPrev (Lkotlinx/io/Segment;)V
public final synthetic fun writeBackData ([BI)V
}

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

public abstract interface class kotlinx/io/unsafe/BufferIterationContext : kotlinx/io/unsafe/SegmentReadContext {
public abstract fun next (Lkotlinx/io/Segment;)Lkotlinx/io/Segment;
}

public abstract interface class kotlinx/io/unsafe/SegmentReadContext {
public abstract fun getUnchecked (Lkotlinx/io/Segment;I)B
}

public abstract interface class kotlinx/io/unsafe/SegmentWriteContext {
public abstract fun setUnchecked (Lkotlinx/io/Segment;IB)V
public abstract fun setUnchecked (Lkotlinx/io/Segment;IBB)V
public abstract fun setUnchecked (Lkotlinx/io/Segment;IBBB)V
public abstract fun setUnchecked (Lkotlinx/io/Segment;IBBBB)V
}

public final class kotlinx/io/unsafe/UnsafeBufferOperations {
public static final field INSTANCE Lkotlinx/io/unsafe/UnsafeBufferOperations;
public final fun getMaxSafeWriteCapacity ()I
public final fun iterate (Lkotlinx/io/Buffer;JLkotlin/jvm/functions/Function3;)V
public final fun iterate (Lkotlinx/io/Buffer;Lkotlin/jvm/functions/Function2;)V
public final fun moveToTail (Lkotlinx/io/Buffer;[BII)V
public static synthetic fun moveToTail$default (Lkotlinx/io/unsafe/UnsafeBufferOperations;Lkotlinx/io/Buffer;[BIIILjava/lang/Object;)V
public final fun readFromHead (Lkotlinx/io/Buffer;Lkotlin/jvm/functions/Function2;)V
public final fun readFromHead (Lkotlinx/io/Buffer;Lkotlin/jvm/functions/Function3;)V
public final fun writeToTail (Lkotlinx/io/Buffer;ILkotlin/jvm/functions/Function2;)V
public final fun writeToTail (Lkotlinx/io/Buffer;ILkotlin/jvm/functions/Function3;)V
}

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

public final class kotlinx/io/unsafe/UnsafeBufferOperationsKt {
public static final synthetic fun getBufferIterationContextImpl ()Lkotlinx/io/unsafe/BufferIterationContext;
public static final synthetic fun getSegmentReadContextImpl ()Lkotlinx/io/unsafe/SegmentReadContext;
public static final synthetic fun getSegmentWriteContextImpl ()Lkotlinx/io/unsafe/SegmentWriteContext;
public static final synthetic fun withData (Lkotlinx/io/unsafe/SegmentReadContext;Lkotlinx/io/Segment;Lkotlin/jvm/functions/Function3;)V
}

27 changes: 27 additions & 0 deletions core/api/kotlinx-io-core.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@
// - Show declarations: true

// Library unique name: <org.jetbrains.kotlinx:kotlinx-io-core>
abstract interface kotlinx.io.unsafe/BufferIterationContext : kotlinx.io.unsafe/SegmentReadContext { // kotlinx.io.unsafe/BufferIterationContext|null[0]
abstract fun next(kotlinx.io/Segment): kotlinx.io/Segment? // kotlinx.io.unsafe/BufferIterationContext.next|next(kotlinx.io.Segment){}[0]
}
abstract interface kotlinx.io.unsafe/SegmentReadContext { // kotlinx.io.unsafe/SegmentReadContext|null[0]
abstract fun getUnchecked(kotlinx.io/Segment, kotlin/Int): kotlin/Byte // kotlinx.io.unsafe/SegmentReadContext.getUnchecked|getUnchecked(kotlinx.io.Segment;kotlin.Int){}[0]
}
abstract interface kotlinx.io.unsafe/SegmentWriteContext { // kotlinx.io.unsafe/SegmentWriteContext|null[0]
abstract fun setUnchecked(kotlinx.io/Segment, kotlin/Int, kotlin/Byte) // kotlinx.io.unsafe/SegmentWriteContext.setUnchecked|setUnchecked(kotlinx.io.Segment;kotlin.Int;kotlin.Byte){}[0]
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]
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]
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]
}
abstract interface kotlinx.io/RawSink : kotlin/AutoCloseable { // kotlinx.io/RawSink|null[0]
abstract fun close() // kotlinx.io/RawSink.close|close(){}[0]
abstract fun flush() // kotlinx.io/RawSink.flush|flush(){}[0]
Expand Down Expand Up @@ -100,6 +112,9 @@ final class kotlinx.io/Segment { // kotlinx.io/Segment|null[0]
final var pos // kotlinx.io/Segment.pos|{}pos[0]
final fun <get-pos>(): kotlin/Int // kotlinx.io/Segment.pos.<get-pos>|<get-pos>(){}[0]
final fun <set-pos>(kotlin/Int) // kotlinx.io/Segment.pos.<set-pos>|<set-pos>(kotlin.Int){}[0]
final var prev // kotlinx.io/Segment.prev|{}prev[0]
final fun <get-prev>(): kotlinx.io/Segment? // kotlinx.io/Segment.prev.<get-prev>|<get-prev>(){}[0]
final fun <set-prev>(kotlinx.io/Segment?) // kotlinx.io/Segment.prev.<set-prev>|<set-prev>(kotlinx.io.Segment?){}[0]
}
final fun (kotlinx.io.files/Path).kotlinx.io.files/sink(): kotlinx.io/Sink // kotlinx.io.files/sink|sink@kotlinx.io.files.Path(){}[0]
final fun (kotlinx.io.files/Path).kotlinx.io.files/source(): kotlinx.io/Source // kotlinx.io.files/source|source@kotlinx.io.files.Path(){}[0]
Expand Down Expand Up @@ -163,10 +178,16 @@ final fun kotlinx.io.files/Path(kotlin/String): kotlinx.io.files/Path // kotlinx
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]
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]
final fun kotlinx.io/discardingSink(): kotlinx.io/RawSink // kotlinx.io/discardingSink|discardingSink(){}[0]
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]
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]
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]
final object kotlinx.io.unsafe/UnsafeBufferOperations { // kotlinx.io.unsafe/UnsafeBufferOperations|null[0]
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]
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]
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]
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]
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]
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]
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]
final val maxSafeWriteCapacity // kotlinx.io.unsafe/UnsafeBufferOperations.maxSafeWriteCapacity|{}maxSafeWriteCapacity[0]
final fun <get-maxSafeWriteCapacity>(): kotlin/Int // kotlinx.io.unsafe/UnsafeBufferOperations.maxSafeWriteCapacity.<get-maxSafeWriteCapacity>|<get-maxSafeWriteCapacity>(){}[0]
Expand All @@ -177,6 +198,12 @@ final val kotlinx.io.files/SystemPathSeparator // kotlinx.io.files/SystemPathSep
final fun <get-SystemPathSeparator>(): kotlin/Char // kotlinx.io.files/SystemPathSeparator.<get-SystemPathSeparator>|<get-SystemPathSeparator>(){}[0]
final val kotlinx.io.files/SystemTemporaryDirectory // kotlinx.io.files/SystemTemporaryDirectory|{}SystemTemporaryDirectory[0]
final fun <get-SystemTemporaryDirectory>(): kotlinx.io.files/Path // kotlinx.io.files/SystemTemporaryDirectory.<get-SystemTemporaryDirectory>|<get-SystemTemporaryDirectory>(){}[0]
final val kotlinx.io.unsafe/BufferIterationContextImpl // kotlinx.io.unsafe/BufferIterationContextImpl|{}BufferIterationContextImpl[0]
final fun <get-BufferIterationContextImpl>(): kotlinx.io.unsafe/BufferIterationContext // kotlinx.io.unsafe/BufferIterationContextImpl.<get-BufferIterationContextImpl>|<get-BufferIterationContextImpl>(){}[0]
final val kotlinx.io.unsafe/SegmentReadContextImpl // kotlinx.io.unsafe/SegmentReadContextImpl|{}SegmentReadContextImpl[0]
final fun <get-SegmentReadContextImpl>(): kotlinx.io.unsafe/SegmentReadContext // kotlinx.io.unsafe/SegmentReadContextImpl.<get-SegmentReadContextImpl>|<get-SegmentReadContextImpl>(){}[0]
final val kotlinx.io.unsafe/SegmentWriteContextImpl // kotlinx.io.unsafe/SegmentWriteContextImpl|{}SegmentWriteContextImpl[0]
final fun <get-SegmentWriteContextImpl>(): kotlinx.io.unsafe/SegmentWriteContext // kotlinx.io.unsafe/SegmentWriteContextImpl.<get-SegmentWriteContextImpl>|<get-SegmentWriteContextImpl>(){}[0]
open annotation class kotlinx.io/DelicateIoApi : kotlin/Annotation { // kotlinx.io/DelicateIoApi|null[0]
constructor <init>() // kotlinx.io/DelicateIoApi.<init>|<init>(){}[0]
}
Expand Down
2 changes: 2 additions & 0 deletions core/common/src/Buffer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,8 @@ public class Buffer : Source, Sink {
* Invoke `lambda` with the segment and offset at `fromIndex`. Searches from the front or the back
* depending on what's closer to `fromIndex`.
*/
@PublishedApi
@JvmSynthetic
internal inline fun <T> Buffer.seek(
fromIndex: Long,
lambda: (Segment?, Long) -> T
Expand Down
36 changes: 35 additions & 1 deletion core/common/src/Segment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ public class Segment {
internal var next: Segment? = null

/** Previous segment in the list, or null. */
@JvmField
@PublishedApi
@get:JvmSynthetic
@set:JvmSynthetic
internal var prev: Segment? = null

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

internal fun getUnchecked(index: Int): Byte {
return data[pos + index]
}

internal fun setUnchecked(index: Int, value: Byte) {
data[limit + index] = value
}

internal fun setUnchecked(index: Int, b0: Byte, b1: Byte) {
val d = data
val l = limit
d[l + index] = b0
d[l + index + 1] = b1
}

internal fun setUnchecked(index: Int, b0: Byte, b1: Byte, b2: Byte) {
val d = data
val l = limit
d[l + index] = b0
d[l + index + 1] = b1
d[l + index + 2] = b2
}

internal fun setUnchecked(index: Int, b0: Byte, b1: Byte, b2: Byte, b3: Byte) {
val d = data
val l = limit
d[l + index] = b0
d[l + index + 1] = b1
d[l + index + 2] = b2
d[l + index + 3] = b3
}

internal companion object {
/** The size of all segments in bytes. */
internal const val SIZE = 8192
Expand Down
Loading