1 /*
<lambda>null2  * 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.util.kotlin
18 
19 import kotlinx.coroutines.flow.Flow
20 import kotlinx.coroutines.flow.combine
21 import kotlinx.coroutines.flow.distinctUntilChanged
22 import kotlinx.coroutines.flow.map
23 
24 object BooleanFlowOperators {
25     /**
26      * Logical AND operator for boolean flows. Will collect all flows and [combine] them to
27      * determine the result.
28      *
29      * Usage:
30      * ```
31      * val result = allOf(flow1, flow2)
32      * ```
33      */
34     fun allOf(vararg flows: Flow<Boolean>): Flow<Boolean> = flows.asIterable().all()
35 
36     /**
37      * Logical AND operator for boolean flows. Will collect all flows and [combine] them to
38      * determine the result.
39      */
40     fun Array<Flow<Boolean>>.all(): Flow<Boolean> = allOf(*this)
41 
42     /**
43      * Logical AND operator for boolean flows. Will collect all flows and [combine] them to
44      * determine the result.
45      */
46     fun Iterable<Flow<Boolean>>.all(): Flow<Boolean> =
47         combine(this) { values -> values.all { it } }.distinctUntilChanged()
48 
49     /**
50      * Logical NOT operator for a boolean flow.
51      *
52      * Usage:
53      * ```
54      * val negatedFlow = not(flow)
55      * ```
56      */
57     fun not(flow: Flow<Boolean>) = flow.map { !it }
58 
59     /**
60      * Logical OR operator for a boolean flow. Will collect all flows and [combine] them to
61      * determine the result.
62      */
63     fun anyOf(vararg flows: Flow<Boolean>): Flow<Boolean> = flows.asIterable().any()
64 
65     /**
66      * Logical OR operator for a boolean flow. Will collect all flows and [combine] them to
67      * determine the result.
68      */
69     fun Array<Flow<Boolean>>.any(): Flow<Boolean> = anyOf(*this)
70 
71     /**
72      * Logical OR operator for a boolean flow. Will collect all flows and [combine] them to
73      * determine the result.
74      */
75     fun Iterable<Flow<Boolean>>.any(): Flow<Boolean> =
76         combine(this) { values -> values.any { it } }.distinctUntilChanged()
77 
78     /**
79      * Returns a Flow that produces `true` when all input flows are producing `false`, otherwise
80      * produces `false`.
81      */
82     fun noneOf(vararg flows: Flow<Boolean>): Flow<Boolean> = not(anyOf(*flows))
83 
84     /**
85      * Returns a Flow that produces `true` when all input flows are producing `false`, otherwise
86      * produces `false`.
87      */
88     fun Array<Flow<Boolean>>.none(): Flow<Boolean> = noneOf(*this)
89 
90     /**
91      * Returns a Flow that produces `true` when all input flows are producing `false`, otherwise
92      * produces `false`.
93      */
94     fun Iterable<Flow<Boolean>>.none(): Flow<Boolean> = not(any())
95 }
96