1 /*
<lambda>null2  * Copyright (C) 2020 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
18 
19 import android.util.SparseArray
20 
21 /**
22  * Transforms a sequence of Key/Value pairs into a SparseArray.
23  *
24  * See [kotlin.collections.toMap].
25  */
26 fun <T> Sequence<Pair<Int, T>>.toSparseArray(size: Int = -1): SparseArray<T> {
27     val sparseArray = when {
28         size < 0 -> SparseArray<T>()
29         else -> SparseArray<T>(size)
30     }
31     for ((i, v) in this) {
32         sparseArray.put(i, v)
33     }
34     return sparseArray
35 }
36 
37 /**
38  * Transforms an [Array] into a [SparseArray], by applying each element to [keySelector] in order to
39  * generate the index at which it will be placed. If two elements produce the same index, the latter
40  * replaces the former in the final result.
41  *
42  * See [Array.associateBy].
43  */
associateByToSparseArraynull44 inline fun <T> Array<T>.associateByToSparseArray(
45     crossinline keySelector: (T) -> Int
46 ): SparseArray<T> {
47     val sparseArray = SparseArray<T>(size)
48     for (value in this) {
49         sparseArray.put(keySelector(value), value)
50     }
51     return sparseArray
52 }
53 
54 /**
55  * Folds a [Grouping] into a [SparseArray]. See [Grouping.fold].
56  */
foldToSparseArraynull57 inline fun <T, R> Grouping<T, Int>.foldToSparseArray(
58     initial: R,
59     size: Int = -1,
60     crossinline operation: (R, T) -> R
61 ): SparseArray<R> {
62     val sparseArray = when {
63         size < 0 -> SparseArray<R>()
64         else -> SparseArray<R>(size)
65     }
66     sourceIterator().forEach { elem ->
67         val key = keyOf(elem)
68         val acc = sparseArray.get(key) ?: initial
69         sparseArray.put(key, operation(acc, elem))
70     }
71     return sparseArray
72 }
73 
74 /**
75  * Wraps this [SparseArray] into an immutable [Map], the methods of which forward to this
76  * [SparseArray].
77  */
asMapnull78 fun <T> SparseArray<T>.asMap(): Map<Int, T> = SparseArrayMapWrapper(this)
79 
80 private class SparseArrayMapWrapper<T>(
81     private val sparseArray: SparseArray<T>
82 ) : Map<Int, T> {
83 
84     private data class Entry<T>(override val key: Int, override val value: T) : Map.Entry<Int, T>
85 
86     private val entrySequence = sequence {
87         val size = sparseArray.size()
88         for (i in 0 until size) {
89             val key = sparseArray.keyAt(i)
90             val value = sparseArray.get(key)
91             yield(Entry(key, value))
92         }
93     }
94 
95     override val entries: Set<Map.Entry<Int, T>>
96         get() = object : Set<Map.Entry<Int, T>> {
97             override val size: Int
98                 get() = this@SparseArrayMapWrapper.size
99 
100             override fun contains(element: Map.Entry<Int, T>): Boolean =
101                     sparseArray[element.key]?.let { it == element.value } == true
102 
103             override fun containsAll(elements: Collection<Map.Entry<Int, T>>): Boolean =
104                     elements.all { contains(it) }
105 
106             override fun isEmpty(): Boolean = size == 0
107 
108             override fun iterator(): Iterator<Map.Entry<Int, T>> = entrySequence.iterator()
109         }
110 
111     override val keys: Set<Int> = object : Set<Int> {
112         private val keySequence = entrySequence.map { it.key }
113 
114         override val size: Int
115             get() = this@SparseArrayMapWrapper.size
116 
117         override fun contains(element: Int): Boolean = containsKey(element)
118 
119         override fun containsAll(elements: Collection<Int>): Boolean =
120                 elements.all { contains(it) }
121 
122         override fun isEmpty(): Boolean = size == 0
123 
124         override fun iterator(): Iterator<Int> = keySequence.iterator()
125     }
126     override val size: Int
127         get() = sparseArray.size()
128     override val values: Collection<T>
129         get() = object : Collection<T> {
130             private val valueSequence = entrySequence.map { it.value }
131 
132             override val size: Int
133                 get() = this@SparseArrayMapWrapper.size
134 
135             override fun contains(element: T): Boolean = containsValue(element)
136 
137             override fun containsAll(elements: Collection<T>): Boolean =
138                     elements.all { contains(it) }
139 
140             override fun isEmpty(): Boolean = this@SparseArrayMapWrapper.isEmpty()
141 
142             override fun iterator(): Iterator<T> = valueSequence.iterator()
143         }
144 
145     override fun containsKey(key: Int): Boolean = sparseArray.contains(key)
146 
147     override fun containsValue(value: T): Boolean = sparseArray.indexOfValue(value) >= 0
148 
149     override fun get(key: Int): T? = sparseArray.get(key)
150 
151     override fun isEmpty(): Boolean = sparseArray.size() == 0
152 }