All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tagan.base.1.5.1.source-code.util.kt Maven / Gradle / Ivy

Go to download

Yatagan is a Dependency Injection framework, specializing on runtime performance and build speed. Supports code generation (apt/kapt/ksp) or reflection.

The newest version!
/*
 * Copyright 2022 Yandex LLC
 *
 * 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
 *
 * http://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.
 */

package com.yandex.yatagan.base

import java.util.ServiceLoader
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.reflect.KProperty

inline fun  ifOrElseNull(condition: Boolean, block: () -> R): R? {
    contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) }
    return if (condition) block() else null
}

inline fun  loadServices(): List {
    val serviceClass = S::class.java
    return ServiceLoader.load(serviceClass, serviceClass.classLoader).toList()
}

inline fun  Array.mapToArray(map: (T) -> R): Array {
    contract { callsInPlace(map) }
    return Array(size) { map(get(it)) }
}

inline fun  List.mapToArray(map: (T) -> R): Array {
    contract { callsInPlace(map) }
    return Array(size) { map(get(it)) }
}

fun  Sequence.zipOrNull(another: Sequence): Sequence> {
    return Sequence {
        object : Iterator> {
            val iterator1 = [email protected]()
            val iterator2 = another.iterator()

            override fun hasNext() = iterator1.hasNext() || iterator2.hasNext()
            override fun next(): Pair {
                val v1 = ifOrElseNull(iterator1.hasNext()) { iterator1.next() }
                val v2 = ifOrElseNull(iterator2.hasNext()) { iterator2.next() }
                return v1 to v2
            }
        }
    }
}

inline fun  Iterable.zipWithNextOrNull(block: (T, T?) -> R): List {
    contract { callsInPlace(block) }

    val iterator = iterator()
    if (!iterator.hasNext()) {
        return emptyList()
    }

    val iteratorNext = iterator().also { it.next() }

    val list: MutableList = when (this) {
        is Collection<*> -> ArrayList(size - 1)
        else -> ArrayList()
    }
    while (iterator.hasNext()) {
        val first = iterator.next()
        val second = ifOrElseNull(iterator.hasNext()) { iteratorNext.next() }
        list.add(block(first, second))
    }
    return list
}

inline fun  Iterable>.forEachBi(block: (K, V) -> Unit) {
    contract { callsInPlace(block) }
    forEach { (k, v) -> block(k, v) }
}

inline fun  Array>.forEachBi(block: (K, V) -> Unit) {
    contract { callsInPlace(block) }
    forEach { (k, v) -> block(k, v) }
}

fun  Iterable.sortedWithBy(comparator: Comparator, selector: (T) -> R): List {
    return sortedWith(Comparator.comparing(selector, comparator))
}

inline fun  traverseDepthFirstWithPath(
    roots: Iterable,
    childrenOf: (T) -> Iterable,
    onLoop: ((loop: Sequence) -> Unit) = { /* nothing by default */ },
    visit: (path: Sequence, node: T) -> Unit = { _, _ -> /* nothing by default */ },
) {
    val markedGray = hashSetOf()
    val markedBlack = hashSetOf()
    val stack = arrayListOf>()

    val currentPath = stack.asSequence().map { it.last() }

    stack += roots.toMutableList()

    while (stack.isNotEmpty()) {
        // Substack is introduced to preserve node hierarchy
        val subStack = stack.last()
        if (subStack.isEmpty()) {
            stack.removeLast()
            continue
        }

        when (val node = subStack.last()) {
            in markedBlack -> {
                subStack.removeLast()
            }

            in markedGray -> {
                subStack.removeLast()
                markedBlack += node
                markedGray -= node
            }

            else -> {
                markedGray += node
                visit(currentPath, node)
                stack += childrenOf(node).mapNotNullTo(arrayListOf()) { child ->
                    if (child in markedGray) {
                        // Loop: report and skip
                        onLoop(currentPath.dropWhile { it != child })
                        null
                    } else child
                }
            }
        }
    }
}

class SingleInitPropertyWithFallbackDelegate(
    private val fallbackValue: () -> T,
) {
    @Volatile private var valueHolder: Lazy = lazy(fallbackValue)

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T = valueHolder.value

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        check(!valueHolder.isInitialized()) {
            "$property was already initialized, can't initialize after usage or twice"
        }
        valueHolder = object : Lazy {
            override val value: T get() = value
            override fun isInitialized() = true
        }
    }

    fun deinitialize() {
        valueHolder = lazy(fallbackValue)
    }

    fun isInitialized(): Boolean {
        return valueHolder.isInitialized()
    }
}

fun  singleInitWithFallback(fallback: () -> T) = SingleInitPropertyWithFallbackDelegate(fallback)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy