1  /*
2   * Copyright (C) 2023 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.server.permission.access.immutable
18  
19  import android.util.SparseArray
20  
21  /**
22   * Immutable map with index-based access, [Int] keys and mutable data structure values.
23   *
24   * @see MutableReference
25   */
26  sealed class IntReferenceMap<I : Immutable<M>, M : I>(
27      internal val array: SparseArray<MutableReference<I, M>>
28  ) : Immutable<MutableIntReferenceMap<I, M>> {
29      val size: Int
30          get() = array.size()
31  
isEmptynull32      fun isEmpty(): Boolean = array.size() == 0
33  
34      operator fun contains(key: Int): Boolean = array.contains(key)
35  
36      @Suppress("ReplaceGetOrSet") operator fun get(key: Int): I? = array.get(key)?.get()
37  
38      fun indexOfKey(key: Int): Int = array.indexOfKey(key)
39  
40      fun keyAt(index: Int): Int = array.keyAt(index)
41  
42      fun valueAt(index: Int): I = array.valueAt(index).get()
43  
44      override fun toMutable(): MutableIntReferenceMap<I, M> = MutableIntReferenceMap(this)
45  
46      override fun toString(): String = array.toString()
47  }
48  
49  /**
50   * Mutable map with index-based access, [Int] keys and mutable data structure values.
51   *
52   * @see MutableReference
53   */
54  class MutableIntReferenceMap<I : Immutable<M>, M : I>(
55      array: SparseArray<MutableReference<I, M>> = SparseArray()
56  ) : IntReferenceMap<I, M>(array) {
57      constructor(
58          intReferenceMap: IntReferenceMap<I, M>
59      ) : this(
60          intReferenceMap.array.clone().apply {
61              for (i in 0 until size()) {
62                  setValueAt(i, valueAt(i).toImmutable())
63              }
64          }
65      )
66  
67      @Suppress("ReplaceGetOrSet") fun mutate(key: Int): M? = array.get(key)?.mutate()
68  
69      fun put(key: Int, value: M): I? = array.putReturnOld(key, MutableReference(value))?.get()
70  
71      fun remove(key: Int): I? = array.removeReturnOld(key).also { array.gc() }?.get()
72  
73      fun clear() {
74          array.clear()
75      }
76  
77      fun mutateAt(index: Int): M = array.valueAt(index).mutate()
78  
79      fun putAt(index: Int, value: M): I =
80          array.setValueAtReturnOld(index, MutableReference(value)).get()
81  
82      fun removeAt(index: Int): I = array.removeAtReturnOld(index).also { array.gc() }.get()
83  }
84