Skip to content

Commit cb2ab76

Browse files
committed
chore: wasmjs ArrayBuffer functions
1 parent cf4e828 commit cb2ab76

File tree

6 files changed

+88
-12
lines changed

6 files changed

+88
-12
lines changed

gradle/build-logic/src/main/kotlin/common/CommonExtns.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import java.nio.file.Files
77
import java.nio.file.Path
88
import java.text.DecimalFormat
99
import java.text.NumberFormat
10-
import kotlin.jvm.optionals.getOrNull
1110
import kotlin.math.ln
1211
import kotlin.math.pow
1312
import kotlin.properties.ReadOnlyProperty
@@ -21,10 +20,6 @@ internal val DEC_FORMAT = DecimalFormat("#.##")
2120
/** OS temp location */
2221
val tmp: String = "${System.getProperty("java.io.tmpdir")}${File.separator}"
2322

24-
/** Returns the method name contains this call-site */
25-
inline val methodName
26-
get() = StackWalker.getInstance().walk { it.findFirst().getOrNull()?.methodName }
27-
2823
/** Read the [Class] as [ByteArray] */
2924
fun <T : Class<*>> T.toBytes() =
3025
classLoader.getResourceAsStream("${name.replace('.', '/')}.class")?.readBytes()

shared/src/jsMain/kotlin/dev/suresh/Platform.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package dev.suresh
22

33
import kotlinx.browser.window
4+
import org.khronos.webgl.ArrayBuffer
5+
import org.khronos.webgl.Int8Array
46

57
actual val platform: Platform = JsPlatform
68

@@ -16,3 +18,10 @@ object JsPlatform : Platform {
1618
"vendor" to window.navigator.vendor,
1719
)
1820
}
21+
22+
/**
23+
* Convert JS [ArrayBuffer] to Kotlin [ByteArray]
24+
*
25+
* [Kotlin-JS-Types](https://kotlinlang.org/docs/js-to-kotlin-interop.html#kotlin-types-in-javascript)
26+
*/
27+
fun ArrayBuffer?.asByteArray() = this?.run { Int8Array(this).unsafeCast<ByteArray>() }

shared/src/jvmMain/kotlin/dev/suresh/Extns.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dev.suresh
22

33
import java.io.File
4+
import java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE
45
import java.text.DecimalFormat
56
import java.text.NumberFormat
67
import java.util.concurrent.Semaphore
@@ -16,7 +17,10 @@ val DEC_FORMAT = DecimalFormat("#.##")
1617

1718
/** Returns the method name contains this call-site */
1819
inline val methodName
19-
get() = StackWalker.getInstance().walk { it.findFirst().getOrNull()?.methodName }
20+
get() =
21+
StackWalker.getInstance(RETAIN_CLASS_REFERENCE).walk {
22+
it.findFirst().getOrNull()?.methodName
23+
}
2024

2125
/** Read the [Class] as [ByteArray] */
2226
fun <T : Class<*>> T.toBytes() =

web/wasm/src/wasmJsMain/kotlin/App.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ suspend fun main() {
6161
info?.appendText("Selected files: $files")
6262
files.forEach { file ->
6363
val text = file.readAsText()
64-
info?.appendText("File content: $text")
64+
val buf = file.readAsByteArray()
65+
info?.appendText("Text File content: $text")
66+
info?.appendText("Binary File content: ${buf?.decodeToString()}")
6567
}
6668
}
6769
}

web/wasm/src/wasmJsMain/kotlin/FilePicker.kt

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ suspend fun Document.selectFileFromDisk(accept: String? = null, multiple: Boolea
2323
this.multiple = multiple
2424
accept?.let { this.accept = it }
2525
onchange = {
26-
val files = input.files?.asList().orEmpty()
27-
cont.resume(files)
26+
try {
27+
val files = input.files?.asList().orEmpty()
28+
cont.resume(files)
29+
} catch (e: Exception) {
30+
cont.resumeWithException(e)
31+
}
2832
}
2933
}
3034
body?.appendChild(input)
@@ -35,9 +39,13 @@ suspend fun Document.selectFileFromDisk(accept: String? = null, multiple: Boolea
3539
suspend fun File.readAsText() = suspendCoroutine { cont ->
3640
val reader = FileReader()
3741
reader.onload = {
38-
val target = it.target as? FileReader
39-
val result = target?.result as? ArrayBuffer
40-
cont.resume(result)
42+
try {
43+
val target = it.target as? FileReader
44+
val result = target?.result?.unsafeCast<JsString>()
45+
cont.resume(result?.toString())
46+
} catch (e: Exception) {
47+
cont.resumeWithException(e)
48+
}
4149
}
4250

4351
reader.onerror = {
@@ -50,3 +58,26 @@ suspend fun File.readAsText() = suspendCoroutine { cont ->
5058
}
5159
reader.readAsText(this, "UTF-8")
5260
}
61+
62+
suspend fun File.readAsByteArray() = suspendCoroutine { cont ->
63+
val reader = FileReader()
64+
reader.onload = {
65+
try {
66+
val target = it.target as? FileReader
67+
val result = target?.result?.unsafeCast<ArrayBuffer>()
68+
cont.resume(result.toByteArray())
69+
} catch (e: Exception) {
70+
cont.resumeWithException(e)
71+
}
72+
}
73+
74+
reader.onerror = {
75+
cont.resumeWithException(IllegalStateException("Error reading the file $name"))
76+
}
77+
78+
reader.onprogress = {
79+
val percentage = (it.loaded.toDouble() / it.total.toDouble()) * 100
80+
log.info { "File loading Progress: $percentage%" }
81+
}
82+
reader.readAsArrayBuffer(this)
83+
}

web/wasm/src/wasmJsMain/kotlin/Interop.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import org.khronos.webgl.ArrayBuffer
2+
import org.khronos.webgl.Int8Array
3+
import org.khronos.webgl.get
4+
import org.khronos.webgl.set
5+
16
/** JavaScript console class */
27
external class Console : JsAny {
38
fun log(message: String?)
@@ -11,3 +16,33 @@ external val console: Console
1116
fun currentTimeMillis(): Long = currentTimeMillisJs().toLong()
1217

1318
private fun currentTimeMillisJs(): Double = js("new Date().getTime()")
19+
20+
fun Int8Array.copyInto(
21+
output: ByteArray,
22+
inputOffset: Int = 0,
23+
outputOffset: Int = 0,
24+
length: Int = this.length
25+
) = repeat(length) { output[outputOffset + it] = this[inputOffset + it] }
26+
27+
fun Int8Array.toByteArray(): ByteArray {
28+
val buf = ByteArray(length)
29+
copyInto(buf)
30+
return buf
31+
}
32+
33+
fun ByteArray.copyInto(
34+
output: Int8Array,
35+
inputOffset: Int = 0,
36+
outputOffset: Int = 0,
37+
length: Int = this.size
38+
) = repeat(length) { output[outputOffset + it] = this[inputOffset + it] }
39+
40+
fun ByteArray.toInt8Array(): Int8Array {
41+
val arr = Int8Array(size)
42+
copyInto(arr)
43+
return arr
44+
}
45+
46+
fun ArrayBuffer?.toByteArray() = this?.run { Int8Array(this).toByteArray() }
47+
48+
fun ByteArray.toArrayBuffer() = toInt8Array().buffer

0 commit comments

Comments
 (0)