package com.android.onboarding.contracts import android.content.Intent /** Marks functions that read or write intent data */ @DslMarker internal annotation class IntentManipulationDsl /** Interface for writing an object to an [Intent] and reading the same object from an [Intent]. */ interface IntentSerializer { /** * Utility intent builder that allows writing the [arg] and customising the intent settings * * @param arg to serialize into intent extras * @param builder to configure the intent */ @IntentManipulationDsl fun Intent(arg: V, builder: Intent.() -> Unit = {}): Intent = Intent().also { write(it, arg) it.builder() } /** * Utility intent builder that allows writing the [arg] and customising the intent settings * * @param action the intent should send * @param arg to serialize into intent extras * @param builder to configure the intent */ @IntentManipulationDsl fun Intent(action: String, arg: V, builder: Intent.() -> Unit = {}): Intent = Intent(arg) { this.action = action builder() } fun write(intent: Intent, value: V) fun read(intent: Intent): V /** * Calls [read] to get the value, but instead of throwing an error during read failures it instead * catches it, prints stack trace and returns null */ fun readOrNull(intent: Intent): V? = runCatching { read(intent) }.onFailure(Throwable::printStackTrace).getOrNull() } /** * A serializer that does not expose [Intent] directly and instead works via [NodeAwareIntentScope] * abstraction that can be observed * * TODO This is living as a separate opt-in interface for now, but we should look into incorporating * it inside the contract class to make methods enforceable and protected */ interface NodeAwareIntentSerializer : IntentSerializer, NodeAware { fun NodeAwareIntentScope.write(value: V) fun NodeAwareIntentScope.read(): V override fun write(intent: Intent, value: V): Unit = NodeAwareIntentScope(nodeId, intent).use { it.write(value) } override fun read(intent: Intent): V = NodeAwareIntentScope(nodeId, intent).use { it.read() } }