Provide protected toArray implementation in AbstractCollection.
Relates to #KT-13898
This commit is contained in:
@@ -8,10 +8,10 @@ open class SingletonCollection<T>(val value: T) : AbstractCollection<T>() {
|
|||||||
override val size = 1
|
override val size = 1
|
||||||
override fun iterator(): Iterator<T> = listOf(value).iterator()
|
override fun iterator(): Iterator<T> = listOf(value).iterator()
|
||||||
|
|
||||||
protected fun toArray(): Array<Any?> =
|
protected override final fun toArray(): Array<Any?> =
|
||||||
arrayOf<Any?>(value)
|
arrayOf<Any?>(value)
|
||||||
|
|
||||||
protected fun <E> toArray(a: Array<E>): Array<E> {
|
protected override final fun <E> toArray(a: Array<E>): Array<E> {
|
||||||
a[0] = value as E
|
a[0] = value as E
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ open class SingletonCollection<T>(val value: T) : AbstractCollection<T>() {
|
|||||||
override val size = 1
|
override val size = 1
|
||||||
override fun iterator(): Iterator<T> = listOf(value).iterator()
|
override fun iterator(): Iterator<T> = listOf(value).iterator()
|
||||||
|
|
||||||
protected open fun toArray(): Array<Any?> =
|
protected override fun toArray(): Array<Any?> =
|
||||||
arrayOf<Any?>(value)
|
arrayOf<Any?>(value)
|
||||||
|
|
||||||
protected open fun <E> toArray(a: Array<E>): Array<E> {
|
protected override fun <E> toArray(a: Array<E>): Array<E> {
|
||||||
a[0] = value as E
|
a[0] = value as E
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public inline fun <T> Collection<T>.toTypedArray(): Array<T> = copyToArray(this)
|
|||||||
@JsName("copyToArray")
|
@JsName("copyToArray")
|
||||||
internal fun <T> copyToArray(collection: Collection<T>): Array<T> {
|
internal fun <T> copyToArray(collection: Collection<T>): Array<T> {
|
||||||
return if (collection.asDynamic().toArray !== undefined)
|
return if (collection.asDynamic().toArray !== undefined)
|
||||||
collection.asDynamic().toArray()
|
collection.asDynamic().toArray().unsafeCast<Array<T>>()
|
||||||
else
|
else
|
||||||
copyToArrayImpl(collection).unsafeCast<Array<T>>()
|
copyToArrayImpl(collection).unsafeCast<Array<T>>()
|
||||||
}
|
}
|
||||||
@@ -41,6 +41,22 @@ internal fun copyToArrayImpl(collection: Collection<*>): Array<Any?> {
|
|||||||
return array
|
return array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsName("copyToExistingArrayImpl")
|
||||||
|
internal fun <T> copyToArrayImpl(collection: Collection<*>, array: Array<T>): Array<T> {
|
||||||
|
if (array.size < collection.size)
|
||||||
|
return copyToArrayImpl(collection).unsafeCast<Array<T>>()
|
||||||
|
|
||||||
|
val iterator = collection.iterator()
|
||||||
|
var index = 0
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
array[index++] = iterator.next().unsafeCast<T>()
|
||||||
|
}
|
||||||
|
if (index < array.size) {
|
||||||
|
array[index] = null.unsafeCast<T>()
|
||||||
|
}
|
||||||
|
return array
|
||||||
|
}
|
||||||
|
|
||||||
@library("arrayToString")
|
@library("arrayToString")
|
||||||
internal fun arrayToString(array: Array<*>): String = noImpl
|
internal fun arrayToString(array: Array<*>): String = noImpl
|
||||||
|
|
||||||
|
|||||||
@@ -51,9 +51,6 @@ public abstract class AbstractMutableCollection<E> protected constructor() : Abs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move somehow to AbstractCollection: can't move now, because it cannot be protected on JVM, just public
|
|
||||||
protected open fun toArray(): Array<Any?> = copyToArrayImpl(this)
|
|
||||||
|
|
||||||
open fun toJSON(): Any = this.toArray()
|
open fun toJSON(): Any = this.toArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -158,4 +158,8 @@ header operator fun <K, V> MutableMap<K, V>.set(key: K, value: V): Unit
|
|||||||
|
|
||||||
// from Grouping.kt
|
// from Grouping.kt
|
||||||
public header fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int>
|
public header fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int>
|
||||||
// public header inline fun <T, K> Grouping<T, K>.eachSumOf(valueSelector: (T) -> Int): Map<K, Int>
|
// public header inline fun <T, K> Grouping<T, K>.eachSumOf(valueSelector: (T) -> Int): Map<K, Int>
|
||||||
|
|
||||||
|
internal header fun copyToArrayImpl(collection: Collection<*>): Array<Any?>
|
||||||
|
|
||||||
|
internal header fun <T> copyToArrayImpl(collection: Collection<*>, array: Array<T>): Array<T>
|
||||||
|
|||||||
@@ -31,7 +31,14 @@ public abstract class AbstractCollection<out E> protected constructor() : Collec
|
|||||||
if (it === this) "(this Collection)" else it.toString()
|
if (it === this) "(this Collection)" else it.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns new array of type `Array<Any?>` with the elements of this collection.
|
||||||
|
*/
|
||||||
|
protected open fun toArray(): Array<Any?> = copyToArrayImpl(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills the provided [array] or creates new array of the same type
|
||||||
|
* and fills it with the elements of this collection.
|
||||||
|
*/
|
||||||
|
protected open fun <T> toArray(array: Array<T>): Array<T> = copyToArrayImpl(this, array)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -182,6 +182,16 @@ internal fun <T> List<T>.optimizeReadOnlyList() = when (size) {
|
|||||||
else -> this
|
else -> this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmVersion
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
internal inline fun copyToArrayImpl(collection: Collection<*>): Array<Any?> =
|
||||||
|
kotlin.jvm.internal.CollectionToArray.toArray(collection)
|
||||||
|
|
||||||
|
@JvmVersion
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
internal inline fun <T> copyToArrayImpl(collection: Collection<*>, array: Array<T>): Array<T> =
|
||||||
|
kotlin.jvm.internal.CollectionToArray.toArray(collection, array)
|
||||||
|
|
||||||
// copies typed varargs array to array of objects
|
// copies typed varargs array to array of objects
|
||||||
@JvmVersion
|
@JvmVersion
|
||||||
private fun <T> Array<out T>.copyToArrayOfAny(isVarargs: Boolean): Array<Any?> =
|
private fun <T> Array<out T>.copyToArrayOfAny(isVarargs: Boolean): Array<Any?> =
|
||||||
|
|||||||
@@ -905,4 +905,30 @@ class CollectionTest {
|
|||||||
assertTrue(listOf(1) is RandomAccess, "Default singleton list is RandomAccess")
|
assertTrue(listOf(1) is RandomAccess, "Default singleton list is RandomAccess")
|
||||||
assertTrue(emptyList<Int>() is RandomAccess, "Empty list is RandomAccess")
|
assertTrue(emptyList<Int>() is RandomAccess, "Empty list is RandomAccess")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun abstractCollectionToArray() {
|
||||||
|
class TestCollection<out E>(val data: Collection<E>) : AbstractCollection<E>() {
|
||||||
|
val invocations = mutableListOf<String>()
|
||||||
|
override val size get() = data.size
|
||||||
|
override fun iterator() = data.iterator()
|
||||||
|
|
||||||
|
override fun toArray(): Array<Any?> {
|
||||||
|
invocations += "toArray1"
|
||||||
|
return data.toTypedArray()
|
||||||
|
}
|
||||||
|
public override fun <T> toArray(array: Array<T>): Array<T> {
|
||||||
|
invocations += "toArray2"
|
||||||
|
return super.toArray(array)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val data = listOf("abc", "def")
|
||||||
|
val coll = TestCollection(data)
|
||||||
|
|
||||||
|
val arr1 = coll.toTypedArray()
|
||||||
|
assertEquals(data, arr1.asList())
|
||||||
|
assertTrue("toArray1" in coll.invocations || "toArray2" in coll.invocations)
|
||||||
|
|
||||||
|
val arr2: Array<String> = coll.toArray(Array(coll.size + 1) { "" })
|
||||||
|
assertEquals(data + listOf(null), arr2.asList())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user