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 }