Skip to content

Instantly share code, notes, and snippets.

@ktprograms
Last active November 23, 2020 09:37
Show Gist options
  • Save ktprograms/c6a180216b719b7ac4c8798a26bb74a8 to your computer and use it in GitHub Desktop.
Save ktprograms/c6a180216b719b7ac4c8798a26bb74a8 to your computer and use it in GitHub Desktop.
Kotlin Base85 (Ascii85) encoder/decoder. Doesn't add the <~ and ~> at the start and end.
import kotlin.math.pow
object Base85 {
// Data class to represent the 5 output values of the base85 / ascii85 encoding
private data class Block(val a: UInt, val b: UInt, val c: UInt, val d: UInt, val e: UInt)
// Encode a ByteArray to a Base85 / Ascii85 String
fun encode(arr: ByteArray): String {
var final = ""
for (x in arr.indices step 4) {
val uInt = arr uIntAt x
val block = getBlock(uInt)
final = final add block
}
return final
}
// Decode a Base85 / Ascii85 String to a ByteArray
fun decode(str: String): ByteArray {
var final = ByteArray(0)
for (i in str.indices step 5) {
val c0 = str[i].toInt() - 33
val c1 = str[i + 1].toInt() - 33
val c2 = str[i + 2].toInt() - 33
val c3 = str[i + 3].toInt() - 33
val c4 = str[i + 4].toInt() - 33
val v = (c0 * (85.0).pow(4)) + (c1 * (85.0).pow(3)) + (c2 * (85.0).pow(2)) + (c3 * 85.0) + c4
val vStr = v.toLong().to32bitString()
for (j in 0..3) {
final += Integer.parseInt(vStr.substring(j * 8, (j + 1) * 8), 2).toByte()
}
}
return final
}
// Functions used for encoding / decoding
private infix fun ByteArray.uIntAt(i: Int) =
((this[i].toUInt() and 0xFFu) shl 24) or
((this[i + 1].toUInt() and 0xFFu) shl 16) or
((this[i + 2].toUInt() and 0xFFu) shl 8) or
(this[i + 3].toUInt() and 0xFFu)
private fun getBlock(uInt: UInt): Block {
var n = uInt
val base = 85
val uBase = base.toUInt()
val add = 33
val uAdd = add.toUInt()
val e = n.rem(uBase).plus(uAdd)
n = n.div(uBase)
val d = n.rem(uBase).plus(uAdd)
n = n.div(uBase)
val c = n.rem(uBase).plus(uAdd)
n = n.div(uBase)
val b = n.rem(uBase).plus(uAdd)
n = n.div(uBase)
val a = n.rem(uBase).plus(uAdd)
return Block(a, b, c, d, e)
}
private infix fun String.add(block: Block): String {
var str = this
str += block.a.toInt().toChar()
str += block.b.toInt().toChar()
str += block.c.toInt().toChar()
str += block.d.toInt().toChar()
str += block.e.toInt().toChar()
return str
}
private fun Long.to32bitString(): String =
java.lang.Long.toBinaryString(this).padStart(Int.SIZE_BITS, '0')
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment