• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.kairos.internal.util
18 
19 import com.android.systemui.kairos.internal.store.NoValue
20 import java.util.concurrent.ConcurrentHashMap
21 import java.util.concurrent.ConcurrentMap
22 
23 internal class ConcurrentNullableHashMap<K, V>
24 private constructor(private val inner: ConcurrentHashMap<Any, Any>) :
25     ConcurrentMap<K, V>, AbstractMutableMap<K, V>() {
26 
27     constructor() : this(ConcurrentHashMap())
28 
29     constructor(capacity: Int) : this(ConcurrentHashMap(capacity))
30 
31     override fun get(key: K): V? = inner[key ?: NullValue]?.let { toNullable<V>(it) }
32 
33     fun getValue(key: K): V = toNullable(inner.getValue(key ?: NullValue))
34 
35     @Suppress("UNCHECKED_CAST")
36     override fun put(key: K, value: V): V? =
37         inner.put(key ?: NullValue, value ?: NullValue)?.takeIf { it !== NullValue } as V?
38 
39     operator fun set(key: K, value: V) {
40         put(key, value)
41     }
42 
43     fun toMap(): Map<K, V> =
44         inner.asSequence().associate { (k, v) -> toNullable<K>(k) to toNullable(v) }
45 
46     override fun clear() {
47         inner.clear()
48     }
49 
50     override fun remove(key: K, value: V): Boolean = inner.remove(key ?: NoValue, value ?: NoValue)
51 
52     override val entries: MutableSet<MutableMap.MutableEntry<K, V>> =
53         object : AbstractMutableSet<MutableMap.MutableEntry<K, V>>() {
54             val wrapped = inner.entries
55 
56             override fun add(element: MutableMap.MutableEntry<K, V>): Boolean {
57                 val e =
58                     object : MutableMap.MutableEntry<Any, Any> {
59                         override val key: Any
60                             get() = element.key ?: NullValue
61 
62                         override val value: Any
63                             get() = element.value ?: NullValue
64 
65                         override fun setValue(newValue: Any): Any =
66                             element.setValue(toNullable(newValue)) ?: NullValue
67                     }
68                 return wrapped.add(e)
69             }
70 
71             override val size: Int
72                 get() = wrapped.size
73 
74             override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> {
75                 val iter = wrapped.iterator()
76                 return object : MutableIterator<MutableMap.MutableEntry<K, V>> {
77                     override fun hasNext(): Boolean = iter.hasNext()
78 
79                     override fun next(): MutableMap.MutableEntry<K, V> {
80                         val element = iter.next()
81                         return object : MutableMap.MutableEntry<K, V> {
82                             override val key: K
83                                 get() = toNullable(element.key)
84 
85                             override val value: V
86                                 get() = toNullable(element.value)
87 
88                             override fun setValue(newValue: V): V =
89                                 toNullable(element.setValue(newValue ?: NullValue))
90                         }
91                     }
92 
93                     override fun remove() {
94                         iter.remove()
95                     }
96                 }
97             }
98         }
99 
100     override fun replace(key: K, oldValue: V, newValue: V): Boolean =
101         inner.replace(key ?: NullValue, oldValue ?: NullValue, newValue ?: NullValue)
102 
103     override fun replace(key: K, value: V): V? =
104         inner.replace(key ?: NullValue, value ?: NullValue)?.let { toNullable<V>(it) }
105 
106     override fun putIfAbsent(key: K, value: V): V? =
107         inner.putIfAbsent(key ?: NullValue, value ?: NullValue)?.let { toNullable<V>(it) }
108 
109     @Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
110     private inline fun <T> toNullable(value: Any): T = value.takeIf { it !== NullValue } as T
111 
112     fun isNotEmpty(): Boolean = inner.isNotEmpty()
113 
114     @Suppress("UNCHECKED_CAST")
115     override fun remove(key: K): V? =
116         inner.remove(key ?: NullValue)?.takeIf { it !== NullValue } as V?
117 
118     fun asSequence(): Sequence<Pair<K, V>> =
119         inner.asSequence().map { (key, value) -> toNullable<K>(key) to toNullable(value) }
120 
121     override fun isEmpty(): Boolean = inner.isEmpty()
122 
123     override fun containsKey(key: K): Boolean = inner.containsKey(key ?: NullValue)
124 
125     fun getOrPut(key: K, defaultValue: () -> V): V =
126         toNullable(inner.getOrPut(key) { defaultValue() ?: NullValue })
127 }
128 
129 private object NullValue
130