
Produces short deterministic string tokens for strict-length contexts using a compact PackedFormat (bitset headers, varints/zigzag), optional transforms (checksum, encryption, ECC), and Base62/36/64/85 codecs.
KEncode produces short, predictable text payloads for environments with strict character or length limits such as URLs, file names, Kubernetes labels, and log keys.
KEncode provides three standalone entry points:
dependencies {
implementation("com.eignex:kencode:1.2.3")
}For PackedFormat and EncodedFormat you also need to load the
kotlinx.serialization plugin and core library.
Minimal example using the default EncodedFormat (Base62 + PackedFormat):
@Serializable
data class Payload(
@PackedType(IntPacking.DEFAULT) val id: ULong, // low numbers are compacted
@PackedType(IntPacking.SIGNED) val delta: Int, // zigzagged to compact small negatives
val urgent: Boolean, // Packed into bitset
val handled: Instant?, // Nullability tracked via bitset
val type: PayloadType
)
enum class PayloadType { TYPE1, TYPE2, TYPE3 }
val payload = Payload(123u, -2, true, null, PayloadType.TYPE1)
val encoded = EncodedFormat.encodeToString(payload)
// > 0fiXYI (that's it, this specific payload fits in 4 raw bytes)
val decoded = EncodedFormat.decodeFromString<Payload>(encoded)PackedFormat is a BinaryFormat designed to produce the smallest feasible payloads for Kotlin classes by moving structural metadata into a compact header.
@PackedType(IntPacking.DEFAULT)
(unsigned varint) or @PackedType(IntPacking.SIGNED) (ZigZag) annotations.
The names match kotlinx-serialization-protobuf's ProtoIntegerType, and
@ProtoType annotations are recognized automatically as a fallback.val compactFormat = PackedFormat {
// Change default from varint to fixed byte-width
defaultEncoding = IntPacking.FIXED
// Register custom serializers
serializersModule = myCustomModule
}
val bytes = compactFormat.encodeToByteArray(payload)EncodedFormat provides a StringFormat API that produces short tokens by composing three layers:
PayloadTransform applied after serialization.
Use CompactZeros to strip leading zero bytes, Checksum.asTransform() for
integrity checks, or supply your own for encryption or error-correcting codes.
Chain multiple transforms with PayloadTransform.then.val customFormat = EncodedFormat {
codec = Base36 // Use Base36 instead of Base62 (for lowercase)
checksum = Crc16 // Convenience shorthand for transform = Crc16.asTransform()
binaryFormat = ProtoBuf // Use ProtoBuf instead of PackedFormat
}
val token = customFormat.encodeToString(payload)
// Chain transforms: strip leading zeros, then append checksum
val withBoth = EncodedFormat {
transform = CompactZeros.then(Crc16.asTransform())
}KEncode includes standalone codecs for byte-to-text conversion. All implementations support custom alphabets.
Encoding "any byte data" (13 bytes):
| Codec | Output | Length | Alphabet |
|---|---|---|---|
| Base62 | 2BVj6VHhfNlsGmoMQF |
18 | [0-9A-Za-z] |
| Base36 | 0ksef5o4kvegb70nre15t |
21 | [0-9a-z] |
| Base64 | YW55IGJ5dGUgZGF0YQ== |
20 | [0-9A-Za-z+/=] |
| Base85 | @;^?5@X3',+Cno&@/ |
17 | ASCII 33–117 |
There are examples in the jvmTest source of how to extend the encoding with encryption or error correction.
Wrap a cipher as a PayloadTransform and pass it to EncodedFormat:
@Serializable
data class SecretPayload(val id: Long)
val encryptingTransform = object : PayloadTransform {
override fun encode(data: ByteArray): ByteArray = cipher.encrypt(data)
override fun decode(data: ByteArray): ByteArray = cipher.decrypt(data)
}
val secureFormat = EncodedFormat {
transform = encryptingTransform
}
val token = secureFormat.encodeToString(SecretPayload.serializer(), payload)
val decoded = secureFormat.decodeFromString(SecretPayload.serializer(), token)See EncryptionExample for the full exapmle using BouncyCastle.
Wrap an error-correcting code as a PayloadTransform to recover from corrupted bytes:
val eccTransform = object : PayloadTransform {
override fun encode(data: ByteArray): ByteArray = ecc.encode(data)
override fun decode(data: ByteArray): ByteArray = ecc.decode(data)
}
val robustFormat = EncodedFormat {
transform = eccTransform
}
val token = robustFormat.encodeToString(SecretPayload.serializer(), payload)
val decoded = robustFormat.decodeFromString(SecretPayload.serializer(), token)See ErrorCorrectionExample for the full example using zxing and simulated byte corruption.
KEncode produces short, predictable text payloads for environments with strict character or length limits such as URLs, file names, Kubernetes labels, and log keys.
KEncode provides three standalone entry points:
dependencies {
implementation("com.eignex:kencode:1.2.3")
}For PackedFormat and EncodedFormat you also need to load the
kotlinx.serialization plugin and core library.
Minimal example using the default EncodedFormat (Base62 + PackedFormat):
@Serializable
data class Payload(
@PackedType(IntPacking.DEFAULT) val id: ULong, // low numbers are compacted
@PackedType(IntPacking.SIGNED) val delta: Int, // zigzagged to compact small negatives
val urgent: Boolean, // Packed into bitset
val handled: Instant?, // Nullability tracked via bitset
val type: PayloadType
)
enum class PayloadType { TYPE1, TYPE2, TYPE3 }
val payload = Payload(123u, -2, true, null, PayloadType.TYPE1)
val encoded = EncodedFormat.encodeToString(payload)
// > 0fiXYI (that's it, this specific payload fits in 4 raw bytes)
val decoded = EncodedFormat.decodeFromString<Payload>(encoded)PackedFormat is a BinaryFormat designed to produce the smallest feasible payloads for Kotlin classes by moving structural metadata into a compact header.
@PackedType(IntPacking.DEFAULT)
(unsigned varint) or @PackedType(IntPacking.SIGNED) (ZigZag) annotations.
The names match kotlinx-serialization-protobuf's ProtoIntegerType, and
@ProtoType annotations are recognized automatically as a fallback.val compactFormat = PackedFormat {
// Change default from varint to fixed byte-width
defaultEncoding = IntPacking.FIXED
// Register custom serializers
serializersModule = myCustomModule
}
val bytes = compactFormat.encodeToByteArray(payload)EncodedFormat provides a StringFormat API that produces short tokens by composing three layers:
PayloadTransform applied after serialization.
Use CompactZeros to strip leading zero bytes, Checksum.asTransform() for
integrity checks, or supply your own for encryption or error-correcting codes.
Chain multiple transforms with PayloadTransform.then.val customFormat = EncodedFormat {
codec = Base36 // Use Base36 instead of Base62 (for lowercase)
checksum = Crc16 // Convenience shorthand for transform = Crc16.asTransform()
binaryFormat = ProtoBuf // Use ProtoBuf instead of PackedFormat
}
val token = customFormat.encodeToString(payload)
// Chain transforms: strip leading zeros, then append checksum
val withBoth = EncodedFormat {
transform = CompactZeros.then(Crc16.asTransform())
}KEncode includes standalone codecs for byte-to-text conversion. All implementations support custom alphabets.
Encoding "any byte data" (13 bytes):
| Codec | Output | Length | Alphabet |
|---|---|---|---|
| Base62 | 2BVj6VHhfNlsGmoMQF |
18 | [0-9A-Za-z] |
| Base36 | 0ksef5o4kvegb70nre15t |
21 | [0-9a-z] |
| Base64 | YW55IGJ5dGUgZGF0YQ== |
20 | [0-9A-Za-z+/=] |
| Base85 | @;^?5@X3',+Cno&@/ |
17 | ASCII 33–117 |
There are examples in the jvmTest source of how to extend the encoding with encryption or error correction.
Wrap a cipher as a PayloadTransform and pass it to EncodedFormat:
@Serializable
data class SecretPayload(val id: Long)
val encryptingTransform = object : PayloadTransform {
override fun encode(data: ByteArray): ByteArray = cipher.encrypt(data)
override fun decode(data: ByteArray): ByteArray = cipher.decrypt(data)
}
val secureFormat = EncodedFormat {
transform = encryptingTransform
}
val token = secureFormat.encodeToString(SecretPayload.serializer(), payload)
val decoded = secureFormat.decodeFromString(SecretPayload.serializer(), token)See EncryptionExample for the full exapmle using BouncyCastle.
Wrap an error-correcting code as a PayloadTransform to recover from corrupted bytes:
val eccTransform = object : PayloadTransform {
override fun encode(data: ByteArray): ByteArray = ecc.encode(data)
override fun decode(data: ByteArray): ByteArray = ecc.decode(data)
}
val robustFormat = EncodedFormat {
transform = eccTransform
}
val token = robustFormat.encodeToString(SecretPayload.serializer(), payload)
val decoded = robustFormat.decodeFromString(SecretPayload.serializer(), token)See ErrorCorrectionExample for the full example using zxing and simulated byte corruption.