Compare commits
3 Commits
45d74d9cff
...
83fd77c8ee
| Author | SHA1 | Date | |
|---|---|---|---|
|
83fd77c8ee
|
|||
|
456f33f2d9
|
|||
|
55faf1d670
|
@@ -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 }}
|
|
||||||
47
.gitea/workflows/publish.yaml
Normal file
47
.gitea/workflows/publish.yaml
Normal 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 }}
|
||||||
28
.gitea/workflows/test.yaml
Normal file
28
.gitea/workflows/test.yaml
Normal 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
|
||||||
21
README.md
21
README.md
@@ -7,17 +7,10 @@ Supported encodings:
|
|||||||
- Base8 (octal)
|
- Base8 (octal)
|
||||||
- Base16 (hexadecimal)
|
- Base16 (hexadecimal)
|
||||||
- Base32
|
- Base32
|
||||||
|
- Base36
|
||||||
|
- Base62
|
||||||
- Base64
|
- Base64
|
||||||
|
|
||||||
## Targets
|
|
||||||
|
|
||||||
| Target | Status |
|
|
||||||
|------------------|---------------|
|
|
||||||
| JVM | Supported |
|
|
||||||
| JavaScript | Supported |
|
|
||||||
| Native (Linux) | Supported |
|
|
||||||
| Native (Windows) | Not Supported |
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Add the following to your `build.gradle.kts`.
|
Add the following to your `build.gradle.kts`.
|
||||||
@@ -28,23 +21,19 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.infendro:encoding:1.2.0")
|
implementation("com.infendro:encoding:1.3.0")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
import com.infendro.encoding.Base16
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
// the string to encode
|
// the string to encode
|
||||||
val test = "Hello World!"
|
val test = "Hello World!".encodeToByteArray()
|
||||||
.encodeToByteArray().asUByteArray()
|
|
||||||
|
|
||||||
// encode the string with the desired encoding
|
// encode the string with the desired encoding
|
||||||
val encoded = Base16.encode(test)
|
val encoded = Base16.encode(test).decodeToString()
|
||||||
.asByteArray().decodeToString()
|
|
||||||
|
|
||||||
println(encoded) // 48656c6c6f20576f726c6421
|
println(encoded) // 48656c6c6f20576f726c6421
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
@file:OptIn(ExperimentalWasmDsl::class)
|
||||||
|
|
||||||
import com.infendro.plugin.infendro
|
import com.infendro.plugin.infendro
|
||||||
import com.infendro.plugin.token
|
import com.infendro.plugin.token
|
||||||
|
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||||
|
|
||||||
group = "com.infendro"
|
group = "com.infendro"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.infendro)
|
alias(libs.plugins.infendro)
|
||||||
@@ -13,9 +16,13 @@ plugins {
|
|||||||
kotlin {
|
kotlin {
|
||||||
jvm()
|
jvm()
|
||||||
linuxX64()
|
linuxX64()
|
||||||
js {
|
linuxArm64()
|
||||||
nodejs()
|
mingwX64()
|
||||||
}
|
macosX64()
|
||||||
|
macosArm64()
|
||||||
|
js { nodejs() }
|
||||||
|
wasmJs { nodejs() }
|
||||||
|
wasmWasi { nodejs() }
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -26,10 +33,6 @@ kotlin {
|
|||||||
implementation(libs.test)
|
implementation(libs.test)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compilerOptions {
|
|
||||||
freeCompilerArgs.add("-opt-in=kotlin.ExperimentalUnsignedTypes")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing.repositories {
|
publishing.repositories {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[versions]
|
[versions]
|
||||||
infendro = "1.0.0"
|
infendro = "1.0.0"
|
||||||
kotlin = "2.2.21"
|
kotlin = "2.3.0"
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
infendro = { id = "com.infendro.plugin", version.ref = "infendro" }
|
infendro = { id = "com.infendro.plugin", version.ref = "infendro" }
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -1,92 +1,15 @@
|
|||||||
package com.infendro.encoding
|
package com.infendro.encoding
|
||||||
|
|
||||||
import com.infendro.encoding.util.lcm
|
abstract class Encoding(
|
||||||
import com.infendro.encoding.util.log2
|
val alphabet: ByteArray,
|
||||||
import kotlin.math.pow
|
) {
|
||||||
|
init {
|
||||||
sealed class Encoding {
|
require(alphabet.isNotEmpty())
|
||||||
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])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (padding != null) {
|
val base: Int
|
||||||
val block = lcm(length, 8) / length
|
get() = alphabet.size
|
||||||
while (encoded.size % block != 0) {
|
|
||||||
encoded.add(padding)
|
abstract fun encode(bytes: ByteArray): ByteArray
|
||||||
}
|
abstract fun decode(bytes: ByteArray): ByteArray
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.infendro.encoding.numeric
|
||||||
|
|
||||||
|
private val alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".encodeToByteArray()
|
||||||
|
|
||||||
|
object Base36 : NumericEncoding(alphabet)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.infendro.encoding.numeric
|
||||||
|
|
||||||
|
private val alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".encodeToByteArray()
|
||||||
|
|
||||||
|
object Base62 : NumericEncoding(alphabet)
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.infendro.encoding.stream
|
||||||
|
|
||||||
|
private val alphabet = "0123456789ABCDEF".encodeToByteArray()
|
||||||
|
|
||||||
|
object Base16 : StreamEncoding(alphabet)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.infendro.encoding.stream
|
||||||
|
|
||||||
|
private val alphabet = "01".encodeToByteArray()
|
||||||
|
|
||||||
|
object Base2 : StreamEncoding(alphabet)
|
||||||
@@ -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)
|
||||||
@@ -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)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.infendro.encoding.stream
|
||||||
|
|
||||||
|
private val alphabet = "01234567".encodeToByteArray()
|
||||||
|
|
||||||
|
object Base8 : StreamEncoding(alphabet)
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
89
src/commonMain/kotlin/com/infendro/encoding/util/BigInt.kt
Normal file
89
src/commonMain/kotlin/com/infendro/encoding/util/BigInt.kt
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,14 +2,16 @@ package com.infendro.encoding.util
|
|||||||
|
|
||||||
import kotlin.math.log2
|
import kotlin.math.log2
|
||||||
|
|
||||||
internal fun log2(
|
internal fun log2(value: Int): Double =
|
||||||
value: Int,
|
log2(value.toDouble())
|
||||||
) = log2(value.toDouble())
|
|
||||||
|
|
||||||
internal fun gcd(
|
internal fun Int.divCeil(n: Int): Int =
|
||||||
a: Int,
|
(this + n - 1) / n
|
||||||
b: Int,
|
|
||||||
): Int {
|
internal fun Int.align(n: Int): Int =
|
||||||
|
divCeil(n) * n
|
||||||
|
|
||||||
|
internal fun gcd(a: Int, b: Int): Int {
|
||||||
var x = a
|
var x = a
|
||||||
var y = b
|
var y = b
|
||||||
while (y != 0) {
|
while (y != 0) {
|
||||||
@@ -20,9 +22,6 @@ internal fun gcd(
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun lcm(
|
internal fun lcm(a: Int, b: Int): Int {
|
||||||
a: Int,
|
|
||||||
b: Int,
|
|
||||||
): Int {
|
|
||||||
return (a * b) / gcd(a, b)
|
return (a * b) / gcd(a, b)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,33 @@
|
|||||||
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: Encoding
|
val encoding: StreamEncoding
|
||||||
get() = Base16
|
get() = Base16
|
||||||
|
|
||||||
val `Hello World!` = ubyteArrayOf(
|
val `Hello World!` = byteArrayOf(
|
||||||
0x48U, 0x65U, 0x6cU, 0x6cU,
|
0x48, 0x65, 0x6c, 0x6c,
|
||||||
0x6fU, 0x20U, 0x57U, 0x6fU,
|
0x6f, 0x20, 0x57, 0x6f,
|
||||||
0x72U, 0x6cU, 0x64U, 0x21U,
|
0x72, 0x6c, 0x64, 0x21,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `encode empty ByteArray`() {
|
fun `encode empty ByteArray`() {
|
||||||
val expected = ubyteArrayOf()
|
val expected = byteArrayOf()
|
||||||
val actual = encoding.encode(ubyteArrayOf())
|
val actual = encoding.encode(byteArrayOf())
|
||||||
assertContentEquals(expected, actual)
|
assertContentEquals(expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `encode "Hello World!"`() {
|
fun `encode "Hello World!"`() {
|
||||||
val expected = ubyteArrayOf(
|
val expected = byteArrayOf(
|
||||||
0x34U, 0x38U, 0x36U, 0x35U, 0x36U, 0x63U, 0x36U, 0x63U,
|
0x34, 0x38, 0x36, 0x35, 0x36, 0x63, 0x36, 0x63,
|
||||||
0x36U, 0x66U, 0x32U, 0x30U, 0x35U, 0x37U, 0x36U, 0x66U,
|
0x36, 0x66, 0x32, 0x30, 0x35, 0x37, 0x36, 0x66,
|
||||||
0x37U, 0x32U, 0x36U, 0x63U, 0x36U, 0x34U, 0x32U, 0x31U,
|
0x37, 0x32, 0x36, 0x63, 0x36, 0x34, 0x32, 0x31,
|
||||||
)
|
)
|
||||||
val actual = encoding.encode(`Hello World!`)
|
val actual = encoding.encode(`Hello World!`)
|
||||||
assertContentEquals(expected, actual)
|
assertContentEquals(expected, actual)
|
||||||
|
|||||||
@@ -1,40 +1,42 @@
|
|||||||
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: Encoding
|
val encoding: StreamEncoding
|
||||||
get() = Base2
|
get() = Base2
|
||||||
|
|
||||||
val `Hello World!` = ubyteArrayOf(
|
val `Hello World!` = byteArrayOf(
|
||||||
0x48U, 0x65U, 0x6cU, 0x6cU,
|
0x48, 0x65, 0x6c, 0x6c,
|
||||||
0x6fU, 0x20U, 0x57U, 0x6fU,
|
0x6f, 0x20, 0x57, 0x6f,
|
||||||
0x72U, 0x6cU, 0x64U, 0x21U,
|
0x72, 0x6c, 0x64, 0x21,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `encode empty ByteArray`() {
|
fun `encode empty ByteArray`() {
|
||||||
val expected = ubyteArrayOf()
|
val expected = byteArrayOf()
|
||||||
val actual = encoding.encode(ubyteArrayOf())
|
val actual = encoding.encode(byteArrayOf())
|
||||||
assertContentEquals(expected, actual)
|
assertContentEquals(expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `encode "Hello World!"`() {
|
fun `encode "Hello World!"`() {
|
||||||
val expected = ubyteArrayOf(
|
val expected = byteArrayOf(
|
||||||
0x30U, 0x31U, 0x30U, 0x30U, 0x31U, 0x30U, 0x30U, 0x30U,
|
0x30, 0x31, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30,
|
||||||
0x30U, 0x31U, 0x31U, 0x30U, 0x30U, 0x31U, 0x30U, 0x31U,
|
0x30, 0x31, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31,
|
||||||
0x30U, 0x31U, 0x31U, 0x30U, 0x31U, 0x31U, 0x30U, 0x30U,
|
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30,
|
||||||
0x30U, 0x31U, 0x31U, 0x30U, 0x31U, 0x31U, 0x30U, 0x30U,
|
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30,
|
||||||
0x30U, 0x31U, 0x31U, 0x30U, 0x31U, 0x31U, 0x31U, 0x31U,
|
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x31, 0x31,
|
||||||
0x30U, 0x30U, 0x31U, 0x30U, 0x30U, 0x30U, 0x30U, 0x30U,
|
0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||||
0x30U, 0x31U, 0x30U, 0x31U, 0x30U, 0x31U, 0x31U, 0x31U,
|
0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x31,
|
||||||
0x30U, 0x31U, 0x31U, 0x30U, 0x31U, 0x31U, 0x31U, 0x31U,
|
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x31, 0x31,
|
||||||
0x30U, 0x31U, 0x31U, 0x31U, 0x30U, 0x30U, 0x31U, 0x30U,
|
0x30, 0x31, 0x31, 0x31, 0x30, 0x30, 0x31, 0x30,
|
||||||
0x30U, 0x31U, 0x31U, 0x30U, 0x31U, 0x31U, 0x30U, 0x30U,
|
0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30,
|
||||||
0x30U, 0x31U, 0x31U, 0x30U, 0x30U, 0x31U, 0x30U, 0x30U,
|
0x30, 0x31, 0x31, 0x30, 0x30, 0x31, 0x30, 0x30,
|
||||||
0x30U, 0x30U, 0x31U, 0x30U, 0x30U, 0x30U, 0x30U, 0x31U,
|
0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x31,
|
||||||
)
|
)
|
||||||
val actual = encoding.encode(`Hello World!`)
|
val actual = encoding.encode(`Hello World!`)
|
||||||
assertContentEquals(expected, actual)
|
assertContentEquals(expected, actual)
|
||||||
|
|||||||
@@ -1,31 +1,33 @@
|
|||||||
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: Encoding
|
val encoding: StreamEncoding
|
||||||
get() = Base32
|
get() = Base32
|
||||||
|
|
||||||
val `Hello World!` = ubyteArrayOf(
|
val `Hello World!` = byteArrayOf(
|
||||||
0x48U, 0x65U, 0x6cU, 0x6cU,
|
0x48, 0x65, 0x6c, 0x6c,
|
||||||
0x6fU, 0x20U, 0x57U, 0x6fU,
|
0x6f, 0x20, 0x57, 0x6f,
|
||||||
0x72U, 0x6cU, 0x64U, 0x21U,
|
0x72, 0x6c, 0x64, 0x21,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `encode empty ByteArray`() {
|
fun `encode empty ByteArray`() {
|
||||||
val expected = ubyteArrayOf()
|
val expected = byteArrayOf()
|
||||||
val actual = encoding.encode(ubyteArrayOf())
|
val actual = encoding.encode(byteArrayOf())
|
||||||
assertContentEquals(expected, actual)
|
assertContentEquals(expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `encode "Hello World!"`() {
|
fun `encode "Hello World!"`() {
|
||||||
val expected = ubyteArrayOf(
|
val expected = byteArrayOf(
|
||||||
0x4aU, 0x42U, 0x53U, 0x57U, 0x59U, 0x33U, 0x44U, 0x50U,
|
0x4a, 0x42, 0x53, 0x57, 0x59, 0x33, 0x44, 0x50,
|
||||||
0x45U, 0x42U, 0x4cU, 0x57U, 0x36U, 0x34U, 0x54U, 0x4dU,
|
0x45, 0x42, 0x4c, 0x57, 0x36, 0x34, 0x54, 0x4d,
|
||||||
0x4dU, 0x51U, 0x51U, 0x51U, 0x3dU, 0x3dU, 0x3dU, 0x3dU,
|
0x4d, 0x51, 0x51, 0x51, 0x3d, 0x3d, 0x3d, 0x3d,
|
||||||
)
|
)
|
||||||
val actual = encoding.encode(`Hello World!`)
|
val actual = encoding.encode(`Hello World!`)
|
||||||
assertContentEquals(expected, actual)
|
assertContentEquals(expected, actual)
|
||||||
|
|||||||
@@ -1,30 +1,32 @@
|
|||||||
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: Encoding
|
val encoding: StreamEncoding
|
||||||
get() = Base64
|
get() = Base64
|
||||||
|
|
||||||
val `Hello World!` = ubyteArrayOf(
|
val `Hello World!` = byteArrayOf(
|
||||||
0x48U, 0x65U, 0x6cU, 0x6cU,
|
0x48, 0x65, 0x6c, 0x6c,
|
||||||
0x6fU, 0x20U, 0x57U, 0x6fU,
|
0x6f, 0x20, 0x57, 0x6f,
|
||||||
0x72U, 0x6cU, 0x64U, 0x21U,
|
0x72, 0x6c, 0x64, 0x21,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `encode empty ByteArray`() {
|
fun `encode empty ByteArray`() {
|
||||||
val expected = ubyteArrayOf()
|
val expected = byteArrayOf()
|
||||||
val actual = encoding.encode(ubyteArrayOf())
|
val actual = encoding.encode(byteArrayOf())
|
||||||
assertContentEquals(expected, actual)
|
assertContentEquals(expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `encode "Hello World!"`() {
|
fun `encode "Hello World!"`() {
|
||||||
val expected = ubyteArrayOf(
|
val expected = byteArrayOf(
|
||||||
0x53U, 0x47U, 0x56U, 0x73U, 0x62U, 0x47U, 0x38U, 0x67U,
|
0x53, 0x47, 0x56, 0x73, 0x62, 0x47, 0x38, 0x67,
|
||||||
0x56U, 0x32U, 0x39U, 0x79U, 0x62U, 0x47U, 0x51U, 0x68U,
|
0x56, 0x32, 0x39, 0x79, 0x62, 0x47, 0x51, 0x68,
|
||||||
)
|
)
|
||||||
val actual = encoding.encode(`Hello World!`)
|
val actual = encoding.encode(`Hello World!`)
|
||||||
assertContentEquals(expected, actual)
|
assertContentEquals(expected, actual)
|
||||||
|
|||||||
@@ -1,32 +1,34 @@
|
|||||||
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: Encoding
|
val encoding: StreamEncoding
|
||||||
get() = Base8
|
get() = Base8
|
||||||
|
|
||||||
val `Hello World!` = ubyteArrayOf(
|
val `Hello World!` = byteArrayOf(
|
||||||
0x48U, 0x65U, 0x6cU, 0x6cU,
|
0x48, 0x65, 0x6c, 0x6c,
|
||||||
0x6fU, 0x20U, 0x57U, 0x6fU,
|
0x6f, 0x20, 0x57, 0x6f,
|
||||||
0x72U, 0x6cU, 0x64U, 0x21U,
|
0x72, 0x6c, 0x64, 0x21,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `encode empty ByteArray`() {
|
fun `encode empty ByteArray`() {
|
||||||
val expected = ubyteArrayOf()
|
val expected = byteArrayOf()
|
||||||
val actual = encoding.encode(ubyteArrayOf())
|
val actual = encoding.encode(byteArrayOf())
|
||||||
assertContentEquals(expected, actual)
|
assertContentEquals(expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `encode "Hello World!"`() {
|
fun `encode "Hello World!"`() {
|
||||||
val expected = ubyteArrayOf(
|
val expected = byteArrayOf(
|
||||||
0x32U, 0x32U, 0x30U, 0x36U, 0x32U, 0x35U, 0x35U, 0x34U,
|
0x32, 0x32, 0x30, 0x36, 0x32, 0x35, 0x35, 0x34,
|
||||||
0x33U, 0x33U, 0x30U, 0x36U, 0x37U, 0x34U, 0x34U, 0x30U,
|
0x33, 0x33, 0x30, 0x36, 0x37, 0x34, 0x34, 0x30,
|
||||||
0x32U, 0x35U, 0x36U, 0x36U, 0x37U, 0x35U, 0x36U, 0x32U,
|
0x32, 0x35, 0x36, 0x36, 0x37, 0x35, 0x36, 0x32,
|
||||||
0x33U, 0x33U, 0x30U, 0x36U, 0x32U, 0x30U, 0x34U, 0x31U,
|
0x33, 0x33, 0x30, 0x36, 0x32, 0x30, 0x34, 0x31,
|
||||||
)
|
)
|
||||||
val actual = encoding.encode(`Hello World!`)
|
val actual = encoding.encode(`Hello World!`)
|
||||||
assertContentEquals(expected, actual)
|
assertContentEquals(expected, actual)
|
||||||
|
|||||||
Reference in New Issue
Block a user