Android JNI example
libUasmUniZstd.so exports both the existing Node-API module and an Android JNI API.
Copy or source-set-link android/Zstd.kt into the Android
application and package the matching ABI's libUasmUniZstd.so under jniLibs.
Initialize the Android Node-API runtime before the first reference to Zstd.
This combined library still imports the host's napi_* symbols. If Kotlin must
also work before or without that runtime, build jni_binding.cc as a separate
JNI shared library and link both bridges to the same static codec library.
val compressed = Zstd.compress("hello from Kotlin")
val restored = Zstd.decompress(compressed).toString(Charsets.UTF_8)
val binaryCompressed = Zstd.compress(byteArrayOf(1, 2, 3), level = 10)
val parallelCompressed = Zstd.compress(largeInput, level = 10, workers = 2)
val binaryRestored = Zstd.decompress(
binaryCompressed,
maxOutputSize = 16L * 1024L * 1024L,
)
To avoid copying native output into a ByteArray, use the direct-buffer API.
The returned buffer refers to native memory and must only be used inside the
owner's use block:
Zstd.compressDirect(largeInput).use { output ->
val buffer: ByteBuffer = output.buffer
channel.write(buffer)
}
ZstdDecompressor.updateDirect() and the other Direct variants use the same
ownership rule. Calling close() releases the native output; any retained
ByteBuffer is invalid afterwards. Input is still a ByteArray, so this API
only removes the native-to-Kotlin output copy.
For files or other large inputs, read fixed-size chunks and write each returned chunk immediately:
ZstdCompressor(workers = 2).use { compressor ->
source.inputStream().use { input ->
destination.outputStream().use { output ->
val chunk = ByteArray(64 * 1024)
while (true) {
val count = input.read(chunk)
if (count < 0) break
output.write(compressor.update(chunk.copyOf(count)))
}
output.write(compressor.finish())
}
}
}
Use ZstdDecompressor the same way for decompression. Its
maxOutputSize limit applies to the sum of all update results. finish()
validates that the final compressed frame is complete.
workers = 0 is the default single-threaded mode. A positive value configures
that many zstd compression workers; decompression remains single-threaded.
This mirrors the JavaScript API:
const compressed = zstd.compress('hello from JavaScript')
const restored = zstd.decompress(compressed).toString('utf8')
The Kotlin package and object name are part of the static JNI symbol names. If
uts.sdk.modules.zstd.Zstd is renamed, update both Java_... function names in
jni_binding.cc, or switch the bridge to RegisterNatives.