1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.compose.runtime
18 
19 internal interface ValueHolder<T> {
readValuenull20     fun readValue(map: PersistentCompositionLocalMap): T
21 
22     fun toProvided(local: CompositionLocal<T>): ProvidedValue<T>
23 }
24 
25 /** A StaticValueHolder holds a value that will never change. */
26 internal data class StaticValueHolder<T>(val value: T) : ValueHolder<T> {
27     override fun readValue(map: PersistentCompositionLocalMap): T = value
28 
29     override fun toProvided(local: CompositionLocal<T>): ProvidedValue<T> =
30         ProvidedValue(
31             compositionLocal = local,
32             value = value,
33             explicitNull = value === null,
34             mutationPolicy = null,
35             state = null,
36             compute = null,
37             isDynamic = false
38         )
39 }
40 
41 /**
42  * A lazy value holder is static value holder for which the value is produced by the valueProducer
43  * parameter which is called once and the result is remembered for the life of LazyValueHolder.
44  */
45 internal class LazyValueHolder<T>(valueProducer: () -> T) : ValueHolder<T> {
46     private val current by lazy(valueProducer)
47 
readValuenull48     override fun readValue(map: PersistentCompositionLocalMap): T = current
49 
50     override fun toProvided(local: CompositionLocal<T>): ProvidedValue<T> =
51         composeRuntimeError("Cannot produce a provider from a lazy value holder")
52 }
53 
54 internal data class ComputedValueHolder<T>(val compute: CompositionLocalAccessorScope.() -> T) :
55     ValueHolder<T> {
56     override fun readValue(map: PersistentCompositionLocalMap): T = map.compute()
57 
58     override fun toProvided(local: CompositionLocal<T>): ProvidedValue<T> =
59         ProvidedValue(
60             compositionLocal = local,
61             value = null,
62             explicitNull = false,
63             mutationPolicy = null,
64             state = null,
65             compute = compute,
66             isDynamic = false
67         )
68 }
69 
70 internal data class DynamicValueHolder<T>(val state: MutableState<T>) : ValueHolder<T> {
readValuenull71     override fun readValue(map: PersistentCompositionLocalMap): T = state.value
72 
73     override fun toProvided(local: CompositionLocal<T>): ProvidedValue<T> =
74         ProvidedValue(
75             compositionLocal = local,
76             value = null,
77             explicitNull = false,
78             mutationPolicy = null,
79             state = state,
80             compute = null,
81             isDynamic = true
82         )
83 }
84