|
5 | 5 |
|
6 | 6 | package kotlinx.io.unsafe |
7 | 7 |
|
| 8 | +import kotlin.contracts.ExperimentalContracts |
| 9 | +import kotlin.contracts.InvocationKind.EXACTLY_ONCE |
| 10 | +import kotlin.contracts.contract |
8 | 11 | import kotlinx.io.* |
9 | 12 | import kotlin.jvm.JvmSynthetic |
10 | 13 |
|
11 | 14 | @UnsafeIoApi |
| 15 | +@OptIn(ExperimentalContracts::class) |
12 | 16 | public object UnsafeBufferOperations { |
13 | 17 | /** |
14 | 18 | * Maximum value that is safe to pass to [writeToTail]. |
@@ -88,6 +92,10 @@ public object UnsafeBufferOperations { |
88 | 92 | buffer: Buffer, |
89 | 93 | readAction: (bytes: ByteArray, startIndexInclusive: Int, endIndexExclusive: Int) -> Int |
90 | 94 | ): Int { |
| 95 | + contract { |
| 96 | + callsInPlace(readAction, EXACTLY_ONCE) |
| 97 | + } |
| 98 | + |
91 | 99 | require(!buffer.exhausted()) { "Buffer is empty" } |
92 | 100 | val head = buffer.head!! |
93 | 101 | val bytesRead = readAction(head.dataAsByteArray(true), head.pos, head.limit) |
@@ -128,6 +136,10 @@ public object UnsafeBufferOperations { |
128 | 136 | * @sample kotlinx.io.samples.unsafe.UnsafeBufferOperationsSamples.readUleb128 |
129 | 137 | */ |
130 | 138 | public inline fun readFromHead(buffer: Buffer, readAction: (SegmentReadContext, Segment) -> Int): Int { |
| 139 | + contract { |
| 140 | + callsInPlace(readAction, EXACTLY_ONCE) |
| 141 | + } |
| 142 | + |
131 | 143 | require(!buffer.exhausted()) { "Buffer is empty" } |
132 | 144 | val head = buffer.head!! |
133 | 145 | val bytesRead = readAction(SegmentReadContextImpl, head) |
@@ -176,6 +188,10 @@ public object UnsafeBufferOperations { |
176 | 188 | buffer: Buffer, minimumCapacity: Int, |
177 | 189 | writeAction: (bytes: ByteArray, startIndexInclusive: Int, endIndexExclusive: Int) -> Int |
178 | 190 | ): Int { |
| 191 | + contract { |
| 192 | + callsInPlace(writeAction, EXACTLY_ONCE) |
| 193 | + } |
| 194 | + |
179 | 195 | val tail = buffer.writableSegment(minimumCapacity) |
180 | 196 |
|
181 | 197 | val data = tail.dataAsByteArray(false) |
@@ -240,6 +256,10 @@ public object UnsafeBufferOperations { |
240 | 256 | minimumCapacity: Int, |
241 | 257 | writeAction: (SegmentWriteContext, Segment) -> Int |
242 | 258 | ): Int { |
| 259 | + contract { |
| 260 | + callsInPlace(writeAction, EXACTLY_ONCE) |
| 261 | + } |
| 262 | + |
243 | 263 | val tail = buffer.writableSegment(minimumCapacity) |
244 | 264 | val bytesWritten = writeAction(SegmentWriteContextImpl, tail) |
245 | 265 |
|
@@ -285,6 +305,9 @@ public object UnsafeBufferOperations { |
285 | 305 | * @sample kotlinx.io.samples.unsafe.UnsafeBufferOperationsSamples.crc32Unsafe |
286 | 306 | */ |
287 | 307 | public inline fun iterate(buffer: Buffer, iterationAction: (BufferIterationContext, Segment?) -> Unit) { |
| 308 | + contract { |
| 309 | + callsInPlace(iterationAction, EXACTLY_ONCE) |
| 310 | + } |
288 | 311 | iterationAction(BufferIterationContextImpl, buffer.head) |
289 | 312 | } |
290 | 313 |
|
@@ -314,6 +337,10 @@ public object UnsafeBufferOperations { |
314 | 337 | buffer: Buffer, offset: Long, |
315 | 338 | iterationAction: (BufferIterationContext, Segment?, Long) -> Unit |
316 | 339 | ) { |
| 340 | + contract { |
| 341 | + callsInPlace(iterationAction, EXACTLY_ONCE) |
| 342 | + } |
| 343 | + |
317 | 344 | require(offset >= 0) { "Offset must be non-negative: $offset" } |
318 | 345 | if (offset >= buffer.size) { |
319 | 346 | throw IndexOutOfBoundsException("Offset should be less than buffer's size (${buffer.size}): $offset") |
@@ -365,7 +392,11 @@ public interface SegmentReadContext { |
365 | 392 | */ |
366 | 393 | @UnsafeIoApi |
367 | 394 | @JvmSynthetic |
| 395 | +@OptIn(ExperimentalContracts::class) |
368 | 396 | public inline fun SegmentReadContext.withData(segment: Segment, readAction: (ByteArray, Int, Int) -> Unit) { |
| 397 | + contract { |
| 398 | + callsInPlace(readAction, EXACTLY_ONCE) |
| 399 | + } |
369 | 400 | readAction(segment.dataAsByteArray(true), segment.pos, segment.limit) |
370 | 401 | } |
371 | 402 |
|
|
0 commit comments