RawSink

expect interface RawSink : AutoCloseable(source)

Receives a stream of bytes. RawSink is a base interface for kotlinx-io data receivers.

This interface should be implemented to write data wherever it's needed: to the network, storage, or a buffer in memory. Sinks may be layered to transform received data, such as to compress, encrypt, throttle, or add protocol framing.

Most application code shouldn't operate on a raw sink directly, but rather on a buffered Sink which is both more efficient and more convenient. Use buffered to wrap any raw sink with a buffer.

Implementors should abstain from throwing exceptions other than those that are documented for RawSink methods.

Thread-safety guarantees

RawSink implementations are not required to be thread safe. However, if an implementation provides some thread safety guarantees, it is recommended to explicitly document them.

Samples

import kotlinx.io.*
import kotlin.test.*

fun main() { 
   //sampleStart 
   /**
 * Sink calculating CRC-32 code for all the data written to it and sending this data to the upstream afterward.
 * The CRC-32 value could be obtained using [crc32] method.
 *
 * See https://en.wikipedia.org/wiki/Cyclic_redundancy_check for more information about CRC-32.
 */
class CRC32Sink(private val upstream: RawSink): RawSink {
    private val tempBuffer = Buffer()
    private val crc32Table = generateCrc32Table()
    private var crc32: UInt = 0xffffffffU

    private fun update(value: Byte) {
        val index = value.toUInt().xor(crc32).toUByte()
        crc32 = crc32Table[index.toInt()].xor(crc32.shr(8))
    }

    fun crc32(): UInt = crc32.xor(0xffffffffU)

    override fun write(source: Buffer, byteCount: Long) {
        source.copyTo(tempBuffer, 0, byteCount)

        while (!tempBuffer.exhausted()) {
            update(tempBuffer.readByte())
        }

        upstream.write(source, byteCount)
    }

    override fun flush() = upstream.flush()

    override fun close() = upstream.close()

    private fun generateCrc32Table(): UIntArray {
        val table = UIntArray(256)

        for (idx in table.indices) {
            table[idx] = idx.toUInt()
            for (bit in 8 downTo 1) {
                table[idx] = if (table[idx] % 2U == 0U) {
                    table[idx].shr(1)
                } else {
                    table[idx].shr(1).xor(0xEDB88320U)
                }
            }
        }

        return table
    }
}

val crc32Sink = CRC32Sink(discardingSink())

crc32Sink.buffered().use {
    it.writeString("hello crc32")
}

assertEquals(0x9896d398U, crc32Sink.crc32()) 
   //sampleEnd
}

Inheritors

actual interface RawSink : AutoCloseable(source)
actual interface RawSink : AutoCloseable, Flushable(source)
actual interface RawSink : AutoCloseable(source)
actual interface RawSink : AutoCloseable(source)

Functions

Link copied to clipboard

Returns a new sink that buffers writes to the sink. The returned sink will batch writes to the sink. Use this wherever you write to a sink to get ergonomic and efficient access to data.

Link copied to clipboard
expect abstract override fun close()

Pushes all buffered bytes to their final destination and releases the resources held by this sink. It is an error to write a closed sink. It is safe to close a sink more than once.

actual abstract override fun close()
actual abstract override fun close()
actual abstract override fun close()
actual abstract override fun close()
Link copied to clipboard
expect abstract fun flush()

Pushes all buffered bytes to their final destination.

actual abstract fun flush()
actual abstract override fun flush()
actual abstract fun flush()
actual abstract fun flush()
Link copied to clipboard
expect abstract fun write(source: Buffer, byteCount: Long)

Removes byteCount bytes from source and appends them to this sink.

actual abstract fun write(source: Buffer, byteCount: Long)
actual abstract fun write(source: Buffer, byteCount: Long)
actual abstract fun write(source: Buffer, byteCount: Long)
actual abstract fun write(source: Buffer, byteCount: Long)