Skip to content
/ z85 Public

KMP compatible implementation of the Z85 encoding

License

Notifications You must be signed in to change notification settings

ktool-dev/z85

Repository files navigation

Z85

A Kotlin Multiplatform implementation of Z85 (ZeroMQ Base-85) encoding, as specified in RFC32.

Build Maven Central GitHub License GitHub issues Kotlin

What is Z85?

Z85 is a Base85 encoding format optimized for embedding binary data in strings. It encodes 4 bytes of binary data into 5 ASCII characters, providing better efficiency than Base64 (1.25x overhead vs 1.33x).

Key Features

  • Efficient: 25% overhead (vs 33% for Base64)
  • ASCII-safe: Uses only printable ASCII characters (codes 33-126)
  • Kotlin Multiplatform: Supports JVM, JS, Wasm, Linux, macOS, and Windows
  • Automatic padding: Handles data of any length with automatic padding indicators
  • Streaming support: Iterator-based encoding/decoding for large data

Installation

Add the dependency to your build.gradle.kts:

dependencies {
    implementation("dev.ktool:z85:<version>")
}

Usage

Basic Encoding and Decoding

import dev.ktool.z85.*

// Encode a ByteArray
val data = byteArrayOf(
    0x86.toByte(), 0x4F, 0xD2.toByte(), 0x6F,
    0xB5.toByte(), 0x59, 0xF7.toByte(), 0x5B
)

val encoded: String = data.encodeZ85()

// Decode a Z85 string
val decoded: ByteArray = encoded.decodeZ85()

Automatic Padding

The Z85 encoding requires the data to be divisible into 4 byte chunks. The implementation automatically handles data that isn't a multiple of 4 bytes by adding padding and a padding indicator:

// Data with 3 bytes (not divisible by 4)
val data = byteArrayOf(0x01, 0x02, 0x03)
val encoded = data.encodeZ85()  // Ends with "_1" to indicate 1 byte of padding

// Decoding automatically removes padding
val decoded = encoded.decodeZ85()  // Returns original 3 bytes

Streaming with Iterators

For processing large data streams:

// Encode a sequence
val byteSequence: Sequence<Byte> = // ... your data source
val encodedChars = byteSequence.encodeZ85()

// Decode a sequence
val charSequence: Sequence<Char> = // ... your Z85 data source
val decodedBytes = charSequence.decodeZ85()

Using the Z85 Object Directly

You can also use the Z85 object for more control:

// Encode
val encoded = Z85.encode(byteArray)
val encodedIterator = Z85.encode(byteIterator)

// Decode
val decoded = Z85.decode(encodedString)
val decodedIterator = Z85.decode(charIterator)

Padding Format

When input data length is not a multiple of 4 bytes, the encoder:

  1. Pads the data with zeros to make it divisible by 4
  2. Appends a padding indicator in the format _N where N is '1', '2', or '3'

The underscore delimiter ensures the padding indicator is never confused with legitimate Z85 output.

Note: Empty ByteArray encodes to "0" as a special case.

API Reference

Extension Functions

  • ByteArray.encodeZ85(): String - Encode bytes to Z85 string
  • String.decodeZ85(): ByteArray - Decode Z85 string to bytes
  • Sequence<Byte>.encodeZ85(): Sequence<Char> - Stream encoding
  • Sequence<Char>.decodeZ85(): Sequence<Byte> - Stream decoding
  • Iterator<Byte>.encodeZ85(): Iterator<Char> - Iterator encoding
  • Iterator<Char>.decodeZ85(): Iterator<Byte> - Iterator decoding

Z85 Object

  • Z85.encode(data: ByteArray): String - Encode bytes to Z85
  • Z85.encode(data: Iterator<Byte>): Iterator<Char> - Stream encoding
  • Z85.decode(string: String): ByteArray - Decode Z85 to bytes
  • Z85.decode(chars: Iterator<Char>): Iterator<Byte> - Stream decoding

JVM Stream Helpers

The library provides additional extension functions for working with Java I/O streams on the JVM platform:

Encoding

  • InputStream.encodeZ85(): Iterator<Char> - Encode InputStream to Z85 characters
  • InputStream.encodeZ85(outputStream: OutputStream) - Encode and write to OutputStream
  • InputStream.encodeZ85(writer: Writer) - Encode and write to Writer
  • BufferedInputStream.encodeZ85(): Iterator<Char> - Encode BufferedInputStream to Z85 characters
  • BufferedInputStream.encodeZ85(outputStream: OutputStream) - Encode and write to OutputStream
  • BufferedInputStream.encodeZ85(writer: Writer) - Encode and write to Writer

Decoding

  • InputStream.decodeZ85(): Iterator<Byte> - Decode Z85 InputStream to bytes
  • InputStream.decodeZ85(outputStream: OutputStream) - Decode and write to OutputStream
  • InputStream.decodeZ85(writer: Writer) - Decode and write to Writer
  • BufferedInputStream.decodeZ85(): Iterator<Byte> - Decode BufferedInputStream to bytes
  • BufferedInputStream.decodeZ85(outputStream: OutputStream) - Decode and write to OutputStream
  • BufferedInputStream.decodeZ85(writer: Writer) - Decode and write to Writer

Platform Support

This library supports all Kotlin Multiplatform targets:

  • JVM (Java 17+)
  • JavaScript (Browser and Node.js)
  • WebAssembly (Browser and Node.js)
  • Native
    • Linux (x64)
    • macOS (x64, ARM64)
    • Windows (x64)

Building

./gradlew build

Testing

./gradlew test

License

This project is licensed under the MIT License - see the LICENSE file for details.

References

About

KMP compatible implementation of the Z85 encoding

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages