Compare commits

...

12 Commits

Author SHA1 Message Date
12ba3bf530 Update README.md 2026-04-16 16:12:39 +00:00
b2d8048713 Upgrade plugin 2026-02-15 14:10:59 +01:00
c366c79d4c refactor utility function name 2026-02-03 23:03:59 +01:00
e08cbb0fa9 fix README
All checks were successful
/ test (pull_request) Successful in 45s
2026-01-21 22:09:31 +01:00
61d6a8e191 implement Base45 2026-01-21 22:04:51 +01:00
6283c2f44d refactor encodings 2026-01-21 22:03:03 +01:00
8290955755 split padding in StreamEncoding to PaddedStreamEncoding 2026-01-20 09:52:58 +01:00
c1b8800e82 implement composition 2026-01-19 19:55:39 +01:00
684b6d78ea implement Base56 and Base58 2026-01-18 22:15:25 +01:00
24c667bc9c implement decode exception 2026-01-18 21:48:18 +01:00
a347bd617c fix 2^n check 2026-01-17 15:50:17 +01:00
a553aa6723 improve test coverage 2026-01-17 13:46:57 +01:00
37 changed files with 564 additions and 290 deletions

View File

@@ -1,15 +1,19 @@
# encoding-kt # encoding.kt
`encoding-kt` is a Kotlin Multiplatform library that provides common `ByteArray` encodings. `encoding.kt` is a Kotlin Multiplatform library that provides common `ByteArray` encodings.
Supported encodings: Supported encodings:
- Base2 (binary) - Base2 (binary)
- Base8 (octal) - Base8 (octal)
- Base16 (hexadecimal) - Base10 (decimal)
- Base16 (hexadecimal, uppercase/lowercase)
- Base32 - Base32
- Base36 - Base36
- Base45
- Base56
- Base58
- Base62 - Base62
- Base64 - Base64 (standard/URL)
## Installation ## Installation
@@ -35,6 +39,6 @@ fun main() {
// encode the string with the desired encoding // encode the string with the desired encoding
val encoded = Base16.encode(test).decodeToString() val encoded = Base16.encode(test).decodeToString()
println(encoded) // 48656c6c6f20576f726c6421 println(encoded) // 48656C6C6F20576F726C6421
} }
``` ```

View File

@@ -1,5 +1,5 @@
[versions] [versions]
infendro = "1.0.0" infendro = "1.1.0"
kotlin = "2.3.0" kotlin = "2.3.0"
[plugins] [plugins]

View File

@@ -0,0 +1,5 @@
package com.infendro.encoding
private val alphabet = "0123456789".encodeToByteArray()
object Base10 : Encoding by NumericEncoding(alphabet)

View File

@@ -0,0 +1,10 @@
package com.infendro.encoding
private val uppercase = "0123456789ABCDEF".encodeToByteArray()
private val lowercase = "0123456789abcdef".encodeToByteArray()
object Base16 : Encoding by StreamEncoding(uppercase) {
val UPPERCASE = this
object LOWERCASE : Encoding by StreamEncoding(lowercase)
}

View File

@@ -0,0 +1,5 @@
package com.infendro.encoding
private val alphabet = "01".encodeToByteArray()
object Base2 : Encoding by StreamEncoding(alphabet)

View File

@@ -1,6 +1,6 @@
package com.infendro.encoding.stream package com.infendro.encoding
private val alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".encodeToByteArray() private val alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".encodeToByteArray()
private const val padding = '='.code.toByte() private const val padding = '='.code.toByte()
object Base32 : StreamEncoding(alphabet, padding) object Base32 : Encoding by StreamEncoding(alphabet, padding)

View File

@@ -1,5 +1,5 @@
package com.infendro.encoding.numeric package com.infendro.encoding
private val alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".encodeToByteArray() private val alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".encodeToByteArray()
object Base36 : NumericEncoding(alphabet) object Base36 : Encoding by NumericEncoding(alphabet)

View File

@@ -0,0 +1,51 @@
package com.infendro.encoding
import com.infendro.encoding.exception.IllegalByteException
object Base45 : Encoding {
private val alphabet: ByteArray = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".encodeToByteArray()
private val base: Int = alphabet.size
override fun encode(bytes: ByteArray): ByteArray {
val result = mutableListOf<Byte>()
for (i in bytes.indices step 2) {
val remaining = minOf(bytes.size - i, 2)
var value = 0
for (j in 0..<remaining) {
val byte = bytes[i + j]
value = (value shl 8) or (byte.toInt() and 0xFF)
}
repeat(remaining + 1) {
result += alphabet[value % base]
value /= base
}
}
return result.toByteArray()
}
override fun decode(bytes: ByteArray): ByteArray {
val result = mutableListOf<Byte>()
for (i in bytes.indices step 3) {
val remaining = minOf(bytes.size - i, 3)
var value = 0
for (j in (0..<remaining).reversed()) {
val byte = bytes[i + j]
val index = alphabet.indexOf(byte)
if (index == -1) throw IllegalByteException(byte)
value = value * base + index
}
for (j in (0..<(remaining - 1)).reversed()) {
result += ((value shr (j * 8)) and 0xFF).toByte()
}
}
return result.toByteArray()
}
}

View File

@@ -0,0 +1,5 @@
package com.infendro.encoding
private val alphabet = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz".encodeToByteArray()
object Base56 : Encoding by NumericEncoding(alphabet)

View File

@@ -0,0 +1,5 @@
package com.infendro.encoding
private val alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".encodeToByteArray()
object Base58 : Encoding by NumericEncoding(alphabet)

View File

@@ -1,5 +1,5 @@
package com.infendro.encoding.numeric package com.infendro.encoding
private val alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".encodeToByteArray() private val alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".encodeToByteArray()
object Base62 : NumericEncoding(alphabet) object Base62 : Encoding by NumericEncoding(alphabet)

View File

@@ -0,0 +1,11 @@
package com.infendro.encoding
private val standard = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".encodeToByteArray()
private val url = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".encodeToByteArray()
private const val padding = '='.code.toByte()
object Base64 : Encoding by StreamEncoding(standard, padding) {
val STANDARD = this
object URL : Encoding by StreamEncoding(url)
}

View File

@@ -0,0 +1,5 @@
package com.infendro.encoding
private val alphabet = "01234567".encodeToByteArray()
object Base8 : Encoding by StreamEncoding(alphabet)

View File

@@ -1,15 +1,6 @@
package com.infendro.encoding package com.infendro.encoding
abstract class Encoding( interface Encoding {
val alphabet: ByteArray, fun encode(bytes: ByteArray): ByteArray
) { fun decode(bytes: ByteArray): ByteArray
init {
require(alphabet.isNotEmpty())
}
val base: Int
get() = alphabet.size
abstract fun encode(bytes: ByteArray): ByteArray
abstract fun decode(bytes: ByteArray): ByteArray
} }

View File

@@ -1,28 +1,26 @@
package com.infendro.encoding.numeric package com.infendro.encoding
import com.infendro.encoding.Encoding import com.infendro.encoding.exception.IllegalByteException
import com.infendro.encoding.util.BigInt import com.infendro.encoding.util.BigInt
import com.infendro.encoding.util.log2
import kotlin.math.ceil
open class NumericEncoding( class NumericEncoding internal constructor(
alphabet: ByteArray, private val alphabet: ByteArray,
) : Encoding(alphabet) { ) : Encoding {
private val base: Int = alphabet.size
override fun encode(bytes: ByteArray): ByteArray { override fun encode(bytes: ByteArray): ByteArray {
if (bytes.isEmpty()) return byteArrayOf() if (bytes.isEmpty()) return byteArrayOf()
val size = ceil(bytes.size * 8 / log2(base)).toInt() val result = mutableListOf<Byte>()
val result = ByteArray(size)
var x = BigInt.from(bytes) var x = BigInt.from(bytes)
var i = result.size
while (!x.isZero()) { while (!x.isZero()) {
val (quotient, remainder) = x.divRem(base) val (quotient, remainder) = x.divRem(base)
x = quotient x = quotient
result[--i] = alphabet[remainder] result += alphabet[remainder]
} }
return result.copyOfRange(i, result.size) return result.asReversed().toByteArray()
} }
override fun decode(bytes: ByteArray): ByteArray { override fun decode(bytes: ByteArray): ByteArray {
@@ -30,8 +28,9 @@ open class NumericEncoding(
var value = BigInt.zero var value = BigInt.zero
for (i in 0..<bytes.size) { for (i in 0..<bytes.size) {
val index = alphabet.indexOf(bytes[i]) val byte = bytes[i]
if (index == -1) throw Exception() //TODO val index = alphabet.indexOf(byte)
if (index == -1) throw IllegalByteException(byte)
value = value.timesAdd(base, index) value = value.timesAdd(base, index)
} }

View File

@@ -0,0 +1,80 @@
package com.infendro.encoding
import com.infendro.encoding.exception.IllegalByteException
import com.infendro.encoding.util.align
import com.infendro.encoding.util.ceilDiv
import com.infendro.encoding.util.lcm
import com.infendro.encoding.util.log2
class StreamEncoding internal constructor(
private val alphabet: ByteArray,
private val padding: Byte? = null,
) : Encoding {
private val base: Int = alphabet.size
private val bits: Int = log2(base).toInt()
private val block: Int = lcm(bits, 8) / bits
private val mask: Int = (0x01 shl bits) - 1
override fun encode(bytes: ByteArray): ByteArray {
val size = when (padding) {
null -> (bytes.size * 8).ceilDiv(bits)
else -> (bytes.size * 8).ceilDiv(bits).align(block)
}
val encoded = ByteArray(size)
var i = 0
var buffer = 0
var bufferBits = 0
for (byte in bytes) {
buffer = (buffer shl 8) or (byte.toInt() and 0xFF)
bufferBits += 8
while (bufferBits >= bits) {
val index = (buffer shr (bufferBits - bits)) and mask
bufferBits -= bits
encoded[i++] = alphabet[index]
}
}
if (bufferBits > 0) {
val index = (buffer shl (bits - bufferBits)) and mask
encoded[i++] = alphabet[index]
}
while (i < encoded.size) {
encoded[i++] = padding!!
}
return encoded
}
override fun decode(bytes: ByteArray): ByteArray {
val end = when (padding) {
null -> bytes.size
else -> when (val index = bytes.indexOf(padding)) {
-1 -> bytes.size
else -> index
}
}
val size = end * bits / 8
val decoded = ByteArray(size)
var i = 0
var buffer = 0
var bufferBits = 0
for (b in 0..<end) {
val byte = bytes[b]
val index = alphabet.indexOf(byte)
if (index == -1) throw IllegalByteException(byte)
buffer = (buffer shl bits) or index
bufferBits += bits
if (bufferBits >= 8) {
val byte = (buffer shr (bufferBits - 8)) and 0xFF
bufferBits -= 8
decoded[i++] = byte.toByte()
}
}
return decoded
}
}

View File

@@ -0,0 +1,5 @@
package com.infendro.encoding.exception
abstract class DecodeException : Exception() {
abstract override val message: String
}

View File

@@ -0,0 +1,12 @@
package com.infendro.encoding.exception
class IllegalByteException(
val byte: Byte,
) : DecodeException() {
override val message: String
get() {
val hex = "0x${byte.toHexString().padStart(2, '0')}"
val char = "'${byte.toInt().toChar()}'"
return "Illegal byte $hex ($char)."
}
}

View File

@@ -1,5 +0,0 @@
package com.infendro.encoding.stream
private val alphabet = "0123456789ABCDEF".encodeToByteArray()
object Base16 : StreamEncoding(alphabet)

View File

@@ -1,5 +0,0 @@
package com.infendro.encoding.stream
private val alphabet = "01".encodeToByteArray()
object Base2 : StreamEncoding(alphabet)

View File

@@ -1,6 +0,0 @@
package com.infendro.encoding.stream
private val alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".encodeToByteArray()
private const val padding = '='.code.toByte()
object Base64 : StreamEncoding(alphabet, padding)

View File

@@ -1,5 +0,0 @@
package com.infendro.encoding.stream
private val alphabet = "01234567".encodeToByteArray()
object Base8 : StreamEncoding(alphabet)

View File

@@ -1,96 +0,0 @@
package com.infendro.encoding.stream
import com.infendro.encoding.Encoding
import com.infendro.encoding.util.align
import com.infendro.encoding.util.divCeil
import com.infendro.encoding.util.lcm
import com.infendro.encoding.util.log2
open class StreamEncoding(
alphabet: ByteArray,
private val padding: Byte? = null,
) : Encoding(alphabet) {
init {
require(base % 2 == 0)
}
override fun encode(bytes: ByteArray): ByteArray {
val bits = log2(base).toInt()
val size = (bytes.size * 8).divCeil(bits)
val encodedSize = when (padding) {
null -> size
else -> {
val block = lcm(bits, 8) / bits
size.align(block)
}
}
val result = ByteArray(encodedSize)
var r = 0
var buffer = 0
var bufferBits = 0
for (i in bytes.indices) {
buffer = (buffer shl 8) + bytes[i]
bufferBits += 8
while (bufferBits >= bits) {
val offset = bufferBits - bits
val index = (buffer ushr offset)
buffer = buffer and ((base - 1) shl offset).inv()
bufferBits -= bits
result[r++] = alphabet[index]
}
}
if (bufferBits > 0) {
buffer = buffer shl (bits - bufferBits)
val index = buffer
result[r++] = alphabet[index]
}
if (padding != null) {
while (r < result.size) {
result[r++] = padding
}
}
return result
}
override fun decode(bytes: ByteArray): ByteArray {
val bits = log2(base).toInt()
val index = padding?.let { bytes.indexOf(it) } ?: -1
val decodedSize = when (index) {
-1 -> bytes.size * bits / 8
else -> index * bits / 8
}
val result = ByteArray(decodedSize)
var r = 0
var buffer = 0
var bufferBits = 0
for (i in bytes.indices) {
val byte = bytes[i]
if (byte == padding) break
val index = alphabet.indexOf(byte)
if (index == -1) throw Exception() //TODO
buffer = (buffer shl bits) + index.toByte()
bufferBits += bits
if (bufferBits >= 8) {
val offset = bufferBits - 8
val character = (buffer ushr offset).toByte()
buffer = buffer and (0xFF shl offset).inv()
bufferBits -= 8
result[r++] = character
}
}
return result
}
}

View File

@@ -49,40 +49,24 @@ internal class BigInt private constructor(
} }
fun toByteArray(): ByteArray { fun toByteArray(): ByteArray {
val msw = words.last() val bytes = ByteArray((words.size * 4) - words.last().countLeadingZeroBytes())
val mswBytes = when { for (i in bytes.indices) {
(msw ushr 24) != 0 -> 4 val (wi, bi) = (bytes.lastIndex - i).divRem(4)
(msw ushr 16) != 0 -> 3 bytes[i] = (words[wi] ushr (bi * 8)).toByte()
(msw ushr 8) != 0 -> 2
else -> 1
} }
val size = ((words.size - 1) * 4) + mswBytes return bytes
val result = ByteArray(size)
for (i in 0..<size) {
val index = size - 1 - i
val shift = (index % 4) * 8
result[i] = (words[index / 4] ushr shift).toByte()
}
return result
} }
companion object { companion object {
val zero: BigInt val zero: BigInt
get() = BigInt(intArrayOf(0)) get() = BigInt(intArrayOf(0))
fun from(value: ByteArray): BigInt { fun from(bytes: ByteArray): BigInt {
val size = value.size.divCeil(4) val words = IntArray(bytes.size.ceilDiv(4))
val words = IntArray(size) for (i in bytes.indices) {
val (wi, bi) = (bytes.lastIndex - i).divRem(4)
for (i in value.indices) { words[wi] = words[wi] or ((bytes[i].toInt() and 0xFF) shl (bi * 8))
val byte = value[i].toInt() and 0xFF
val index = value.lastIndex - i
val shift = (index % 4) * 8
words[index / 4] = words[index / 4] or (byte shl shift)
} }
return BigInt(words) return BigInt(words)
} }
} }

View File

@@ -0,0 +1,7 @@
package com.infendro.encoding.util
fun Int.divRem(divisor: Int): Pair<Int, Int> =
Pair(this / divisor, this % divisor)
fun Int.countLeadingZeroBytes(): Int =
countLeadingZeroBits() / 8

View File

@@ -2,14 +2,14 @@ package com.infendro.encoding.util
import kotlin.math.log2 import kotlin.math.log2
internal fun log2(value: Int): Double = internal fun Int.ceilDiv(n: Int): Int =
log2(value.toDouble())
internal fun Int.divCeil(n: Int): Int =
(this + n - 1) / n (this + n - 1) / n
internal fun Int.align(n: Int): Int = internal fun Int.align(n: Int): Int =
divCeil(n) * n ceilDiv(n) * n
internal fun log2(value: Int): Double =
log2(value.toDouble())
internal fun gcd(a: Int, b: Int): Int { internal fun gcd(a: Int, b: Int): Int {
var x = a var x = a

View File

@@ -0,0 +1,36 @@
package com.infendro.encoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base10 Test` {
val encoding: Encoding
get() = Base10
val original = "Hello World!".encodeToByteArray()
val encoded = "22405534230753928650781647905".encodeToByteArray()
@Test
fun `encode empty`() {
val actual = encoding.encode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun `decode empty`() {
val actual = encoding.decode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun encode() {
val actual = encoding.encode(original)
assertContentEquals(encoded, actual)
}
@Test
fun decode() {
val actual = encoding.decode(encoded)
assertContentEquals(original, actual)
}
}

View File

@@ -1,35 +1,36 @@
package com.infendro.encoding package com.infendro.encoding
import com.infendro.encoding.stream.Base16
import com.infendro.encoding.stream.StreamEncoding
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertContentEquals import kotlin.test.assertContentEquals
class `Base16 Test` { class `Base16 Test` {
val encoding: StreamEncoding val encoding: Encoding
get() = Base16 get() = Base16
val `Hello World!` = byteArrayOf( val original = "Hello World!".encodeToByteArray()
0x48, 0x65, 0x6c, 0x6c, val encoded = "48656C6C6F20576F726C6421".encodeToByteArray()
0x6f, 0x20, 0x57, 0x6f,
0x72, 0x6c, 0x64, 0x21,
)
@Test @Test
fun `encode empty ByteArray`() { fun `encode empty`() {
val expected = byteArrayOf()
val actual = encoding.encode(byteArrayOf()) val actual = encoding.encode(byteArrayOf())
assertContentEquals(expected, actual) assertContentEquals(byteArrayOf(), actual)
} }
@Test @Test
fun `encode "Hello World!"`() { fun `decode empty`() {
val expected = byteArrayOf( val actual = encoding.decode(byteArrayOf())
0x34, 0x38, 0x36, 0x35, 0x36, 0x63, 0x36, 0x63, assertContentEquals(byteArrayOf(), actual)
0x36, 0x66, 0x32, 0x30, 0x35, 0x37, 0x36, 0x66, }
0x37, 0x32, 0x36, 0x63, 0x36, 0x34, 0x32, 0x31,
) @Test
val actual = encoding.encode(`Hello World!`) fun encode() {
assertContentEquals(expected, actual) val actual = encoding.encode(original)
assertContentEquals(encoded, actual)
}
@Test
fun decode() {
val actual = encoding.decode(encoded)
assertContentEquals(original, actual)
} }
} }

View File

@@ -1,44 +1,36 @@
package com.infendro.encoding package com.infendro.encoding
import com.infendro.encoding.stream.Base2
import com.infendro.encoding.stream.StreamEncoding
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertContentEquals import kotlin.test.assertContentEquals
class `Base2 Test` { class `Base2 Test` {
val encoding: StreamEncoding val encoding: Encoding
get() = Base2 get() = Base2
val `Hello World!` = byteArrayOf( val original = "Hello World!".encodeToByteArray()
0x48, 0x65, 0x6c, 0x6c, val encoded = "010010000110010101101100011011000110111100100000010101110110111101110010011011000110010000100001".encodeToByteArray()
0x6f, 0x20, 0x57, 0x6f,
0x72, 0x6c, 0x64, 0x21,
)
@Test @Test
fun `encode empty ByteArray`() { fun `encode empty`() {
val expected = byteArrayOf()
val actual = encoding.encode(byteArrayOf()) val actual = encoding.encode(byteArrayOf())
assertContentEquals(expected, actual) assertContentEquals(byteArrayOf(), actual)
} }
@Test @Test
fun `encode "Hello World!"`() { fun `decode empty`() {
val expected = byteArrayOf( val actual = encoding.decode(byteArrayOf())
0x30, 0x31, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, assertContentEquals(byteArrayOf(), actual)
0x30, 0x31, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, }
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30,
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30, @Test
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x31, 0x31, fun encode() {
0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, val actual = encoding.encode(original)
0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x31, assertContentEquals(encoded, actual)
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x31, 0x31, }
0x30, 0x31, 0x31, 0x31, 0x30, 0x30, 0x31, 0x30,
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30, @Test
0x30, 0x31, 0x31, 0x30, 0x30, 0x31, 0x30, 0x30, fun decode() {
0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x31, val actual = encoding.decode(encoded)
) assertContentEquals(original, actual)
val actual = encoding.encode(`Hello World!`)
assertContentEquals(expected, actual)
} }
} }

View File

@@ -1,35 +1,36 @@
package com.infendro.encoding package com.infendro.encoding
import com.infendro.encoding.stream.Base32
import com.infendro.encoding.stream.StreamEncoding
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertContentEquals import kotlin.test.assertContentEquals
class `Base32 Test` { class `Base32 Test` {
val encoding: StreamEncoding val encoding: Encoding
get() = Base32 get() = Base32
val `Hello World!` = byteArrayOf( val original = "Hello World!".encodeToByteArray()
0x48, 0x65, 0x6c, 0x6c, val encoded = "JBSWY3DPEBLW64TMMQQQ====".encodeToByteArray()
0x6f, 0x20, 0x57, 0x6f,
0x72, 0x6c, 0x64, 0x21,
)
@Test @Test
fun `encode empty ByteArray`() { fun `encode empty`() {
val expected = byteArrayOf()
val actual = encoding.encode(byteArrayOf()) val actual = encoding.encode(byteArrayOf())
assertContentEquals(expected, actual) assertContentEquals(byteArrayOf(), actual)
} }
@Test @Test
fun `encode "Hello World!"`() { fun `decode empty`() {
val expected = byteArrayOf( val actual = encoding.decode(byteArrayOf())
0x4a, 0x42, 0x53, 0x57, 0x59, 0x33, 0x44, 0x50, assertContentEquals(byteArrayOf(), actual)
0x45, 0x42, 0x4c, 0x57, 0x36, 0x34, 0x54, 0x4d, }
0x4d, 0x51, 0x51, 0x51, 0x3d, 0x3d, 0x3d, 0x3d,
) @Test
val actual = encoding.encode(`Hello World!`) fun encode() {
assertContentEquals(expected, actual) val actual = encoding.encode(original)
assertContentEquals(encoded, actual)
}
@Test
fun decode() {
val actual = encoding.decode(encoded)
assertContentEquals(original, actual)
} }
} }

View File

@@ -0,0 +1,36 @@
package com.infendro.encoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base36 Test` {
val encoding: Encoding
get() = Base36
val original = "Hello World!".encodeToByteArray()
val encoded = "2678LX5GVMSV1DRO9B5".encodeToByteArray()
@Test
fun `encode empty`() {
val actual = encoding.encode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun `decode empty`() {
val actual = encoding.decode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun encode() {
val actual = encoding.encode(original)
assertContentEquals(encoded, actual)
}
@Test
fun decode() {
val actual = encoding.decode(encoded)
assertContentEquals(original, actual)
}
}

View File

@@ -0,0 +1,36 @@
package com.infendro.encoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base45 Test` {
val encoding: Encoding
get() = Base45
val original = "Hello World!".encodeToByteArray()
val encoded = "%69 VD82EI2B.KESTC".encodeToByteArray()
@Test
fun `encode empty`() {
val actual = encoding.encode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun `decode empty`() {
val actual = encoding.decode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun encode() {
val actual = encoding.encode(original)
assertContentEquals(encoded, actual)
}
@Test
fun decode() {
val actual = encoding.decode(encoded)
assertContentEquals(original, actual)
}
}

View File

@@ -0,0 +1,36 @@
package com.infendro.encoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base56 Test` {
val encoding: Encoding
get() = Base56
val original = "Hello World!".encodeToByteArray()
val encoded = "4Q9SNpVv4JrdwvjKj".encodeToByteArray()
@Test
fun `encode empty`() {
val actual = encoding.encode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun `decode empty`() {
val actual = encoding.decode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun encode() {
val actual = encoding.encode(original)
assertContentEquals(encoded, actual)
}
@Test
fun decode() {
val actual = encoding.decode(encoded)
assertContentEquals(original, actual)
}
}

View File

@@ -0,0 +1,36 @@
package com.infendro.encoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base58 Test` {
val encoding: Encoding
get() = Base58
val original = "Hello World!".encodeToByteArray()
val encoded = "2NEpo7TZRRrLZSi2U".encodeToByteArray()
@Test
fun `encode empty`() {
val actual = encoding.encode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun `decode empty`() {
val actual = encoding.decode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun encode() {
val actual = encoding.encode(original)
assertContentEquals(encoded, actual)
}
@Test
fun decode() {
val actual = encoding.decode(encoded)
assertContentEquals(original, actual)
}
}

View File

@@ -0,0 +1,36 @@
package com.infendro.encoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base62 Test` {
val encoding: Encoding
get() = Base62
val original = "Hello World!".encodeToByteArray()
val encoded = "T8dgcjRGkZ3aysdN".encodeToByteArray()
@Test
fun `encode empty`() {
val actual = encoding.encode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun `decode empty`() {
val actual = encoding.decode(byteArrayOf())
assertContentEquals(byteArrayOf(), actual)
}
@Test
fun encode() {
val actual = encoding.encode(original)
assertContentEquals(encoded, actual)
}
@Test
fun decode() {
val actual = encoding.decode(encoded)
assertContentEquals(original, actual)
}
}

View File

@@ -1,34 +1,36 @@
package com.infendro.encoding package com.infendro.encoding
import com.infendro.encoding.stream.Base64
import com.infendro.encoding.stream.StreamEncoding
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertContentEquals import kotlin.test.assertContentEquals
class `Base64 Test` { class `Base64 Test` {
val encoding: StreamEncoding val encoding: Encoding
get() = Base64 get() = Base64
val `Hello World!` = byteArrayOf( val original = "Hello World!".encodeToByteArray()
0x48, 0x65, 0x6c, 0x6c, val encoded = "SGVsbG8gV29ybGQh".encodeToByteArray()
0x6f, 0x20, 0x57, 0x6f,
0x72, 0x6c, 0x64, 0x21,
)
@Test @Test
fun `encode empty ByteArray`() { fun `encode empty`() {
val expected = byteArrayOf()
val actual = encoding.encode(byteArrayOf()) val actual = encoding.encode(byteArrayOf())
assertContentEquals(expected, actual) assertContentEquals(byteArrayOf(), actual)
} }
@Test @Test
fun `encode "Hello World!"`() { fun `decode empty`() {
val expected = byteArrayOf( val actual = encoding.decode(byteArrayOf())
0x53, 0x47, 0x56, 0x73, 0x62, 0x47, 0x38, 0x67, assertContentEquals(byteArrayOf(), actual)
0x56, 0x32, 0x39, 0x79, 0x62, 0x47, 0x51, 0x68, }
)
val actual = encoding.encode(`Hello World!`) @Test
assertContentEquals(expected, actual) fun encode() {
val actual = encoding.encode(original)
assertContentEquals(encoded, actual)
}
@Test
fun decode() {
val actual = encoding.decode(encoded)
assertContentEquals(original, actual)
} }
} }

View File

@@ -1,36 +1,36 @@
package com.infendro.encoding package com.infendro.encoding
import com.infendro.encoding.stream.Base8
import com.infendro.encoding.stream.StreamEncoding
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertContentEquals import kotlin.test.assertContentEquals
class `Base8 Test` { class `Base8 Test` {
val encoding: StreamEncoding val encoding: Encoding
get() = Base8 get() = Base8
val `Hello World!` = byteArrayOf( val original = "Hello World!".encodeToByteArray()
0x48, 0x65, 0x6c, 0x6c, val encoded = "22062554330674402566756233062041".encodeToByteArray()
0x6f, 0x20, 0x57, 0x6f,
0x72, 0x6c, 0x64, 0x21,
)
@Test @Test
fun `encode empty ByteArray`() { fun `encode empty`() {
val expected = byteArrayOf()
val actual = encoding.encode(byteArrayOf()) val actual = encoding.encode(byteArrayOf())
assertContentEquals(expected, actual) assertContentEquals(byteArrayOf(), actual)
} }
@Test @Test
fun `encode "Hello World!"`() { fun `decode empty`() {
val expected = byteArrayOf( val actual = encoding.decode(byteArrayOf())
0x32, 0x32, 0x30, 0x36, 0x32, 0x35, 0x35, 0x34, assertContentEquals(byteArrayOf(), actual)
0x33, 0x33, 0x30, 0x36, 0x37, 0x34, 0x34, 0x30, }
0x32, 0x35, 0x36, 0x36, 0x37, 0x35, 0x36, 0x32,
0x33, 0x33, 0x30, 0x36, 0x32, 0x30, 0x34, 0x31, @Test
) fun encode() {
val actual = encoding.encode(`Hello World!`) val actual = encoding.encode(original)
assertContentEquals(expected, actual) assertContentEquals(encoded, actual)
}
@Test
fun decode() {
val actual = encoding.decode(encoded)
assertContentEquals(original, actual)
} }
} }