diff --git a/js/js.libraries/src/core/kotlin.kt b/js/js.libraries/src/core/kotlin.kt index b27b133f014..96643f62da5 100644 --- a/js/js.libraries/src/core/kotlin.kt +++ b/js/js.libraries/src/core/kotlin.kt @@ -33,3 +33,20 @@ public fun booleanArrayOf(vararg content : Boolean): BooleanArray = noImpl library("copyToArray") public fun Collection.toTypedArray(): Array = noImpl + + +/** + * Returns an immutable list containing only the specified object [value]. + */ +public fun listOf(value: T): List = arrayListOf(value) + +/** + * Returns an immutable set containing only the specified object [value]. + */ +public fun setOf(value: T): Set = hashSetOf(value) + +/** + * Returns an immutable map, mapping only the specified key to the + * specified value. + */ +public fun mapOf(keyValuePair: Pair): Map = hashMapOf(keyValuePair) \ No newline at end of file diff --git a/libraries/stdlib/src/kotlin/collections/JUtil.kt b/libraries/stdlib/src/kotlin/collections/JUtil.kt index d6fa2899de7..6e486e64257 100644 --- a/libraries/stdlib/src/kotlin/collections/JUtil.kt +++ b/libraries/stdlib/src/kotlin/collections/JUtil.kt @@ -1,54 +1,76 @@ package kotlin +import java.io.Serializable import java.util.* -private object EmptyList : List { - private val list = ArrayList() - - override fun contains(o: Any?): Boolean = list.contains(o) - override fun containsAll(c: Collection): Boolean = list.containsAll(c) - override fun get(index: Int): Any = list.get(index) - override fun indexOf(o: Any?): Int = list.indexOf(o) - override fun isEmpty(): Boolean = list.isEmpty() - override fun iterator(): Iterator = list.iterator() - override fun lastIndexOf(o: Any?): Int = list.lastIndexOf(o) - override fun listIterator(): ListIterator = list.listIterator() - override fun listIterator(index: Int): ListIterator =list.listIterator(index) - override fun size(): Int = list.size() - override fun subList(fromIndex: Int, toIndex: Int): List = list.subList(fromIndex, toIndex) - override fun equals(other: Any?): Boolean = list.equals(other) - override fun hashCode(): Int = list.hashCode() - override fun toString(): String = list.toString() +private object EmptyIterator : ListIterator { + override fun hasNext(): Boolean = false + override fun hasPrevious(): Boolean = false + override fun nextIndex(): Int = 0 + override fun previousIndex(): Int = -1 + override fun next(): Nothing = throw NoSuchElementException() + override fun previous(): Nothing = throw NoSuchElementException() } -private object EmptySet : Set { - private val set = HashSet() +private object EmptyList : List, Serializable { + override fun equals(other: Any?): Boolean = other is List<*> && other.isEmpty() + override fun hashCode(): Int = 1 + override fun toString(): String = "[]" - override fun contains(o: Any?): Boolean = set.contains(o) - override fun containsAll(c: Collection): Boolean = set.containsAll(c) - override fun isEmpty(): Boolean = set.isEmpty() - override fun iterator(): Iterator = set.iterator() - override fun size(): Int = set.size() - override fun equals(other: Any?): Boolean = set.equals(other) - override fun hashCode(): Int = set.hashCode() - override fun toString(): String = set.toString() + override fun size(): Int = 0 + override fun isEmpty(): Boolean = true + override fun contains(o: Any?): Boolean = false + override fun containsAll(c: Collection): Boolean = c.isEmpty() + + override fun get(index: Int): Nothing = throw IndexOutOfBoundsException("Index $index is out of bound of empty list.") + override fun indexOf(o: Any?): Int = -1 + override fun lastIndexOf(o: Any?): Int = -1 + + override fun iterator(): Iterator = EmptyIterator + override fun listIterator(): ListIterator = EmptyIterator + override fun listIterator(index: Int): ListIterator { + if (index != 0) throw IndexOutOfBoundsException("Index: $index") + return EmptyIterator + } + + override fun subList(fromIndex: Int, toIndex: Int): List { + if (fromIndex == 0 && toIndex == 0) return this + throw IndexOutOfBoundsException("fromIndex: $fromIndex, toIndex: $toIndex") + } + + private fun readResolve(): Any = EmptyList } -/** Returns an empty read-only list. */ -public fun emptyList(): List = EmptyList as List -/** Returns an empty read-only set. */ -public fun emptySet(): Set = EmptySet as Set +private object EmptySet : Set, Serializable { + override fun equals(other: Any?): Boolean = other is Set<*> && other.isEmpty() + override fun hashCode(): Int = 0 + override fun toString(): String = "[]" -/** Returns a new read-only list of given elements */ -public fun listOf(vararg values: T): List = if (values.size() == 0) emptyList() else arrayListOf(*values) + override fun size(): Int = 0 + override fun isEmpty(): Boolean = true + override fun contains(o: Any?): Boolean = false + override fun containsAll(c: Collection): Boolean = c.isEmpty() -/** Returns an empty read-only list. */ + override fun iterator(): Iterator = EmptyIterator + + private fun readResolve(): Any = EmptySet +} + +/** Returns an empty read-only list. The returned list is serializable (JVM). */ +public fun emptyList(): List = EmptyList +/** Returns an empty read-only set. The returned set is serializable (JVM). */ +public fun emptySet(): Set = EmptySet + +/** Returns a new read-only list of given elements. The returned list is serializable (JVM). */ +public fun listOf(vararg values: T): List = if (values.size() > 0) arrayListOf(*values) else emptyList() + +/** Returns an empty read-only list. The returned list is serializable (JVM). */ public fun listOf(): List = emptyList() -/** Returns a new read-only ordered set with the given elements. */ -public fun setOf(vararg values: T): Set = if (values.size() == 0) emptySet() else values.toCollection(LinkedHashSet(mapCapacity(values.size()))) +/** Returns a new read-only ordered set with the given elements. The returned set is serializable (JVM). */ +public fun setOf(vararg values: T): Set = if (values.size() > 0) values.toSet() else emptySet() -/** Returns an empty read-only set. */ +/** Returns an empty read-only set. The returned set is serializable (JVM). */ public fun setOf(): Set = emptySet() /** Returns a new [LinkedList] with the given elements. */ diff --git a/libraries/stdlib/src/kotlin/collections/JUtilJVM.kt b/libraries/stdlib/src/kotlin/collections/JUtilJVM.kt index 3b53eb14641..845edc73e91 100644 --- a/libraries/stdlib/src/kotlin/collections/JUtilJVM.kt +++ b/libraries/stdlib/src/kotlin/collections/JUtilJVM.kt @@ -2,6 +2,25 @@ package kotlin import java.util.* + +/** + * Returns an immutable list containing only the specified object [value]. + * The returned list is serializable. + */ +public fun listOf(value: T): List = Collections.singletonList(value) + +/** + * Returns an immutable set containing only the specified object [value]. + * The returned set is serializable. + */ +public fun setOf(value: T): Set = Collections.singleton(value) + +/** + * Returns an immutable map, mapping only the specified key to the + * specified value. The returned map is serializable. + */ +public fun mapOf(keyValuePair: Pair): Map = Collections.singletonMap(keyValuePair.first, keyValuePair.second) + /** * Returns a new [SortedSet] with the given elements. */ diff --git a/libraries/stdlib/src/kotlin/collections/Maps.kt b/libraries/stdlib/src/kotlin/collections/Maps.kt index 10a9d03e347..34273ed66ed 100644 --- a/libraries/stdlib/src/kotlin/collections/Maps.kt +++ b/libraries/stdlib/src/kotlin/collections/Maps.kt @@ -1,34 +1,39 @@ package kotlin +import java.io.Serializable import java.util.* -private object EmptyMap : Map { - private val map = HashMap() +private object EmptyMap : Map, Serializable { + override fun equals(other: Any?): Boolean = other is Map<*,*> && other.isEmpty() + override fun hashCode(): Int = 0 + override fun toString(): String = "{}" - override fun containsKey(key: Any?): Boolean = map.containsKey(key) - override fun containsValue(value: Any?): Boolean = map.containsValue(value) - override fun entrySet(): Set> = map.entrySet() - override fun get(key: Any?): Any? = map.get(key) - override fun keySet(): Set = map.keySet() - override fun values(): Collection = map.values() - override fun isEmpty(): Boolean = map.isEmpty() - override fun size(): Int = map.size() - override fun equals(other: Any?): Boolean = map.equals(other) - override fun hashCode(): Int = map.hashCode() - override fun toString(): String = map.toString() + override fun size(): Int = 0 + override fun isEmpty(): Boolean = true + + override fun containsKey(key: Any?): Boolean = false + override fun containsValue(value: Any?): Boolean = false + override fun get(key: Any?): Nothing? = null + override fun entrySet(): Set> = EmptySet + override fun keySet(): Set = EmptySet + override fun values(): Collection = EmptyList + + private fun readResolve(): Any = EmptyMap } -/** Returns an empty read-only map of specified type */ +/** Returns an empty read-only map of specified type. The returned map is serializable (JVM). */ public fun emptyMap(): Map = EmptyMap as Map /** * Returns a new read-only map with the specified contents, given as a list of pairs * where the first value is the key and the second is the value. If multiple pairs have * the same key, the resulting map will contain the value from the last of those pairs. + * + * The returned map is serializable (JVM). */ -public fun mapOf(vararg values: Pair): Map = if (values.size() == 0) emptyMap() else linkedMapOf(*values) +public fun mapOf(vararg values: Pair): Map = if (values.size() > 0) linkedMapOf(*values) else emptyMap() -/** Returns an empty read-only map */ +/** Returns an empty read-only map. The returned map is serializable (JVM). */ public fun mapOf(): Map = emptyMap() /** @@ -77,8 +82,7 @@ private fun mapCapacity(expectedSize: Int): Int { /** * Returns the [Map] if its not null, or the empty [Map] otherwise. */ -public fun Map?.orEmpty() : Map - = if (this != null) this else emptyMap() +public fun Map?.orEmpty() : Map = this ?: emptyMap() /** * Checks if the map contains the given key. This method allows to use the `x in map` syntax for checking diff --git a/libraries/stdlib/src/kotlin/collections/Sequence.kt b/libraries/stdlib/src/kotlin/collections/Sequence.kt index 38b7c80a3a5..97a04d45ce1 100644 --- a/libraries/stdlib/src/kotlin/collections/Sequence.kt +++ b/libraries/stdlib/src/kotlin/collections/Sequence.kt @@ -68,12 +68,7 @@ public fun sequenceOf(progression: Progression): Sequence = object : S public fun emptySequence(): Sequence = EmptySequence private object EmptySequence : Sequence { - override fun iterator(): Iterator = EmptySequenceIterator -} - -private object EmptySequenceIterator : Iterator { - override fun next(): Nothing = throw NoSuchElementException("Sequence is empty.") - override fun hasNext(): Boolean = false + override fun iterator(): Iterator = EmptyIterator } deprecated("Use FilteringSequence instead") diff --git a/libraries/stdlib/test/collections/CollectionJVMTest.kt b/libraries/stdlib/test/collections/CollectionJVMTest.kt index 066372a174d..7b34b6fe356 100644 --- a/libraries/stdlib/test/collections/CollectionJVMTest.kt +++ b/libraries/stdlib/test/collections/CollectionJVMTest.kt @@ -1,5 +1,9 @@ package test.collections +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.ObjectInputStream +import java.io.ObjectOutputStream import kotlin.test.* import java.util.* @@ -142,4 +146,25 @@ class CollectionJVMTest { val charValues: List = src.filterIsInstance() assertEquals(0, charValues.size()) } + + test fun emptyListIsSerializable() = testSingletonSerialization(emptyList()) + + test fun emptySetIsSerializable() = testSingletonSerialization(emptySet()) + + + private fun testSingletonSerialization(value: Any) { + val outputStream = ByteArrayOutputStream() + val objectOuputStream = ObjectOutputStream(outputStream) + + objectOuputStream.writeObject(value) + objectOuputStream.close() + outputStream.close() + + val inputStream = ByteArrayInputStream(outputStream.toByteArray()) + val inputObjectStream = ObjectInputStream(inputStream) + val result = inputObjectStream.readObject() + + assertEquals(value, result) + assertTrue(value === result) + } }