commonMain.io.matthewnelson.immutable.collections.Immutable.kt Maven / Gradle / Ivy
/*
* Copyright (c) 2024 Matthew Nelson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
@file:JvmName("Immutable")
package io.matthewnelson.immutable.collections
import kotlin.jvm.JvmName
@JvmName("listOf")
public fun Collection.toImmutableList(): List {
if (isEmpty()) return emptyList()
if (this is ImmutableList) return this
return ImmutableList(toList())
}
@JvmName("listOf")
public fun immutableListOf(vararg elements: T): List {
if (elements.isEmpty()) return emptyList()
return ImmutableList(elements.toList())
}
@JvmName("mapOf")
public fun Map.toImmutableMap(): Map {
if (isEmpty()) return emptyMap()
if (this is ImmutableMap) return this
return ImmutableMap(toMap())
}
@JvmName("mapOf")
public fun immutableMapOf(vararg pairs: Pair): Map {
if (pairs.isEmpty()) return emptyMap()
return ImmutableMap(pairs.toMap())
}
@JvmName("setOf")
public fun Collection.toImmutableSet(): Set {
if (isEmpty()) return emptySet()
if (this is ImmutableSet) return this
return ImmutableSet(toSet())
}
@JvmName("setOf")
public fun immutableSetOf(vararg elements: T): Set {
if (elements.isEmpty()) return emptySet()
return ImmutableSet(elements.toSet())
}
private open class ImmutableCollection>(
protected val delegate: D
): Collection {
final override val size: Int get() = delegate.size
final override fun isEmpty(): Boolean = delegate.isEmpty()
final override operator fun iterator(): Iterator = ImmutableIterator(delegate.iterator())
final override fun containsAll(elements: Collection): Boolean = delegate.containsAll(elements)
final override operator fun contains(element: T): Boolean = delegate.contains(element)
final override fun equals(other: Any?): Boolean = delegate == other
final override fun hashCode(): Int = delegate.hashCode()
final override fun toString(): String = delegate.toString()
}
private class ImmutableList(
delegate: List
): ImmutableCollection>(delegate), List {
override operator fun get(index: Int): T = delegate[index]
override fun indexOf(element: T): Int = delegate.indexOf(element)
override fun lastIndexOf(element: T): Int = delegate.lastIndexOf(element)
override fun listIterator(): ListIterator = ImmutableListIterator(delegate.listIterator())
override fun listIterator(index: Int): ListIterator = ImmutableListIterator(delegate.listIterator(index))
override fun subList(fromIndex: Int, toIndex: Int): List {
if (fromIndex == 0 && toIndex == size) return this
val subList = delegate.subList(fromIndex, toIndex)
if (subList.isEmpty()) return emptyList()
return ImmutableList(subList)
}
}
private class ImmutableSet(
delegate: Set
): ImmutableCollection>(delegate), Set
private class ImmutableMap(
private val delegate: Map
): Map {
override val entries: Set> by lazy {
val entries = delegate.entries
val set = LinkedHashSet>(entries.size, 1.0F)
entries.mapTo(set) { ImmutableMapEntry(it) }
ImmutableSet(set)
}
override val keys: Set by lazy { ImmutableSet(delegate.keys) }
override val size: Int get() = delegate.size
override val values: Collection by lazy { ImmutableCollection(delegate.values) }
override fun isEmpty(): Boolean = delegate.isEmpty()
override operator fun get(key: K): V? = delegate[key]
override fun containsValue(value: V): Boolean = delegate.containsValue(value)
override fun containsKey(key: K): Boolean = delegate.containsKey(key)
override fun equals(other: Any?): Boolean = delegate == other
override fun hashCode(): Int = delegate.hashCode()
override fun toString(): String = delegate.toString()
}
private class ImmutableMapEntry(
private val delegate: Map.Entry,
): Map.Entry {
override val key: K get() = delegate.key
override val value: V get() = delegate.value
override fun equals(other: Any?): Boolean = delegate == other
override fun hashCode(): Int = delegate.hashCode()
override fun toString(): String = delegate.toString()
}
private open class ImmutableIterator>(
protected val delegate: D
): Iterator {
final override operator fun hasNext(): Boolean = delegate.hasNext()
final override operator fun next(): T = delegate.next()
final override fun equals(other: Any?): Boolean = delegate == other
final override fun hashCode(): Int = delegate.hashCode()
final override fun toString(): String = delegate.toString()
}
private class ImmutableListIterator(
delegate: ListIterator
): ImmutableIterator>(delegate), ListIterator {
override fun hasPrevious(): Boolean = delegate.hasPrevious()
override fun nextIndex(): Int = delegate.nextIndex()
override fun previous(): T = delegate.previous()
override fun previousIndex(): Int = delegate.previousIndex()
}