Getting Started
Installation
See Maven Central for the latest version.
Gradle (Kotlin DSL)
dependencies {
// Core buffer library
implementation("com.ditchoom:buffer:<latest-version>")
// Optional: Compression (gzip, deflate)
implementation("com.ditchoom:buffer-compression:<latest-version>")
// Optional: Flow extensions (lines, mapBuffer, asStringFlow)
implementation("com.ditchoom:buffer-flow:<latest-version>")
}
Gradle (Groovy)
dependencies {
implementation 'com.ditchoom:buffer:<latest-version>'
}
For multiplatform projects, add to your commonMain dependencies:
kotlin {
sourceSets {
commonMain {
dependencies {
implementation("com.ditchoom:buffer:<latest-version>")
}
}
}
}
Your First Buffer
Allocating a Buffer
import com.ditchoom.buffer.PlatformBuffer
// Allocate 1024 bytes
val buffer = PlatformBuffer.allocate(1024)
Writing Data
// Write primitives (advances position automatically)
buffer.writeByte(0x42)
buffer.writeShort(1000)
buffer.writeInt(123456)
buffer.writeLong(9876543210L)
buffer.writeFloat(3.14f)
buffer.writeDouble(2.71828)
// Write strings
buffer.writeString("Hello, World!")
// Write byte arrays
buffer.writeBytes(byteArrayOf(1, 2, 3, 4))
Preparing to Read
After writing, call resetForRead() to set position to 0 and limit to the written amount:
buffer.resetForRead()
Reading Data
val byte = buffer.readByte()
val short = buffer.readShort()
val int = buffer.readInt()
val long = buffer.readLong()
val float = buffer.readFloat()
val double = buffer.readDouble()
val text = buffer.readString(13) // "Hello, World!"
val bytes = buffer.readByteArray(4)
Wrapping Existing Data
// Wrap a byte array (no copy)
val data = byteArrayOf(0x00, 0x01, 0x02, 0x03)
val buffer = PlatformBuffer.wrap(data)
// Now read from it
buffer.readInt() // 0x00010203 (big-endian)
Allocation Zones
Choose where the buffer is allocated:
import com.ditchoom.buffer.AllocationZone
// Heap allocation (GC managed)
val heapBuffer = PlatformBuffer.allocate(1024, AllocationZone.Heap)
// Direct/off-heap (default, zero-copy I/O)
val directBuffer = PlatformBuffer.allocate(1024, AllocationZone.Direct)
// Shared memory (for IPC on Android)
val sharedBuffer = PlatformBuffer.allocate(1024, AllocationZone.SharedMemory)
See Allocation Zones for details.
Byte Order
Specify endianness:
import com.ditchoom.buffer.ByteOrder
// Big-endian (network byte order, default)
val bigEndian = PlatformBuffer.allocate(1024, byteOrder = ByteOrder.BIG_ENDIAN)
// Little-endian
val littleEndian = PlatformBuffer.allocate(1024, byteOrder = ByteOrder.LITTLE_ENDIAN)
Searching Buffers
Find values within a buffer:
val buffer = PlatformBuffer.allocate(100)
buffer.writeString("Hello, World!")
buffer.resetForRead()
// Find a byte
val index = buffer.indexOf(','.code.toByte()) // 5
// Find a string
val worldIndex = buffer.indexOf("World") // 7
// Find primitive values (respects byte order)
buffer.indexOf(0x1234.toShort())
buffer.indexOf(0x12345678)
buffer.indexOf(0x123456789ABCDEF0L)
// Aligned search (faster, SIMD-accelerated on native)
// Use when values were written with writeShort/writeInt/writeLong
buffer.indexOf(0x1234.toShort(), aligned = true)
buffer.indexOf(0x12345678, aligned = true)
Comparing Buffers
Compare buffer contents:
val buf1 = PlatformBuffer.wrap(byteArrayOf(1, 2, 3, 4))
val buf2 = PlatformBuffer.wrap(byteArrayOf(1, 2, 3, 4))
val buf3 = PlatformBuffer.wrap(byteArrayOf(1, 2, 5, 4))
buf1.contentEquals(buf2) // true
buf1.contentEquals(buf3) // false
buf1.mismatch(buf3) // 2 (index where they differ)
Filling Buffers
Fill a buffer with a repeated value:
val buffer = PlatformBuffer.allocate(1024)
// Zero-fill (optimized: writes 8 bytes at a time)
buffer.fill(0x00.toByte())
// Fill with a pattern
buffer.resetForWrite()
buffer.fill(0xDEADBEEF.toInt()) // Requires size divisible by 4
// XOR mask (SIMD-accelerated on native, used for WebSocket frame masking)
buffer.resetForWrite()
buffer.fill(0x01.toByte())
buffer.resetForRead()
buffer.xorMask(0x12345678) // XOR remaining bytes with repeating 4-byte mask
Buffer Pooling
For high-performance scenarios, use buffer pools to avoid allocation overhead:
import com.ditchoom.buffer.pool.BufferPool
import com.ditchoom.buffer.pool.withPool
import com.ditchoom.buffer.pool.withBuffer
// Use withPool for scoped pool lifetime
withPool(defaultBufferSize = 8192) { pool ->
// Use withBuffer for automatic acquire/release
pool.withBuffer(1024) { buffer ->
buffer.writeInt(42)
buffer.resetForRead()
buffer.readInt()
} // Buffer automatically returned to pool
} // Pool automatically cleared
See Buffer Pooling for more patterns.
Compression
Compress and decompress any ReadBuffer — works on all platforms:
import com.ditchoom.buffer.compression.*
val data = "Hello, World!".toReadBuffer()
val compressed = compress(data, CompressionAlgorithm.Gzip).getOrThrow()
val decompressed = decompress(compressed, CompressionAlgorithm.Gzip).getOrThrow()
See Compression for streaming compression, algorithms, and integration with StreamProcessor.
Flow Extensions
Compose streaming transforms with Kotlin Flow:
import com.ditchoom.buffer.flow.*
// Split arbitrarily chunked strings into complete lines
stringFlow.lines().collect { line -> process(line) }
// Transform buffer flows
bufferFlow
.mapBuffer { decompress(it, Gzip).getOrThrow() }
.asStringFlow()
.lines()
.collect { line -> process(line) }
Next Steps
- Buffer Basics - Position, limit, capacity
- Basic Operations - Read/write patterns
- Stream Processing - Handle chunked data