Compare commits

...

3 Commits

Author SHA1 Message Date
83fd77c8ee split ci 2026-01-17 12:39:30 +01:00
456f33f2d9 bump version to 1.3.0 2026-01-17 12:36:16 +01:00
55faf1d670 implement numeric encodings, optimize 2026-01-17 12:27:41 +01:00
28 changed files with 447 additions and 366 deletions

View File

@@ -1,92 +0,0 @@
on:
push:
branches: [ develop, main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: linux
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '24'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4
with:
key: gradle-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: gradle-
path: |
~/.gradle/caches/
~/.gradle/wrapper/
- name: Cache Konan
uses: actions/cache@v4
with:
key: konan-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: konan-
path: |
~/.konan/
- name: Cache Node
uses: actions/cache@v4
with:
key: node-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: node-
path: |
~/.gradle/nodejs
~/.gradle/yarn
- name: Test
run: ./gradlew allTests
publish:
if: ${{ github.event_name == 'push' && github.ref_name == 'main' }}
needs: test
runs-on: linux
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '24'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4
with:
key: gradle-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: gradle-
path: |
~/.gradle/caches/
~/.gradle/wrapper/
- name: Cache Konan
uses: actions/cache@v4
with:
key: konan-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: konan-
path: |
~/.konan/
- name: Cache Node
uses: actions/cache@v4
with:
key: node-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: node-
path: |
~/.gradle/nodejs
~/.gradle/yarn
- name: Publish
run: ./gradlew publish
env:
INFENDRO__TOKEN: ${{ secrets.TOKEN }}

View File

@@ -0,0 +1,47 @@
on:
push:
branches: [ main ]
jobs:
publish:
runs-on: linux
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '24'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4
with:
key: gradle-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: gradle
path: |
~/.gradle/caches/
~/.gradle/wrapper/
- name: Cache Konan
uses: actions/cache@v4
with:
key: konan-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: konan
path: |
~/.konan/
- name: Cache Node
uses: actions/cache@v4
with:
key: node-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: node
path: |
~/.gradle/nodejs
~/.gradle/yarn
- name: Publish
run: ./gradlew publish
env:
INFENDRO__TOKEN: ${{ secrets.TOKEN }}

View File

@@ -0,0 +1,28 @@
on:
pull_request:
branches: [ main ]
jobs:
test:
runs-on: linux
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '24'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4
with:
key: gradle-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: gradle
path: |
~/.gradle/caches/
~/.gradle/wrapper/
- name: Test
run: ./gradlew jvmTest

View File

@@ -7,17 +7,10 @@ Supported encodings:
- Base8 (octal)
- Base16 (hexadecimal)
- Base32
- Base36
- Base62
- Base64
## Targets
| Target | Status |
|------------------|---------------|
| JVM | Supported |
| JavaScript | Supported |
| Native (Linux) | Supported |
| Native (Windows) | Not Supported |
## Installation
Add the following to your `build.gradle.kts`.
@@ -28,23 +21,19 @@ repositories {
}
dependencies {
implementation("com.infendro:encoding:1.2.0")
implementation("com.infendro:encoding:1.3.0")
}
```
## Usage
```kotlin
import com.infendro.encoding.Base16
fun main() {
// the string to encode
val test = "Hello World!"
.encodeToByteArray().asUByteArray()
val test = "Hello World!".encodeToByteArray()
// encode the string with the desired encoding
val encoded = Base16.encode(test)
.asByteArray().decodeToString()
val encoded = Base16.encode(test).decodeToString()
println(encoded) // 48656c6c6f20576f726c6421
}

View File

@@ -1,8 +1,11 @@
@file:OptIn(ExperimentalWasmDsl::class)
import com.infendro.plugin.infendro
import com.infendro.plugin.token
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
group = "com.infendro"
version = "1.2.0"
version = "1.3.0"
plugins {
alias(libs.plugins.infendro)
@@ -13,9 +16,13 @@ plugins {
kotlin {
jvm()
linuxX64()
js {
nodejs()
}
linuxArm64()
mingwX64()
macosX64()
macosArm64()
js { nodejs() }
wasmJs { nodejs() }
wasmWasi { nodejs() }
repositories {
mavenCentral()
@@ -26,10 +33,6 @@ kotlin {
implementation(libs.test)
}
}
compilerOptions {
freeCompilerArgs.add("-opt-in=kotlin.ExperimentalUnsignedTypes")
}
}
publishing.repositories {

View File

@@ -1,6 +1,6 @@
[versions]
infendro = "1.0.0"
kotlin = "2.2.21"
kotlin = "2.3.0"
[plugins]
infendro = { id = "com.infendro.plugin", version.ref = "infendro" }

View File

@@ -1,16 +0,0 @@
package com.infendro.encoding
object Base16 : Encoding() {
private val CHARACTERS = ubyteArrayOf(
0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
0x38U, 0x39U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U,
)
override fun encode(
bytes: UByteArray,
) = encode(bytes, CHARACTERS)
override fun decode(
bytes: UByteArray,
) = decode(bytes, CHARACTERS)
}

View File

@@ -1,15 +0,0 @@
package com.infendro.encoding
object Base2 : Encoding() {
private val CHARACTERS = ubyteArrayOf(
0x30U, 0x31U,
)
override fun encode(
bytes: UByteArray,
) = encode(bytes, CHARACTERS)
override fun decode(
bytes: UByteArray,
) = decode(bytes, CHARACTERS)
}

View File

@@ -1,19 +0,0 @@
package com.infendro.encoding
object Base32 : Encoding() {
private val CHARACTERS = ubyteArrayOf(
0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U,
0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U,
0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U,
0x59U, 0x5aU, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
)
private const val PADDING: UByte = 0x3dU
override fun encode(
bytes: UByteArray,
) = encode(bytes, CHARACTERS, PADDING)
override fun decode(
bytes: UByteArray,
) = decode(bytes, CHARACTERS, PADDING)
}

View File

@@ -1,23 +0,0 @@
package com.infendro.encoding
object Base64 : Encoding() {
private val CHARACTERS = ubyteArrayOf(
0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U,
0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U,
0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U,
0x59U, 0x5aU, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U,
0x67U, 0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU,
0x6fU, 0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U,
0x77U, 0x78U, 0x79U, 0x7aU, 0x30U, 0x31U, 0x32U, 0x33U,
0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U, 0x2bU, 0x2fU,
)
private const val PADDING: UByte = 0x3dU
override fun encode(
bytes: UByteArray,
) = encode(bytes, CHARACTERS, PADDING)
override fun decode(
bytes: UByteArray,
) = decode(bytes, CHARACTERS, PADDING)
}

View File

@@ -1,15 +0,0 @@
package com.infendro.encoding
object Base8 : Encoding() {
private val CHARACTERS = ubyteArrayOf(
0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
)
override fun encode(
bytes: UByteArray,
) = encode(bytes, CHARACTERS)
override fun decode(
bytes: UByteArray,
) = decode(bytes, CHARACTERS)
}

View File

@@ -1,92 +1,15 @@
package com.infendro.encoding
import com.infendro.encoding.util.lcm
import com.infendro.encoding.util.log2
import kotlin.math.pow
sealed class Encoding {
abstract fun encode(
bytes: UByteArray,
): UByteArray
abstract fun decode(
bytes: UByteArray,
): UByteArray
protected fun encode(
bytes: UByteArray,
characters: UByteArray,
padding: UByte? = null,
): UByteArray {
val length = log2(characters.size).toInt()
val mask = (2.0.pow(length) - 1).toUInt()
val encoded = mutableListOf<UByte>()
var buffer = 0U
var bits = 0
for (byte in bytes) {
buffer = (buffer shl 8) + byte
bits += 8
while (bits >= length) {
val offset = bits - length
val index = (buffer shr offset).toInt()
buffer = buffer and (mask shl offset).inv()
bits -= length
encoded.add(characters[index])
}
}
if (bits > 0) {
buffer = buffer shl (length - bits)
val index = buffer.toInt()
encoded.add(characters[index])
abstract class Encoding(
val alphabet: ByteArray,
) {
init {
require(alphabet.isNotEmpty())
}
if (padding != null) {
val block = lcm(length, 8) / length
while (encoded.size % block != 0) {
encoded.add(padding)
}
}
val base: Int
get() = alphabet.size
return encoded.toUByteArray()
}
protected fun decode(
bytes: UByteArray,
characters: UByteArray,
padding: UByte? = null,
): UByteArray {
val length = log2(characters.size).toInt()
val mask = 0xffU
val decoded = mutableListOf<UByte>()
var buffer = 0U
var bits = 0
for (byte in bytes) {
if (byte == padding) break
val index = characters.indexOf(byte)
if (index == -1) throw Exception()
buffer = (buffer shl length) + index.toUByte()
bits += length
if (bits >= 8) {
val offset = bits - 8
val character = (buffer shr offset).toUByte()
buffer = buffer and (mask shl offset).inv()
bits -= 8
decoded.add(character)
}
}
return decoded.toUByteArray()
}
abstract fun encode(bytes: ByteArray): ByteArray
abstract fun decode(bytes: ByteArray): ByteArray
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,96 @@
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

@@ -0,0 +1,89 @@
package com.infendro.encoding.util
internal class BigInt private constructor(
val words: IntArray,
) {
init {
require(words.isNotEmpty())
}
fun isZero(): Boolean = words.all { it == 0 }
fun timesAdd(multiplier: Int, addend: Int): BigInt {
val product = IntArray(words.size)
var carry = addend
for (i in words.indices) {
val current = (words[i].toLong() and 0xFFFFFFFFL) * multiplier + carry
product[i] = current.toInt()
carry = (current ushr 32).toInt()
}
when {
carry > 0 -> {
val expanded = product.copyOf(product.size + 1)
expanded[product.size] = carry
return BigInt(expanded)
}
else -> return BigInt(product)
}
}
fun divRem(divisor: Int): Pair<BigInt, Int> {
val quotient = IntArray(words.size)
var remainder = 0
for (i in words.indices.reversed()) {
val current = (remainder.toLong() shl 32) or (words[i].toLong() and 0xFFFFFFFFL)
quotient[i] = (current / divisor.toLong()).toInt()
remainder = (current % divisor.toLong()).toInt()
}
when {
quotient.size > 1 && quotient.last() == 0 -> {
val contracted = quotient.copyOfRange(0, quotient.size - 1)
return Pair(BigInt(contracted), remainder)
}
else -> return Pair(BigInt(quotient), remainder)
}
}
fun toByteArray(): ByteArray {
val msw = words.last()
val mswBytes = when {
(msw ushr 24) != 0 -> 4
(msw ushr 16) != 0 -> 3
(msw ushr 8) != 0 -> 2
else -> 1
}
val size = ((words.size - 1) * 4) + mswBytes
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 {
val zero: BigInt
get() = BigInt(intArrayOf(0))
fun from(value: ByteArray): BigInt {
val size = value.size.divCeil(4)
val words = IntArray(size)
for (i in value.indices) {
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)
}
}
}

View File

@@ -2,14 +2,16 @@ package com.infendro.encoding.util
import kotlin.math.log2
internal fun log2(
value: Int,
) = log2(value.toDouble())
internal fun log2(value: Int): Double =
log2(value.toDouble())
internal fun gcd(
a: Int,
b: Int,
): Int {
internal fun Int.divCeil(n: Int): Int =
(this + n - 1) / n
internal fun Int.align(n: Int): Int =
divCeil(n) * n
internal fun gcd(a: Int, b: Int): Int {
var x = a
var y = b
while (y != 0) {
@@ -20,9 +22,6 @@ internal fun gcd(
return x
}
internal fun lcm(
a: Int,
b: Int,
): Int {
internal fun lcm(a: Int, b: Int): Int {
return (a * b) / gcd(a, b)
}

View File

@@ -1,31 +1,33 @@
package com.infendro.encoding
import com.infendro.encoding.stream.Base16
import com.infendro.encoding.stream.StreamEncoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base16 Test` {
val encoding: Encoding
val encoding: StreamEncoding
get() = Base16
val `Hello World!` = ubyteArrayOf(
0x48U, 0x65U, 0x6cU, 0x6cU,
0x6fU, 0x20U, 0x57U, 0x6fU,
0x72U, 0x6cU, 0x64U, 0x21U,
val `Hello World!` = byteArrayOf(
0x48, 0x65, 0x6c, 0x6c,
0x6f, 0x20, 0x57, 0x6f,
0x72, 0x6c, 0x64, 0x21,
)
@Test
fun `encode empty ByteArray`() {
val expected = ubyteArrayOf()
val actual = encoding.encode(ubyteArrayOf())
val expected = byteArrayOf()
val actual = encoding.encode(byteArrayOf())
assertContentEquals(expected, actual)
}
@Test
fun `encode "Hello World!"`() {
val expected = ubyteArrayOf(
0x34U, 0x38U, 0x36U, 0x35U, 0x36U, 0x63U, 0x36U, 0x63U,
0x36U, 0x66U, 0x32U, 0x30U, 0x35U, 0x37U, 0x36U, 0x66U,
0x37U, 0x32U, 0x36U, 0x63U, 0x36U, 0x34U, 0x32U, 0x31U,
val expected = byteArrayOf(
0x34, 0x38, 0x36, 0x35, 0x36, 0x63, 0x36, 0x63,
0x36, 0x66, 0x32, 0x30, 0x35, 0x37, 0x36, 0x66,
0x37, 0x32, 0x36, 0x63, 0x36, 0x34, 0x32, 0x31,
)
val actual = encoding.encode(`Hello World!`)
assertContentEquals(expected, actual)

View File

@@ -1,40 +1,42 @@
package com.infendro.encoding
import com.infendro.encoding.stream.Base2
import com.infendro.encoding.stream.StreamEncoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base2 Test` {
val encoding: Encoding
val encoding: StreamEncoding
get() = Base2
val `Hello World!` = ubyteArrayOf(
0x48U, 0x65U, 0x6cU, 0x6cU,
0x6fU, 0x20U, 0x57U, 0x6fU,
0x72U, 0x6cU, 0x64U, 0x21U,
val `Hello World!` = byteArrayOf(
0x48, 0x65, 0x6c, 0x6c,
0x6f, 0x20, 0x57, 0x6f,
0x72, 0x6c, 0x64, 0x21,
)
@Test
fun `encode empty ByteArray`() {
val expected = ubyteArrayOf()
val actual = encoding.encode(ubyteArrayOf())
val expected = byteArrayOf()
val actual = encoding.encode(byteArrayOf())
assertContentEquals(expected, actual)
}
@Test
fun `encode "Hello World!"`() {
val expected = ubyteArrayOf(
0x30U, 0x31U, 0x30U, 0x30U, 0x31U, 0x30U, 0x30U, 0x30U,
0x30U, 0x31U, 0x31U, 0x30U, 0x30U, 0x31U, 0x30U, 0x31U,
0x30U, 0x31U, 0x31U, 0x30U, 0x31U, 0x31U, 0x30U, 0x30U,
0x30U, 0x31U, 0x31U, 0x30U, 0x31U, 0x31U, 0x30U, 0x30U,
0x30U, 0x31U, 0x31U, 0x30U, 0x31U, 0x31U, 0x31U, 0x31U,
0x30U, 0x30U, 0x31U, 0x30U, 0x30U, 0x30U, 0x30U, 0x30U,
0x30U, 0x31U, 0x30U, 0x31U, 0x30U, 0x31U, 0x31U, 0x31U,
0x30U, 0x31U, 0x31U, 0x30U, 0x31U, 0x31U, 0x31U, 0x31U,
0x30U, 0x31U, 0x31U, 0x31U, 0x30U, 0x30U, 0x31U, 0x30U,
0x30U, 0x31U, 0x31U, 0x30U, 0x31U, 0x31U, 0x30U, 0x30U,
0x30U, 0x31U, 0x31U, 0x30U, 0x30U, 0x31U, 0x30U, 0x30U,
0x30U, 0x30U, 0x31U, 0x30U, 0x30U, 0x30U, 0x30U, 0x31U,
val expected = byteArrayOf(
0x30, 0x31, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30,
0x30, 0x31, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31,
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30,
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30,
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x31, 0x31,
0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x31,
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x31, 0x31,
0x30, 0x31, 0x31, 0x31, 0x30, 0x30, 0x31, 0x30,
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30,
0x30, 0x31, 0x31, 0x30, 0x30, 0x31, 0x30, 0x30,
0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x31,
)
val actual = encoding.encode(`Hello World!`)
assertContentEquals(expected, actual)

View File

@@ -1,31 +1,33 @@
package com.infendro.encoding
import com.infendro.encoding.stream.Base32
import com.infendro.encoding.stream.StreamEncoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base32 Test` {
val encoding: Encoding
val encoding: StreamEncoding
get() = Base32
val `Hello World!` = ubyteArrayOf(
0x48U, 0x65U, 0x6cU, 0x6cU,
0x6fU, 0x20U, 0x57U, 0x6fU,
0x72U, 0x6cU, 0x64U, 0x21U,
val `Hello World!` = byteArrayOf(
0x48, 0x65, 0x6c, 0x6c,
0x6f, 0x20, 0x57, 0x6f,
0x72, 0x6c, 0x64, 0x21,
)
@Test
fun `encode empty ByteArray`() {
val expected = ubyteArrayOf()
val actual = encoding.encode(ubyteArrayOf())
val expected = byteArrayOf()
val actual = encoding.encode(byteArrayOf())
assertContentEquals(expected, actual)
}
@Test
fun `encode "Hello World!"`() {
val expected = ubyteArrayOf(
0x4aU, 0x42U, 0x53U, 0x57U, 0x59U, 0x33U, 0x44U, 0x50U,
0x45U, 0x42U, 0x4cU, 0x57U, 0x36U, 0x34U, 0x54U, 0x4dU,
0x4dU, 0x51U, 0x51U, 0x51U, 0x3dU, 0x3dU, 0x3dU, 0x3dU,
val expected = byteArrayOf(
0x4a, 0x42, 0x53, 0x57, 0x59, 0x33, 0x44, 0x50,
0x45, 0x42, 0x4c, 0x57, 0x36, 0x34, 0x54, 0x4d,
0x4d, 0x51, 0x51, 0x51, 0x3d, 0x3d, 0x3d, 0x3d,
)
val actual = encoding.encode(`Hello World!`)
assertContentEquals(expected, actual)

View File

@@ -1,30 +1,32 @@
package com.infendro.encoding
import com.infendro.encoding.stream.Base64
import com.infendro.encoding.stream.StreamEncoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base64 Test` {
val encoding: Encoding
val encoding: StreamEncoding
get() = Base64
val `Hello World!` = ubyteArrayOf(
0x48U, 0x65U, 0x6cU, 0x6cU,
0x6fU, 0x20U, 0x57U, 0x6fU,
0x72U, 0x6cU, 0x64U, 0x21U,
val `Hello World!` = byteArrayOf(
0x48, 0x65, 0x6c, 0x6c,
0x6f, 0x20, 0x57, 0x6f,
0x72, 0x6c, 0x64, 0x21,
)
@Test
fun `encode empty ByteArray`() {
val expected = ubyteArrayOf()
val actual = encoding.encode(ubyteArrayOf())
val expected = byteArrayOf()
val actual = encoding.encode(byteArrayOf())
assertContentEquals(expected, actual)
}
@Test
fun `encode "Hello World!"`() {
val expected = ubyteArrayOf(
0x53U, 0x47U, 0x56U, 0x73U, 0x62U, 0x47U, 0x38U, 0x67U,
0x56U, 0x32U, 0x39U, 0x79U, 0x62U, 0x47U, 0x51U, 0x68U,
val expected = byteArrayOf(
0x53, 0x47, 0x56, 0x73, 0x62, 0x47, 0x38, 0x67,
0x56, 0x32, 0x39, 0x79, 0x62, 0x47, 0x51, 0x68,
)
val actual = encoding.encode(`Hello World!`)
assertContentEquals(expected, actual)

View File

@@ -1,32 +1,34 @@
package com.infendro.encoding
import com.infendro.encoding.stream.Base8
import com.infendro.encoding.stream.StreamEncoding
import kotlin.test.Test
import kotlin.test.assertContentEquals
class `Base8 Test` {
val encoding: Encoding
val encoding: StreamEncoding
get() = Base8
val `Hello World!` = ubyteArrayOf(
0x48U, 0x65U, 0x6cU, 0x6cU,
0x6fU, 0x20U, 0x57U, 0x6fU,
0x72U, 0x6cU, 0x64U, 0x21U,
val `Hello World!` = byteArrayOf(
0x48, 0x65, 0x6c, 0x6c,
0x6f, 0x20, 0x57, 0x6f,
0x72, 0x6c, 0x64, 0x21,
)
@Test
fun `encode empty ByteArray`() {
val expected = ubyteArrayOf()
val actual = encoding.encode(ubyteArrayOf())
val expected = byteArrayOf()
val actual = encoding.encode(byteArrayOf())
assertContentEquals(expected, actual)
}
@Test
fun `encode "Hello World!"`() {
val expected = ubyteArrayOf(
0x32U, 0x32U, 0x30U, 0x36U, 0x32U, 0x35U, 0x35U, 0x34U,
0x33U, 0x33U, 0x30U, 0x36U, 0x37U, 0x34U, 0x34U, 0x30U,
0x32U, 0x35U, 0x36U, 0x36U, 0x37U, 0x35U, 0x36U, 0x32U,
0x33U, 0x33U, 0x30U, 0x36U, 0x32U, 0x30U, 0x34U, 0x31U,
val expected = byteArrayOf(
0x32, 0x32, 0x30, 0x36, 0x32, 0x35, 0x35, 0x34,
0x33, 0x33, 0x30, 0x36, 0x37, 0x34, 0x34, 0x30,
0x32, 0x35, 0x36, 0x36, 0x37, 0x35, 0x36, 0x32,
0x33, 0x33, 0x30, 0x36, 0x32, 0x30, 0x34, 0x31,
)
val actual = encoding.encode(`Hello World!`)
assertContentEquals(expected, actual)