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