From fc85781bfc52df5e01b1c7f08043bc255be51e92 Mon Sep 17 00:00:00 2001 From: Abduqodiri Qurbonzoda Date: Thu, 24 Jan 2019 16:55:57 +0300 Subject: [PATCH] Implement asList, slice & sliceArray extension functions for UArrays --- generators/builtins/unsignedTypes.kt | 3 +- .../stdlib/common/src/generated/_Arrays.kt | 18 +- .../stdlib/common/src/generated/_UArrays.kt | 200 ++++++++++++++++++ .../js/irRuntime/generated/_ArraysJs.kt | 15 +- .../js/irRuntime/generated/_UArraysJs.kt | 114 ++++++++++ .../stdlib/js/src/generated/_ArraysJs.kt | 15 +- .../stdlib/js/src/generated/_UArraysJs.kt | 114 ++++++++++ .../stdlib/jvm/src/generated/_UArraysJvm.kt | 64 ++++++ .../test/collections/UnsignedArraysTest.kt | 55 ++++- .../stdlib/unsigned/src/kotlin/UByteArray.kt | 3 +- .../stdlib/unsigned/src/kotlin/UIntArray.kt | 3 +- .../stdlib/unsigned/src/kotlin/ULongArray.kt | 3 +- .../stdlib/unsigned/src/kotlin/UShortArray.kt | 3 +- .../kotlin-stdlib-runtime-merged.txt | 20 ++ .../kotlin-stdlib-gen/src/templates/Arrays.kt | 28 ++- .../src/templates/Filtering.kt | 27 ++- 16 files changed, 646 insertions(+), 39 deletions(-) create mode 100644 libraries/stdlib/js/irRuntime/generated/_UArraysJs.kt create mode 100644 libraries/stdlib/js/src/generated/_UArraysJs.kt diff --git a/generators/builtins/unsignedTypes.kt b/generators/builtins/unsignedTypes.kt index 9db3b685927..44de31ca317 100644 --- a/generators/builtins/unsignedTypes.kt +++ b/generators/builtins/unsignedTypes.kt @@ -454,8 +454,7 @@ class UnsignedArrayGenerator(val type: UnsignedType, out: PrintWriter) : BuiltIn } override fun containsAll(elements: Collection<$elementType>): Boolean { - if ((elements as Collection).any { it as? $elementType == null }) return false - return elements.all { storage.contains(it.to$storageElementType()) } + return (elements as Collection<*>).all { it is $elementType && storage.contains(it.to$storageElementType()) } } override fun isEmpty(): Boolean = this.storage.size == 0""" diff --git a/libraries/stdlib/common/src/generated/_Arrays.kt b/libraries/stdlib/common/src/generated/_Arrays.kt index e27e576445d..dfdb51caeb5 100644 --- a/libraries/stdlib/common/src/generated/_Arrays.kt +++ b/libraries/stdlib/common/src/generated/_Arrays.kt @@ -4040,7 +4040,7 @@ public fun CharArray.sliceArray(indices: Collection): CharArray { } /** - * Returns a list containing elements at indices in the specified [indices] range. + * Returns an array containing elements at indices in the specified [indices] range. */ public fun Array.sliceArray(indices: IntRange): Array { if (indices.isEmpty()) return copyOfRange(0, 0) @@ -4048,7 +4048,7 @@ public fun Array.sliceArray(indices: IntRange): Array { } /** - * Returns a list containing elements at indices in the specified [indices] range. + * Returns an array containing elements at indices in the specified [indices] range. */ public fun ByteArray.sliceArray(indices: IntRange): ByteArray { if (indices.isEmpty()) return ByteArray(0) @@ -4056,7 +4056,7 @@ public fun ByteArray.sliceArray(indices: IntRange): ByteArray { } /** - * Returns a list containing elements at indices in the specified [indices] range. + * Returns an array containing elements at indices in the specified [indices] range. */ public fun ShortArray.sliceArray(indices: IntRange): ShortArray { if (indices.isEmpty()) return ShortArray(0) @@ -4064,7 +4064,7 @@ public fun ShortArray.sliceArray(indices: IntRange): ShortArray { } /** - * Returns a list containing elements at indices in the specified [indices] range. + * Returns an array containing elements at indices in the specified [indices] range. */ public fun IntArray.sliceArray(indices: IntRange): IntArray { if (indices.isEmpty()) return IntArray(0) @@ -4072,7 +4072,7 @@ public fun IntArray.sliceArray(indices: IntRange): IntArray { } /** - * Returns a list containing elements at indices in the specified [indices] range. + * Returns an array containing elements at indices in the specified [indices] range. */ public fun LongArray.sliceArray(indices: IntRange): LongArray { if (indices.isEmpty()) return LongArray(0) @@ -4080,7 +4080,7 @@ public fun LongArray.sliceArray(indices: IntRange): LongArray { } /** - * Returns a list containing elements at indices in the specified [indices] range. + * Returns an array containing elements at indices in the specified [indices] range. */ public fun FloatArray.sliceArray(indices: IntRange): FloatArray { if (indices.isEmpty()) return FloatArray(0) @@ -4088,7 +4088,7 @@ public fun FloatArray.sliceArray(indices: IntRange): FloatArray { } /** - * Returns a list containing elements at indices in the specified [indices] range. + * Returns an array containing elements at indices in the specified [indices] range. */ public fun DoubleArray.sliceArray(indices: IntRange): DoubleArray { if (indices.isEmpty()) return DoubleArray(0) @@ -4096,7 +4096,7 @@ public fun DoubleArray.sliceArray(indices: IntRange): DoubleArray { } /** - * Returns a list containing elements at indices in the specified [indices] range. + * Returns an array containing elements at indices in the specified [indices] range. */ public fun BooleanArray.sliceArray(indices: IntRange): BooleanArray { if (indices.isEmpty()) return BooleanArray(0) @@ -4104,7 +4104,7 @@ public fun BooleanArray.sliceArray(indices: IntRange): BooleanArray { } /** - * Returns a list containing elements at indices in the specified [indices] range. + * Returns an array containing elements at indices in the specified [indices] range. */ public fun CharArray.sliceArray(indices: IntRange): CharArray { if (indices.isEmpty()) return CharArray(0) diff --git a/libraries/stdlib/common/src/generated/_UArrays.kt b/libraries/stdlib/common/src/generated/_UArrays.kt index acae6d049f6..8858f0f299c 100644 --- a/libraries/stdlib/common/src/generated/_UArrays.kt +++ b/libraries/stdlib/common/src/generated/_UArrays.kt @@ -1383,6 +1383,178 @@ public inline fun UShortArray.singleOrNull(predicate: (UShort) -> Boolean): USho return single } +/** + * Returns a list containing elements at indices in the specified [indices] range. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UIntArray.slice(indices: IntRange): List { + if (indices.isEmpty()) return listOf() + return copyOfRange(indices.start, indices.endInclusive + 1).asList() +} + +/** + * Returns a list containing elements at indices in the specified [indices] range. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun ULongArray.slice(indices: IntRange): List { + if (indices.isEmpty()) return listOf() + return copyOfRange(indices.start, indices.endInclusive + 1).asList() +} + +/** + * Returns a list containing elements at indices in the specified [indices] range. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UByteArray.slice(indices: IntRange): List { + if (indices.isEmpty()) return listOf() + return copyOfRange(indices.start, indices.endInclusive + 1).asList() +} + +/** + * Returns a list containing elements at indices in the specified [indices] range. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UShortArray.slice(indices: IntRange): List { + if (indices.isEmpty()) return listOf() + return copyOfRange(indices.start, indices.endInclusive + 1).asList() +} + +/** + * Returns a list containing elements at specified [indices]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UIntArray.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) { + list.add(get(index)) + } + return list +} + +/** + * Returns a list containing elements at specified [indices]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun ULongArray.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) { + list.add(get(index)) + } + return list +} + +/** + * Returns a list containing elements at specified [indices]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UByteArray.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) { + list.add(get(index)) + } + return list +} + +/** + * Returns a list containing elements at specified [indices]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UShortArray.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) { + list.add(get(index)) + } + return list +} + +/** + * Returns an array containing elements of this array at specified [indices]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UIntArray.sliceArray(indices: Collection): UIntArray { + return UIntArray(storage.sliceArray(indices)) +} + +/** + * Returns an array containing elements of this array at specified [indices]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun ULongArray.sliceArray(indices: Collection): ULongArray { + return ULongArray(storage.sliceArray(indices)) +} + +/** + * Returns an array containing elements of this array at specified [indices]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UByteArray.sliceArray(indices: Collection): UByteArray { + return UByteArray(storage.sliceArray(indices)) +} + +/** + * Returns an array containing elements of this array at specified [indices]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UShortArray.sliceArray(indices: Collection): UShortArray { + return UShortArray(storage.sliceArray(indices)) +} + +/** + * Returns an array containing elements at indices in the specified [indices] range. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UIntArray.sliceArray(indices: IntRange): UIntArray { + return UIntArray(storage.sliceArray(indices)) +} + +/** + * Returns an array containing elements at indices in the specified [indices] range. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun ULongArray.sliceArray(indices: IntRange): ULongArray { + return ULongArray(storage.sliceArray(indices)) +} + +/** + * Returns an array containing elements at indices in the specified [indices] range. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UByteArray.sliceArray(indices: IntRange): UByteArray { + return UByteArray(storage.sliceArray(indices)) +} + +/** + * Returns an array containing elements at indices in the specified [indices] range. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun UShortArray.sliceArray(indices: IntRange): UShortArray { + return UShortArray(storage.sliceArray(indices)) +} + /** * Reverses elements in the array in-place. */ @@ -1533,6 +1705,34 @@ public inline fun UIntArray.asIntArray(): IntArray { return storage } +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public expect fun UIntArray.asList(): List + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public expect fun ULongArray.asList(): List + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public expect fun UByteArray.asList(): List + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public expect fun UShortArray.asList(): List + /** * Returns an array of type [LongArray], which is a view of this array where each element is a signed reinterpretation * of the corresponding element of this array. diff --git a/libraries/stdlib/js/irRuntime/generated/_ArraysJs.kt b/libraries/stdlib/js/irRuntime/generated/_ArraysJs.kt index 869cd739670..3cc16a4f3cc 100644 --- a/libraries/stdlib/js/irRuntime/generated/_ArraysJs.kt +++ b/libraries/stdlib/js/irRuntime/generated/_ArraysJs.kt @@ -85,9 +85,18 @@ public actual fun CharArray.asList(): List { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() override fun contains(element: Char): Boolean = this@asList.contains(element) - override fun get(index: Int): Char = this@asList[index] - override fun indexOf(element: Char): Int = this@asList.indexOf(element) - override fun lastIndexOf(element: Char): Int = this@asList.lastIndexOf(element) + override fun get(index: Int): Char { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: Char): Int { + if ((element as Any?) !is Char) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: Char): Int { + if ((element as Any?) !is Char) return -1 + return this@asList.lastIndexOf(element) + } } } diff --git a/libraries/stdlib/js/irRuntime/generated/_UArraysJs.kt b/libraries/stdlib/js/irRuntime/generated/_UArraysJs.kt new file mode 100644 index 00000000000..d5e1b99b498 --- /dev/null +++ b/libraries/stdlib/js/irRuntime/generated/_UArraysJs.kt @@ -0,0 +1,114 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + +import kotlin.js.* + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UIntArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UInt): Boolean = this@asList.contains(element) + override fun get(index: Int): UInt { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: UInt): Int { + if ((element as Any?) !is UInt) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: UInt): Int { + if ((element as Any?) !is UInt) return -1 + return this@asList.lastIndexOf(element) + } + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun ULongArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: ULong): Boolean = this@asList.contains(element) + override fun get(index: Int): ULong { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: ULong): Int { + if ((element as Any?) !is ULong) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: ULong): Int { + if ((element as Any?) !is ULong) return -1 + return this@asList.lastIndexOf(element) + } + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UByteArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UByte): Boolean = this@asList.contains(element) + override fun get(index: Int): UByte { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: UByte): Int { + if ((element as Any?) !is UByte) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: UByte): Int { + if ((element as Any?) !is UByte) return -1 + return this@asList.lastIndexOf(element) + } + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UShortArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UShort): Boolean = this@asList.contains(element) + override fun get(index: Int): UShort { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: UShort): Int { + if ((element as Any?) !is UShort) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: UShort): Int { + if ((element as Any?) !is UShort) return -1 + return this@asList.lastIndexOf(element) + } + } +} + diff --git a/libraries/stdlib/js/src/generated/_ArraysJs.kt b/libraries/stdlib/js/src/generated/_ArraysJs.kt index 639b78f8e13..99b92ea31e0 100644 --- a/libraries/stdlib/js/src/generated/_ArraysJs.kt +++ b/libraries/stdlib/js/src/generated/_ArraysJs.kt @@ -85,9 +85,18 @@ public actual fun CharArray.asList(): List { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() override fun contains(element: Char): Boolean = this@asList.contains(element) - override fun get(index: Int): Char = this@asList[index] - override fun indexOf(element: Char): Int = this@asList.indexOf(element) - override fun lastIndexOf(element: Char): Int = this@asList.lastIndexOf(element) + override fun get(index: Int): Char { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: Char): Int { + if ((element as Any?) !is Char) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: Char): Int { + if ((element as Any?) !is Char) return -1 + return this@asList.lastIndexOf(element) + } } } diff --git a/libraries/stdlib/js/src/generated/_UArraysJs.kt b/libraries/stdlib/js/src/generated/_UArraysJs.kt new file mode 100644 index 00000000000..d5e1b99b498 --- /dev/null +++ b/libraries/stdlib/js/src/generated/_UArraysJs.kt @@ -0,0 +1,114 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + +import kotlin.js.* + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UIntArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UInt): Boolean = this@asList.contains(element) + override fun get(index: Int): UInt { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: UInt): Int { + if ((element as Any?) !is UInt) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: UInt): Int { + if ((element as Any?) !is UInt) return -1 + return this@asList.lastIndexOf(element) + } + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun ULongArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: ULong): Boolean = this@asList.contains(element) + override fun get(index: Int): ULong { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: ULong): Int { + if ((element as Any?) !is ULong) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: ULong): Int { + if ((element as Any?) !is ULong) return -1 + return this@asList.lastIndexOf(element) + } + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UByteArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UByte): Boolean = this@asList.contains(element) + override fun get(index: Int): UByte { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: UByte): Int { + if ((element as Any?) !is UByte) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: UByte): Int { + if ((element as Any?) !is UByte) return -1 + return this@asList.lastIndexOf(element) + } + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UShortArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UShort): Boolean = this@asList.contains(element) + override fun get(index: Int): UShort { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: UShort): Int { + if ((element as Any?) !is UShort) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: UShort): Int { + if ((element as Any?) !is UShort) return -1 + return this@asList.lastIndexOf(element) + } + } +} + diff --git a/libraries/stdlib/jvm/src/generated/_UArraysJvm.kt b/libraries/stdlib/jvm/src/generated/_UArraysJvm.kt index 6a4ccd19d6c..97f8449957e 100644 --- a/libraries/stdlib/jvm/src/generated/_UArraysJvm.kt +++ b/libraries/stdlib/jvm/src/generated/_UArraysJvm.kt @@ -14,6 +14,70 @@ package kotlin.collections // +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UIntArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UInt): Boolean = this@asList.contains(element) + override fun get(index: Int): UInt = this@asList[index] + override fun indexOf(element: UInt): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: UInt): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun ULongArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: ULong): Boolean = this@asList.contains(element) + override fun get(index: Int): ULong = this@asList[index] + override fun indexOf(element: ULong): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: ULong): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UByteArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UByte): Boolean = this@asList.contains(element) + override fun get(index: Int): UByte = this@asList[index] + override fun indexOf(element: UByte): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: UByte): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UShortArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UShort): Boolean = this@asList.contains(element) + override fun get(index: Int): UShort = this@asList[index] + override fun indexOf(element: UShort): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: UShort): Int = this@asList.lastIndexOf(element) + } +} + /** * Searches the array or the range of the array for the provided [element] using the binary search algorithm. * The array is expected to be sorted, otherwise the result is undefined. diff --git a/libraries/stdlib/test/collections/UnsignedArraysTest.kt b/libraries/stdlib/test/collections/UnsignedArraysTest.kt index c501adffea2..c324527799a 100644 --- a/libraries/stdlib/test/collections/UnsignedArraysTest.kt +++ b/libraries/stdlib/test/collections/UnsignedArraysTest.kt @@ -7,6 +7,7 @@ package test.collections import test.collections.behaviors.collectionBehavior +import test.collections.behaviors.listBehavior import kotlin.test.* fun assertArrayContentEquals(expected: UIntArray, actual: UIntArray, message: String = "") { assertTrue(expected contentEquals actual, message) } @@ -19,10 +20,10 @@ class UnsignedArraysTest { @Test fun collectionBehavior() { - compare(listOf(), ubyteArrayOf()) { this.collectionBehavior() } - compare(listOf(1), ushortArrayOf(1)) { this.collectionBehavior() } - compare(listOf(1, 2), uintArrayOf(1u, 2u)) { this.collectionBehavior() } - compare(listOf(1, 2, 3), ulongArrayOf(1u, 2u, 3u)) { this.collectionBehavior() } + compare(listOf(), ubyteArrayOf()) { collectionBehavior() } + compare(listOf(1), ushortArrayOf(1)) { collectionBehavior() } + compare(listOf(1, 2), uintArrayOf(1u, 2u)) { collectionBehavior() } + compare(listOf(1, 2, 3), ulongArrayOf(1u, 2u, 3u)) { collectionBehavior() } } @Test @@ -364,4 +365,50 @@ class UnsignedArraysTest { assertArrayContentEquals(ushortArrayOf(3u, 2u, 1u), ushortArrayOf(1u, 2u, 3u).reversedArray()) assertArrayContentEquals(ulongArrayOf(3u, 2u, 1u), ulongArrayOf(1u, 2u, 3u).reversedArray()) } + + @Test + fun asList() { + compare(listOf(), ubyteArrayOf().asList()) { listBehavior() } + compare(listOf(1), ushortArrayOf(1.toUShort()).asList()) { listBehavior() } + compare(listOf(1, 2), uintArrayOf(1u, 2u).asList()) { listBehavior() } + compare(listOf(1, 2, 3), uintArrayOf(1u, 2u, 3u).asList()) { listBehavior() } + + val ulongs = ulongArrayOf(1uL, 5uL, 7uL) + val ulongsAsList = ulongs.asList() + assertEquals(5uL, ulongsAsList[1]) + ulongs[1] = 10 + assertEquals(10uL, ulongsAsList[1], "Should reflect changes in original array") + } + + @Test + fun slice() { + assertEquals(listOf(), uintArrayOf(1, 2, 3).slice(5..1)) + assertEquals(listOf(2, 3, 9), uintArrayOf(2, 3, 9, 2, 3, 9).slice(listOf(3, 1, 2))) + assertEquals(listOf(127, 100), ubyteArrayOf(50, 100, 127).slice(2 downTo 1)) + assertEquals(listOf(200, 100), ushortArrayOf(50, 100, 200).slice(2 downTo 1)) + assertEquals(listOf(100, 200, 30), ulongArrayOf(50, 100, 200, 30).slice(1..3)) + + for (range in listOf(-1 until 0, 0 until 2, 2..2)) { + val bounds = "range: $range" + val exClass = IndexOutOfBoundsException::class + assertFailsWith(exClass, bounds) { uintArrayOf(1).slice(range) } + assertFailsWith(exClass, bounds) { ulongArrayOf(1).slice(range) } + } + } + + @Test + fun sliceArray() { + assertArrayContentEquals(uintArrayOf(), uintArrayOf(1, 2, 3).sliceArray(5..1)) + assertArrayContentEquals(uintArrayOf(2, 3, 9), uintArrayOf(2, 3, 9, 2, 3, 9).sliceArray(listOf(3, 1, 2))) + assertArrayContentEquals(ubyteArrayOf(127, 100), ubyteArrayOf(50, 100, 127).sliceArray(listOf(2, 1))) + assertArrayContentEquals(ushortArrayOf(200, 100), ushortArrayOf(50, 100, 200).sliceArray(listOf(2, 1))) + assertArrayContentEquals(ulongArrayOf(100, 200, 30), ulongArrayOf(50, 100, 200, 30).sliceArray(1..3)) + + for (range in listOf(-1 until 0, 0 until 2, 2..2)) { + val bounds = "range: $range" + val exClass = IndexOutOfBoundsException::class + assertFailsWith(exClass, bounds) { ubyteArrayOf(1).sliceArray(range) } + assertFailsWith(exClass, bounds) { ushortArrayOf(1).sliceArray(range) } + } + } } \ No newline at end of file diff --git a/libraries/stdlib/unsigned/src/kotlin/UByteArray.kt b/libraries/stdlib/unsigned/src/kotlin/UByteArray.kt index dbc8cac0ff3..d6942aea744 100644 --- a/libraries/stdlib/unsigned/src/kotlin/UByteArray.kt +++ b/libraries/stdlib/unsigned/src/kotlin/UByteArray.kt @@ -46,8 +46,7 @@ internal constructor(@PublishedApi internal val storage: ByteArray) : Collection } override fun containsAll(elements: Collection): Boolean { - if ((elements as Collection).any { it as? UByte == null }) return false - return elements.all { storage.contains(it.toByte()) } + return (elements as Collection<*>).all { it is UByte && storage.contains(it.toByte()) } } override fun isEmpty(): Boolean = this.storage.size == 0 diff --git a/libraries/stdlib/unsigned/src/kotlin/UIntArray.kt b/libraries/stdlib/unsigned/src/kotlin/UIntArray.kt index 646189c325f..d53864d0dcc 100644 --- a/libraries/stdlib/unsigned/src/kotlin/UIntArray.kt +++ b/libraries/stdlib/unsigned/src/kotlin/UIntArray.kt @@ -46,8 +46,7 @@ internal constructor(@PublishedApi internal val storage: IntArray) : Collection< } override fun containsAll(elements: Collection): Boolean { - if ((elements as Collection).any { it as? UInt == null }) return false - return elements.all { storage.contains(it.toInt()) } + return (elements as Collection<*>).all { it is UInt && storage.contains(it.toInt()) } } override fun isEmpty(): Boolean = this.storage.size == 0 diff --git a/libraries/stdlib/unsigned/src/kotlin/ULongArray.kt b/libraries/stdlib/unsigned/src/kotlin/ULongArray.kt index d98e8968730..253ea81e48a 100644 --- a/libraries/stdlib/unsigned/src/kotlin/ULongArray.kt +++ b/libraries/stdlib/unsigned/src/kotlin/ULongArray.kt @@ -46,8 +46,7 @@ internal constructor(@PublishedApi internal val storage: LongArray) : Collection } override fun containsAll(elements: Collection): Boolean { - if ((elements as Collection).any { it as? ULong == null }) return false - return elements.all { storage.contains(it.toLong()) } + return (elements as Collection<*>).all { it is ULong && storage.contains(it.toLong()) } } override fun isEmpty(): Boolean = this.storage.size == 0 diff --git a/libraries/stdlib/unsigned/src/kotlin/UShortArray.kt b/libraries/stdlib/unsigned/src/kotlin/UShortArray.kt index 8f2a0264dc5..df96e10e32e 100644 --- a/libraries/stdlib/unsigned/src/kotlin/UShortArray.kt +++ b/libraries/stdlib/unsigned/src/kotlin/UShortArray.kt @@ -46,8 +46,7 @@ internal constructor(@PublishedApi internal val storage: ShortArray) : Collectio } override fun containsAll(elements: Collection): Boolean { - if ((elements as Collection).any { it as? UShort == null }) return false - return elements.all { storage.contains(it.toShort()) } + return (elements as Collection<*>).all { it is UShort && storage.contains(it.toShort()) } } override fun isEmpty(): Boolean = this.storage.size == 0 diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt index b557ac43416..b584d687250 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt @@ -2287,6 +2287,10 @@ public abstract class kotlin/collections/ShortIterator : java/util/Iterator, kot } public final class kotlin/collections/UArraysKt { + public static final fun asList--ajY-9A ([I)Ljava/util/List; + public static final fun asList-GBYM_sE ([B)Ljava/util/List; + public static final fun asList-QwZRm1k ([J)Ljava/util/List; + public static final fun asList-rL5Bavg ([S)Ljava/util/List; public static final fun binarySearch-2fe2U9s ([IIII)I public static synthetic fun binarySearch-2fe2U9s$default ([IIIIILjava/lang/Object;)I public static final fun binarySearch-EtDCXyQ ([SSII)I @@ -2343,6 +2347,22 @@ public final class kotlin/collections/UArraysKt { public static final fun singleOrNull-GBYM_sE ([B)Lkotlin/UByte; public static final fun singleOrNull-QwZRm1k ([J)Lkotlin/ULong; public static final fun singleOrNull-rL5Bavg ([S)Lkotlin/UShort; + public static final fun slice-F7u83W8 ([JLjava/lang/Iterable;)Ljava/util/List; + public static final fun slice-HwE9HBo ([ILjava/lang/Iterable;)Ljava/util/List; + public static final fun slice-JGPC0-M ([SLjava/lang/Iterable;)Ljava/util/List; + public static final fun slice-JQknh5Q ([BLjava/lang/Iterable;)Ljava/util/List; + public static final fun slice-Q6IL4kU ([SLkotlin/ranges/IntRange;)Ljava/util/List; + public static final fun slice-ZRhS8yI ([JLkotlin/ranges/IntRange;)Ljava/util/List; + public static final fun slice-c0bezYM ([BLkotlin/ranges/IntRange;)Ljava/util/List; + public static final fun slice-tAntMlw ([ILkotlin/ranges/IntRange;)Ljava/util/List; + public static final fun sliceArray-CFIt9YE ([ILjava/util/Collection;)[I + public static final fun sliceArray-Q6IL4kU ([SLkotlin/ranges/IntRange;)[S + public static final fun sliceArray-ZRhS8yI ([JLkotlin/ranges/IntRange;)[J + public static final fun sliceArray-c0bezYM ([BLkotlin/ranges/IntRange;)[B + public static final fun sliceArray-kzHmqpY ([JLjava/util/Collection;)[J + public static final fun sliceArray-ojwP5H8 ([SLjava/util/Collection;)[S + public static final fun sliceArray-tAntMlw ([ILkotlin/ranges/IntRange;)[I + public static final fun sliceArray-xo_DsdI ([BLjava/util/Collection;)[B public static final fun toTypedArray--ajY-9A ([I)[Lkotlin/UInt; public static final fun toTypedArray-GBYM_sE ([B)[Lkotlin/UByte; public static final fun toTypedArray-QwZRm1k ([J)[Lkotlin/ULong; diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt index fb4e1dbee19..bd15dabc081 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt @@ -1147,7 +1147,7 @@ object ArrayOps : TemplateGroupBase() { val f_asList = fn("asList()") { - include(ArraysOfObjects, ArraysOfPrimitives) + include(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { doc { "Returns a [List] that wraps the original array." } returns("List") @@ -1168,13 +1168,33 @@ object ArrayOps : TemplateGroupBase() { override fun lastIndexOf(element: T): Int = this@asList.lastIndexOf(element) } """ - specialFor(ArraysOfPrimitives) { + specialFor(ArraysOfPrimitives, ArraysOfUnsigned) { on(Platform.JVM) { body { objectLiteralImpl } } on(Platform.JS) { - if (primitive == PrimitiveType.Char) { - body { objectLiteralImpl } + if (primitive == PrimitiveType.Char || primitive in PrimitiveType.unsignedPrimitives) { + body { + """ + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: T): Boolean = this@asList.contains(element) + override fun get(index: Int): T { + AbstractList.checkElementIndex(index, size) + return this@asList[index] + } + override fun indexOf(element: T): Int { + if ((element as Any?) !is T) return -1 + return this@asList.indexOf(element) + } + override fun lastIndexOf(element: T): Int { + if ((element as Any?) !is T) return -1 + return this@asList.lastIndexOf(element) + } + } + """ + } } else { inlineOnly() diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt index 25755a61c25..f0231aa0421 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt @@ -17,6 +17,11 @@ object Filtering : TemplateGroupBase() { sequenceClassification(terminal) else sequenceClassification(intermediate, stateless) + + specialFor(ArraysOfUnsigned) { + since("1.3") + annotation("@ExperimentalUnsignedTypes") + } } } @@ -832,7 +837,7 @@ object Filtering : TemplateGroupBase() { val f_slice = fn("slice(indices: Iterable)") { - include(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) + include(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { doc { "Returns a list containing elements at specified [indices]." } returns("List") @@ -870,7 +875,7 @@ object Filtering : TemplateGroupBase() { } val f_slice_range = fn("slice(indices: IntRange)") { - include(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) + include(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { doc { "Returns a list containing elements at indices in the specified [indices] range." } returns("List") @@ -880,7 +885,7 @@ object Filtering : TemplateGroupBase() { return this.subList(indices.start, indices.endInclusive + 1).toList() """ } - body(ArraysOfPrimitives, ArraysOfObjects) { + body(ArraysOfPrimitives, ArraysOfObjects, ArraysOfUnsigned) { """ if (indices.isEmpty()) return listOf() return copyOfRange(indices.start, indices.endInclusive + 1).asList() @@ -900,7 +905,7 @@ object Filtering : TemplateGroupBase() { } val f_sliceArray = fn("sliceArray(indices: Collection)") { - include(InvariantArraysOfObjects, ArraysOfPrimitives) + include(InvariantArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { doc { "Returns an array containing elements of this array at specified [indices]." } returns("SELF") @@ -924,12 +929,17 @@ object Filtering : TemplateGroupBase() { return result """ } + body(ArraysOfUnsigned) { + """ + return SELF(storage.sliceArray(indices)) + """ + } } val f_sliceArrayRange = fn("sliceArray(indices: IntRange)") { - include(InvariantArraysOfObjects, ArraysOfPrimitives) + include(InvariantArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { - doc { "Returns a list containing elements at indices in the specified [indices] range." } + doc { "Returns an array containing elements at indices in the specified [indices] range." } returns("SELF") body(InvariantArraysOfObjects) { """ @@ -943,5 +953,10 @@ object Filtering : TemplateGroupBase() { return copyOfRange(indices.start, indices.endInclusive + 1) """ } + body(ArraysOfUnsigned) { + """ + return SELF(storage.sliceArray(indices)) + """ + } } }