diff --git a/bytestring/api/kotlinx-io-bytestring.klib.api b/bytestring/api/kotlinx-io-bytestring.klib.api index 7dd54088..47fe266b 100644 --- a/bytestring/api/kotlinx-io-bytestring.klib.api +++ b/bytestring/api/kotlinx-io-bytestring.klib.api @@ -82,3 +82,15 @@ final fun (kotlinx.io.bytestring/ByteStringBuilder).kotlinx.io.bytestring/append final fun <#A: kotlin.text/Appendable> (kotlin.io.encoding/Base64).kotlinx.io.bytestring/encodeToAppendable(kotlinx.io.bytestring/ByteString, #A, kotlin/Int = ..., kotlin/Int = ...): #A // kotlinx.io.bytestring/encodeToAppendable|encodeToAppendable@kotlin.io.encoding.Base64(kotlinx.io.bytestring.ByteString;0:0;kotlin.Int;kotlin.Int){0ยง}[0] final fun kotlinx.io.bytestring/ByteString(kotlin/ByteArray...): kotlinx.io.bytestring/ByteString // kotlinx.io.bytestring/ByteString|ByteString(kotlin.ByteArray...){}[0] final inline fun kotlinx.io.bytestring/buildByteString(kotlin/Int = ..., kotlin/Function1): kotlinx.io.bytestring/ByteString // kotlinx.io.bytestring/buildByteString|buildByteString(kotlin.Int;kotlin.Function1){}[0] + +// Targets: [js, wasmJs] +final fun (kotlinx.io.bytestring/ByteString).kotlinx.io.bytestring/toArrayBuffer(): org.khronos.webgl/ArrayBuffer // kotlinx.io.bytestring/toArrayBuffer|toArrayBuffer@kotlinx.io.bytestring.ByteString(){}[0] + +// Targets: [js, wasmJs] +final fun (kotlinx.io.bytestring/ByteString).kotlinx.io.bytestring/toInt8Array(): org.khronos.webgl/Int8Array // kotlinx.io.bytestring/toInt8Array|toInt8Array@kotlinx.io.bytestring.ByteString(){}[0] + +// Targets: [js, wasmJs] +final fun (org.khronos.webgl/ArrayBuffer).kotlinx.io.bytestring/toByteString(): kotlinx.io.bytestring/ByteString // kotlinx.io.bytestring/toByteString|toByteString@org.khronos.webgl.ArrayBuffer(){}[0] + +// Targets: [js, wasmJs] +final fun (org.khronos.webgl/Int8Array).kotlinx.io.bytestring/toByteString(): kotlinx.io.bytestring/ByteString // kotlinx.io.bytestring/toByteString|toByteString@org.khronos.webgl.Int8Array(){}[0] diff --git a/bytestring/js/src/ByteStringsJs.kt b/bytestring/js/src/ByteStringsJs.kt new file mode 100644 index 00000000..7a0f3d30 --- /dev/null +++ b/bytestring/js/src/ByteStringsJs.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2017-2024 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file. + */ + +package kotlinx.io.bytestring + +import org.khronos.webgl.ArrayBuffer +import org.khronos.webgl.Int8Array + +/** + * Returns a new [Int8Array] instance initialized with bytes copied from [this] ByteString. + */ +public fun ByteString.toInt8Array(): Int8Array = toByteArray().unsafeCast() + +/** + * Returns a new [ArrayBuffer] instance initialized with bytes copied from [this] ByteString. + */ +public fun ByteString.toArrayBuffer(): ArrayBuffer = toInt8Array().buffer + +/** + * Return a new [ByteString] holding data copied from [this] Int8Array. + */ +public fun Int8Array.toByteString(): ByteString = ByteString(*unsafeCast()) + +/** + * Returns a new [ByteString] holding data copied from [this] ArrayBuffer + */ +public fun ArrayBuffer.toByteString(): ByteString = Int8Array(this).toByteString() \ No newline at end of file diff --git a/bytestring/js/test/ByteStringConversionsTest.kt b/bytestring/js/test/ByteStringConversionsTest.kt new file mode 100644 index 00000000..ccd82ea7 --- /dev/null +++ b/bytestring/js/test/ByteStringConversionsTest.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2017-2024 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file. + */ + +package kotlinx.io.bytestring + +import kotlinx.io.bytestring.unsafe.UnsafeByteStringApi +import kotlinx.io.bytestring.unsafe.UnsafeByteStringOperations +import org.khronos.webgl.ArrayBuffer +import org.khronos.webgl.Int8Array +import org.khronos.webgl.get +import org.khronos.webgl.set +import kotlin.test.Test +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class ByteStringConversionsTest { + @Test + fun int8ArrayToByteString() { + assertTrue(Int8Array(0).toByteString().isEmpty()) + + val str = Int8Array(byteArrayOf(1, 2, 3, 4).toTypedArray()).toByteString() + assertContentEquals(byteArrayOf(1, 2, 3, 4), str.toByteArray()) + } + + @Test + fun arrayBufferToByteString() { + assertTrue(ArrayBuffer(0).toByteString().isEmpty()) + + val str = Int8Array(byteArrayOf(1, 2, 3, 4).toTypedArray()).buffer.toByteString() + assertContentEquals(byteArrayOf(1, 2, 3, 4), str.toByteArray()) + } + + @Test + fun byteStringToInt8Array() { + assertEquals(0, ByteString().toInt8Array().length) + + val array = ByteString(1, 2, 3, 4).toInt8Array() + for (idx in 0..<3) { + assertEquals((idx + 1).toByte(), array[idx], "idx = $idx") + } + } + + @Test + fun byteStringToArrayBuffer() { + assertEquals(0, ByteString().toArrayBuffer().byteLength) + + val buffer = ByteString(1, 2, 3, 4).toArrayBuffer() + val array = Int8Array(buffer) + for (idx in 0..<3) { + assertEquals((idx + 1).toByte(), array[idx], "idx = $idx") + } + } + + @OptIn(UnsafeByteStringApi::class) + @Test + fun integrityCheck() { + val array = Int8Array(byteArrayOf(1, 2, 3, 4).toTypedArray()) + val str = array.toByteString() + + array[0] = 42 + assertContentEquals(byteArrayOf(1, 2, 3, 4), str.toByteArray()) + + val array2 = str.toInt8Array() + UnsafeByteStringOperations.withByteArrayUnsafe(str) { it[1] = 42 } + assertEquals(2, array2[1]) + } +} \ No newline at end of file diff --git a/bytestring/wasmJs/src/ByteStringsWasmJs.kt b/bytestring/wasmJs/src/ByteStringsWasmJs.kt new file mode 100644 index 00000000..bb9ad1c1 --- /dev/null +++ b/bytestring/wasmJs/src/ByteStringsWasmJs.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2017-2024 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file. + */ + +package kotlinx.io.bytestring + +import org.khronos.webgl.ArrayBuffer +import org.khronos.webgl.Int8Array +import org.khronos.webgl.get +import org.khronos.webgl.set + +/** + * Returns a new [Int8Array] instance initialized with bytes copied from [this] ByteString. + */ +public fun ByteString.toInt8Array(): Int8Array { + val res = Int8Array(size) + for (idx in this.indices) { + res[idx] = this[idx] + } + return res +} + +/** + * Returns a new [ArrayBuffer] instance initialized with bytes copied from [this] ByteString. + */ +public fun ByteString.toArrayBuffer(): ArrayBuffer = toInt8Array().buffer + +/** + * Return a new [ByteString] holding data copied from [this] Int8Array. + */ +public fun Int8Array.toByteString(): ByteString { + if (length == 0) { + return ByteString.EMPTY + } + val builder = ByteStringBuilder(length) + for (idx in 0..