All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.korlibs.io.stream.async.AsyncStream.slice.kt Maven / Gradle / Ivy

@file:Suppress("PackageDirectoryMismatch")
package korlibs.io.stream

suspend fun AsyncStream.sliceWithSize(start: Long, length: Long, closeParent: Boolean = false): AsyncStream = sliceWithBounds(start, start + length, closeParent)
suspend fun AsyncStream.sliceWithSize(start: Int, length: Int, closeParent: Boolean = false): AsyncStream =
    sliceWithBounds(start.toLong(), (start + length).toLong(), closeParent)

suspend fun AsyncStream.slice(range: IntRange, closeParent: Boolean = false): AsyncStream =
    sliceWithBounds(range.start.toLong(), (range.endInclusive.toLong() + 1), closeParent)

suspend fun AsyncStream.slice(range: LongRange, closeParent: Boolean = false): AsyncStream = sliceWithBounds(range.start, (range.endInclusive + 1), closeParent)

suspend fun AsyncStream.sliceWithBounds(start: Long, end: Long, closeParent: Boolean = false): AsyncStream {
    val rlen = if (this.hasLength()) this.getLength() else end
    val len = if (rlen >= 0L) rlen else end
    val clampedStart = start.coerceIn(0, len)
    val clampedEnd = end.coerceIn(0, len)

    val base = this.base
    return when (base) {
        is SliceAsyncStreamBase -> {
            SliceAsyncStreamBase(
                base.base,
                base.baseStart + clampedStart,
                base.baseStart + clampedEnd,
                closeParent
            )
        }
        else -> {
            SliceAsyncStreamBase(this.base, clampedStart, clampedEnd, closeParent)
        }
    }.toAsyncStream()
}

suspend fun AsyncStream.sliceStart(start: Long = 0L, closeParent: Boolean = false): AsyncStream = sliceWithBounds(start, this.getLength(), closeParent)
suspend fun AsyncStream.sliceHere(closeParent: Boolean = false): AsyncStream = this.sliceWithSize(position, this.getLength(), closeParent)

suspend fun AsyncStream.readSlice(length: Long): AsyncStream {
    val start = getPosition()
    val out = this.sliceWithSize(start, length)
    setPosition(start + length)
    return out
}

suspend fun AsyncStream.readStream(length: Int): AsyncStream = readSlice(length.toLong())
suspend fun AsyncStream.readStream(length: Long): AsyncStream = readSlice(length)

class SliceAsyncStreamBase(
    internal val base: AsyncStreamBase,
    internal val baseStart: Long,
    internal val baseEnd: Long,
    internal val closeParent: Boolean
) : AsyncStreamBase() {
    init {
        //check(baseStart < 0) { "baseStart negative: $baseStart" }
        //check(baseEnd < baseStart) { "Invalid baseEnd=$baseEnd" }
    }
    //init {
    //	base.refCount++
    //}

    internal val baseLength = baseEnd - baseStart

    private fun clampPosition(position: Long) = position.coerceIn(baseStart, baseEnd)

    private fun clampPositionLen(position: Long, len: Int): Pair {
        if (position < 0L) throw IllegalArgumentException("Invalid position")
        val targetStartPosition = clampPosition(this.baseStart + position)
        val targetEndPosition = clampPosition(targetStartPosition + len)
        val targetLen = (targetEndPosition - targetStartPosition).toInt()
        return Pair(targetStartPosition, targetLen)
    }

    override suspend fun read(position: Long, buffer: ByteArray, offset: Int, len: Int): Int {
        val (targetStartPosition, targetLen) = clampPositionLen(position, len)
        return base.read(targetStartPosition, buffer, offset, targetLen)
    }

    override suspend fun write(position: Long, buffer: ByteArray, offset: Int, len: Int) {
        val (targetStartPosition, targetLen) = clampPositionLen(position, len)
        return base.write(targetStartPosition, buffer, offset, targetLen)
    }

    override suspend fun getLength(): Long = baseLength

    override suspend fun close() {
        if (closeParent) {
            base.close()
        }
    }

    override fun toString(): String = "SliceAsyncStreamBase($base, $baseStart, $baseEnd)"
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy