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

commonMain.network.component.ComponentStorage.kt Maven / Gradle / Ivy

/*
 * Copyright 2019-2022 Mamoe Technologies and contributors.
 *
 * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
 * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
 *
 * https://github.com/mamoe/mirai/blob/dev/LICENSE
 */

package net.mamoe.mirai.internal.network.component

import org.jetbrains.annotations.TestOnly
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

/**
 * Mediator for [component][ComponentKey]s accessing each other.
 *
 * Implementation must be thread-safe.
 *
 * @see MutableComponentStorage
 * @see ConcurrentComponentStorage
 * @see withFallback
 */
internal interface ComponentStorage {
    @get:TestOnly
    val size: Int

    @Throws(NoSuchComponentException::class)
    operator fun  get(key: ComponentKey): T
    fun  getOrNull(key: ComponentKey): T?

    val keys: Set>

    override fun toString(): String

    companion object {
        val EMPTY: ComponentStorage by lazy { ConcurrentComponentStorage() }
    }
}

internal fun buildComponentStorage(builderAction: MutableComponentStorage.() -> Unit): ComponentStorage {
    contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
    return ConcurrentComponentStorage(builderAction)
}

internal fun ComponentStorage?.withFallback(fallback: ComponentStorage?): ComponentStorage {
    if (this == null) return fallback ?: return ComponentStorage.EMPTY
    if (fallback == null) return this
    return CombinedComponentStorage(this, fallback)
}

internal fun ComponentStorage?.withPrimary(primary: ComponentStorage?): ComponentStorage = primary.withFallback(this)

private class CombinedComponentStorage(
    val main: ComponentStorage,
    val fallback: ComponentStorage,
) : ComponentStorage {
    override val keys: Set> get() = main.keys + fallback.keys
    override val size: Int get() = main.size + fallback.size

    override fun  get(key: ComponentKey): T {
        return main.getOrNull(key) ?: fallback.getOrNull(key) ?: throw NoSuchComponentException(key, this)
            .apply {
                //
                kotlin.runCatching { main[key] }.exceptionOrNull()?.let(::addSuppressed)
                kotlin.runCatching { fallback[key] }.exceptionOrNull()?.let(::addSuppressed)
            }
    }

    override fun  getOrNull(key: ComponentKey): T? {
        return main.getOrNull(key) ?: fallback.getOrNull(key)
    }

    override fun toString(): String = buildString {
        appendLine("CombinedComponentStorage {")
        appendLine("* main:")
        main.toString().lines().forEach {
            append("  ").appendLine(it)
        }
        appendLine("*** fallback:")
        fallback.toString().lines().forEach {
            append("  ").appendLine(it)
        }
        appendLine("}")
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy