• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 import com.android.systemui.kairos.util.Maybe.Present
20 
21 /** Contains at least one of two potential values. */
22 sealed class These<out A, out B> {
23     /** A [These] that contains a [First] value. */
24     class First<A, B> internal constructor(val value: A) : These<A, B>()
25 
26     /** A [These] that contains a [Second] value. */
27     class Second<A, B> internal constructor(val value: B) : These<A, B>()
28 
29     /** A [These] that contains [Both] a [first] and [second] value. */
30     class Both<A, B> internal constructor(val first: A, val second: B) : These<A, B>()
31 
32     companion object {
33         /** Constructs a [These] containing the first possibility. */
firstnull34         fun <A> first(value: A): These<A, Nothing> = First(value)
35 
36         /** Constructs a [These] containing the second possibility. */
37         fun <B> second(value: B): These<Nothing, B> = Second(value)
38 
39         /** Constructs a [These] containing both possibilities. */
40         fun <A, B> both(first: A, second: B): These<A, B> = Both(first, second)
41     }
42 }
43 
44 /**
45  * Returns a single value from this [These]; either the single value held within, or the result of
46  * applying [f] to both values.
47  */
48 inline fun <A> These<A, A>.merge(f: (A, A) -> A): A =
49     when (this) {
50         is These.First -> value
51         is These.Second -> value
52         is These.Both -> f(first, second)
53     }
54 
55 /** Returns the [These.First] [value][These.First.value] present in this [These] as a [Maybe]. */
maybeFirstnull56 fun <A> These<A, *>.maybeFirst(): Maybe<A> =
57     when (this) {
58         is These.Both -> Maybe.present(first)
59         is These.Second -> Maybe.absent
60         is These.First -> Maybe.present(value)
61     }
62 
63 /**
64  * Returns the [These.First] [value][These.First.value] present in this [These], or `null` if not
65  * present.
66  */
firstOrNullnull67 fun <A : Any> These<A, *>.firstOrNull(): A? =
68     when (this) {
69         is These.Both -> first
70         is These.Second -> null
71         is These.First -> value
72     }
73 
74 /** Returns the [These.Second] [value][These.Second.value] present in this [These] as a [Maybe]. */
maybeSecondnull75 fun <A> These<*, A>.maybeSecond(): Maybe<A> =
76     when (this) {
77         is These.Both -> Maybe.present(second)
78         is These.Second -> Maybe.present(value)
79         is These.First -> Maybe.absent
80     }
81 
82 /**
83  * Returns the [These.Second] [value][These.Second.value] present in this [These], or `null` if not
84  * present.
85  */
secondOrNullnull86 fun <A : Any> These<*, A>.secondOrNull(): A? =
87     when (this) {
88         is These.Both -> second
89         is These.Second -> value
90         is These.First -> null
91     }
92 
93 /** Returns [These.Both] values present in this [These] as a [Maybe]. */
maybeBothnull94 fun <A, B> These<A, B>.maybeBoth(): Maybe<Pair<A, B>> =
95     when (this) {
96         is These.Both -> Maybe.present(first to second)
97         else -> Maybe.absent
98     }
99 
100 /** Returns a [These] containing [first] and/or [second] if they are present. */
thesenull101 fun <A, B> these(first: Maybe<A>, second: Maybe<B>): Maybe<These<A, B>> =
102     when (first) {
103         is Present ->
104             Maybe.present(
105                 when (second) {
106                     is Present -> These.both(first.value, second.value)
107                     else -> These.first(first.value)
108                 }
109             )
110 
111         else ->
112             when (second) {
113                 is Present -> Maybe.present(These.second(second.value))
114                 else -> Maybe.absent
115             }
116     }
117 
118 /**
119  * Returns a [These] containing [first] and/or [second] if they are non-null, or `null` if both are
120  * `null`.
121  */
theseNotNullnull122 fun <A : Any, B : Any> theseNotNull(first: A?, second: B?): These<A, B>? =
123     first?.let { second?.let { These.both(first, second) } ?: These.first(first) }
<lambda>null124         ?: second?.let { These.second(second) }
125 
126 /**
127  * Returns two maps, with [Pair.first] containing all [These.First] values and [Pair.second]
128  * containing all [These.Second] values.
129  *
130  * If the value is [These.Both], then the associated key with appear in both output maps, bound to
131  * [These.Both.first] and [These.Both.second] in each respective output.
132  */
partitionThesenull133 fun <K, A, B> Map<K, These<A, B>>.partitionThese(): Pair<Map<K, A>, Map<K, B>> {
134     val a = mutableMapOf<K, A>()
135     val b = mutableMapOf<K, B>()
136     for ((k, t) in this) {
137         when (t) {
138             is These.Both -> {
139                 a[k] = t.first
140                 b[k] = t.second
141             }
142             is These.Second -> {
143                 b[k] = t.value
144             }
145             is These.First -> {
146                 a[k] = t.value
147             }
148         }
149     }
150     return a to b
151 }
152