xref: /aosp_15_r20/frameworks/base/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/These.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2024 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 com.android.systemui.kairos.util
18 
19 /** Contains at least one of two potential values. */
20 sealed class These<A, B> {
21     /** Contains a single potential value. */
22     class This<A, B> internal constructor(val thiz: A) : These<A, B>()
23 
24     /** Contains a single potential value. */
25     class That<A, B> internal constructor(val that: B) : These<A, B>()
26 
27     /** Contains both potential values. */
28     class Both<A, B> internal constructor(val thiz: A, val that: B) : These<A, B>()
29 
30     companion object {
31         /** Constructs a [These] containing only [thiz]. */
thiznull32         fun <A, B> thiz(thiz: A): These<A, B> = This(thiz)
33 
34         /** Constructs a [These] containing only [that]. */
35         fun <A, B> that(that: B): These<A, B> = That(that)
36 
37         /** Constructs a [These] containing both [thiz] and [that]. */
38         fun <A, B> both(thiz: A, that: B): These<A, B> = Both(thiz, that)
39     }
40 }
41 
42 /**
43  * Returns a single value from this [These]; either the single value held within, or the result of
44  * applying [f] to both values.
45  */
46 inline fun <A> These<A, A>.merge(f: (A, A) -> A): A =
47     when (this) {
48         is These.This -> thiz
49         is These.That -> that
50         is These.Both -> f(thiz, that)
51     }
52 
53 /** Returns the [These.This] [value][These.This.thiz] present in this [These] as a [Maybe]. */
maybeThisnull54 fun <A> These<A, *>.maybeThis(): Maybe<A> =
55     when (this) {
56         is These.Both -> just(thiz)
57         is These.That -> None
58         is These.This -> just(thiz)
59     }
60 
61 /**
62  * Returns the [These.This] [value][These.This.thiz] present in this [These], or `null` if not
63  * present.
64  */
thisOrNullnull65 fun <A : Any> These<A, *>.thisOrNull(): A? =
66     when (this) {
67         is These.Both -> thiz
68         is These.That -> null
69         is These.This -> thiz
70     }
71 
72 /** Returns the [These.That] [value][These.That.that] present in this [These] as a [Maybe]. */
maybeThatnull73 fun <A> These<*, A>.maybeThat(): Maybe<A> =
74     when (this) {
75         is These.Both -> just(that)
76         is These.That -> just(that)
77         is These.This -> None
78     }
79 
80 /**
81  * Returns the [These.That] [value][These.That.that] present in this [These], or `null` if not
82  * present.
83  */
thatOrNullnull84 fun <A : Any> These<*, A>.thatOrNull(): A? =
85     when (this) {
86         is These.Both -> that
87         is These.That -> that
88         is These.This -> null
89     }
90 
91 /** Returns [These.Both] values present in this [These] as a [Maybe]. */
maybeBothnull92 fun <A, B> These<A, B>.maybeBoth(): Maybe<Pair<A, B>> =
93     when (this) {
94         is These.Both -> just(thiz to that)
95         else -> None
96     }
97 
98 /** Returns a [These] containing [thiz] and/or [that] if they are present. */
thesenull99 fun <A, B> these(thiz: Maybe<A>, that: Maybe<B>): Maybe<These<A, B>> =
100     when (thiz) {
101         is Just ->
102             just(
103                 when (that) {
104                     is Just -> These.both(thiz.value, that.value)
105                     else -> These.thiz(thiz.value)
106                 }
107             )
108         else ->
109             when (that) {
110                 is Just -> just(These.that(that.value))
111                 else -> none
112             }
113     }
114 
115 /**
116  * Returns a [These] containing [thiz] and/or [that] if they are non-null, or `null` if both are
117  * `null`.
118  */
theseNullnull119 fun <A : Any, B : Any> theseNull(thiz: A?, that: B?): These<A, B>? =
120     thiz?.let { that?.let { These.both(thiz, that) } ?: These.thiz(thiz) }
<lambda>null121         ?: that?.let { These.that(that) }
122 
123 /**
124  * Returns two maps, with [Pair.first] containing all [These.This] values and [Pair.second]
125  * containing all [These.That] values.
126  *
127  * If the value is [These.Both], then the associated key with appear in both output maps, bound to
128  * [These.Both.thiz] and [These.Both.that] in each respective output.
129  */
partitionThesenull130 fun <K, A, B> Map<K, These<A, B>>.partitionThese(): Pair<Map<K, A>, Map<K, B>> {
131     val a = mutableMapOf<K, A>()
132     val b = mutableMapOf<K, B>()
133     for ((k, t) in this) {
134         when (t) {
135             is These.Both -> {
136                 a[k] = t.thiz
137                 b[k] = t.that
138             }
139             is These.That -> {
140                 b[k] = t.that
141             }
142             is These.This -> {
143                 a[k] = t.thiz
144             }
145         }
146     }
147     return a to b
148 }
149