Skip to content

Commit a0cfb21

Browse files
committed
Migrate random module to use shared web declarations
1 parent a46ea44 commit a0cfb21

File tree

5 files changed

+59
-76
lines changed

5 files changed

+59
-76
lines changed

cryptography-random/build.gradle.kts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023-2024 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license.
2+
* Copyright (c) 2023-2025 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

55
import ckbuild.*
@@ -15,6 +15,10 @@ description = "cryptography-kotlin random API"
1515
kotlin {
1616
allTargets()
1717

18+
compilerOptions {
19+
freeCompilerArgs.add("-Xexpect-actual-classes")
20+
}
21+
1822
applyDefaultHierarchyTemplate {
1923
common {
2024
group("linuxAndAndroidNative") {

cryptography-random/src/jsMain/kotlin/CryptographyRandom.js.kt

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,6 @@
44

55
package dev.whyoleg.cryptography.random
66

7-
import org.khronos.webgl.*
8-
9-
internal actual fun defaultCryptographyRandom(): CryptographyRandom = WebCryptoCryptographyRandom
10-
11-
private object WebCryptoCryptographyRandom : AbstractRandom() {
12-
private const val MAX_ARRAY_SIZE = 65536
13-
private val crypto: Crypto = getCrypto()
14-
override fun fillBytes(array: ByteArray) {
15-
fillBytes(array.unsafeCast<Int8Array>())
16-
}
17-
18-
private fun fillBytes(jsArray: Int8Array) {
19-
val size = jsArray.length
20-
if (size <= MAX_ARRAY_SIZE) {
21-
crypto.getRandomValues(jsArray)
22-
} else {
23-
var filled = 0
24-
do {
25-
val chunkSize = minOf(MAX_ARRAY_SIZE, size - filled)
26-
crypto.getRandomValues(jsArray.subarray(filled, filled + chunkSize))
27-
filled += chunkSize
28-
} while (filled < size)
29-
}
30-
}
7+
internal actual inline fun ByteArray.useAsInt8Array(block: (array: Int8Array) -> Unit) {
8+
block(this.unsafeCast<Int8Array>())
319
}
32-
33-
private external interface Crypto {
34-
fun getRandomValues(array: Int8Array)
35-
}
36-
37-
//language=JavaScript
38-
private fun getCrypto(): Crypto = js("(globalThis ? globalThis.crypto : (window.crypto || window.msCrypto))")

cryptography-random/src/wasmJsMain/kotlin/CryptographyRandom.wasmJs.kt

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,10 @@
44

55
package dev.whyoleg.cryptography.random
66

7-
internal actual fun defaultCryptographyRandom(): CryptographyRandom = WebCryptoCryptographyRandom
8-
9-
private object WebCryptoCryptographyRandom : AbstractRandom() {
10-
private const val MAX_ARRAY_SIZE = 65536
11-
private val crypto: Crypto = getCrypto()
12-
override fun fillBytes(array: ByteArray) {
13-
val size = array.size
14-
val jsArray = Int8Array(size)
15-
fillBytes(jsArray)
16-
repeat(size) { array[it] = jsArray[it] }
17-
}
18-
19-
private fun fillBytes(jsArray: Int8Array) {
20-
val size = jsArray.length
21-
if (size <= MAX_ARRAY_SIZE) {
22-
crypto.getRandomValues(jsArray)
23-
} else {
24-
var filled = 0
25-
do {
26-
val chunkSize = minOf(MAX_ARRAY_SIZE, size - filled)
27-
crypto.getRandomValues(jsArray.subarray(filled, filled + chunkSize))
28-
filled += chunkSize
29-
} while (filled < size)
30-
}
31-
}
7+
internal actual inline fun ByteArray.useAsInt8Array(block: (array: Int8Array) -> Unit) {
8+
val jsArray = Int8Array(size).apply(block)
9+
repeat(size) { this[it] = getByte(jsArray, it) }
3210
}
3311

34-
private external interface Crypto {
35-
fun getRandomValues(array: Int8Array)
36-
}
37-
38-
//language=JavaScript
39-
private fun getCrypto(): Crypto = js("(globalThis ? globalThis.crypto : (window.crypto || window.msCrypto))")
40-
41-
private external class Int8Array {
42-
constructor(length: Int)
43-
44-
val length: Int
45-
fun subarray(start: Int, end: Int): Int8Array
46-
}
47-
48-
private fun getImpl(obj: Int8Array, index: Int): Byte = js("obj[index]")
49-
50-
private operator fun Int8Array.get(index: Int): Byte = getImpl(this, index)
12+
@OptIn(ExperimentalWasmJsInterop::class)
13+
private fun getByte(obj: Int8Array, index: Int): Byte = js("obj[index]")

cryptography-random/src/wasmWasiMain/kotlin/CryptographyRandom.wasmWasi.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
/*
2-
* Copyright (c) 2023-2024 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license.
2+
* Copyright (c) 2023-2025 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

55
package dev.whyoleg.cryptography.random
66

7-
import kotlin.wasm.*
87
import kotlin.wasm.unsafe.*
98

109
internal actual fun defaultCryptographyRandom(): CryptographyRandom = WasiPreview1CryptographyRandom
@@ -25,5 +24,6 @@ private object WasiPreview1CryptographyRandom : AbstractRandom() {
2524
}
2625
}
2726

27+
@OptIn(kotlin.wasm.ExperimentalWasmInterop::class)
2828
@WasmImport("wasi_snapshot_preview1", "random_get")
2929
private external fun wasiRandomGet(address: Int, size: Int): Int
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2023-2025 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
@file:OptIn(ExperimentalWasmJsInterop::class)
6+
7+
package dev.whyoleg.cryptography.random
8+
9+
import kotlin.js.*
10+
11+
internal actual fun defaultCryptographyRandom(): CryptographyRandom = WebCryptoCryptographyRandom
12+
13+
private object WebCryptoCryptographyRandom : AbstractRandom() {
14+
private const val MAX_ARRAY_SIZE = 65536
15+
private val crypto: Crypto = getCrypto()
16+
override fun fillBytes(array: ByteArray): Unit = array.useAsInt8Array(::fillBytes)
17+
18+
private fun fillBytes(jsArray: Int8Array) {
19+
val size = jsArray.length
20+
if (size <= MAX_ARRAY_SIZE) {
21+
crypto.getRandomValues(jsArray)
22+
} else {
23+
var filled = 0
24+
do {
25+
val chunkSize = minOf(MAX_ARRAY_SIZE, size - filled)
26+
crypto.getRandomValues(jsArray.subarray(filled, filled + chunkSize))
27+
filled += chunkSize
28+
} while (filled < size)
29+
}
30+
}
31+
}
32+
33+
private external interface Crypto {
34+
fun getRandomValues(array: Int8Array)
35+
}
36+
37+
//language=JavaScript
38+
private fun getCrypto(): Crypto = js("(globalThis ? globalThis.crypto : (window.crypto || window.msCrypto))")
39+
40+
internal expect inline fun ByteArray.useAsInt8Array(block: (array: Int8Array) -> Unit)
41+
42+
internal external class Int8Array(length: Int) {
43+
val length: Int
44+
fun subarray(start: Int, end: Int): Int8Array
45+
}

0 commit comments

Comments
 (0)