Skip to content

Commit bcfc805

Browse files
committed
fix: tweaks to ModernVersionPatcher
1 parent 5c2417c commit bcfc805

2 files changed

Lines changed: 330 additions & 30 deletions

File tree

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
package com.mineinabyss.packy.helpers
2+
3+
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap
4+
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
5+
import it.unimi.dsi.fastutil.objects.ObjectArrayList
6+
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet
7+
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
8+
import java.util.*
9+
import kotlin.also
10+
import kotlin.apply
11+
import kotlin.collections.addAll
12+
import kotlin.collections.associateByTo
13+
import kotlin.collections.associateTo
14+
import kotlin.collections.associateWithTo
15+
import kotlin.collections.copyOf
16+
import kotlin.collections.count
17+
import kotlin.collections.filterIsInstanceTo
18+
import kotlin.collections.filterTo
19+
import kotlin.collections.flatMapTo
20+
import kotlin.collections.mapNotNullTo
21+
import kotlin.collections.mapTo
22+
import kotlin.collections.set
23+
import kotlin.collections.toMap
24+
import kotlin.let
25+
import kotlin.ranges.coerceAtLeast
26+
import kotlin.sequences.filterTo
27+
import kotlin.to
28+
29+
inline fun <T, R> Iterable<T>.flatMapFast(transform: (T) -> Iterable<R>): ObjectArrayList<R> {
30+
return flatMapTo(ObjectArrayList<R>(), transform)
31+
}
32+
33+
inline fun <T, R> Iterable<T>.flatMapFastNotNull(transform: (T) -> Iterable<R?>): ObjectArrayList<R> {
34+
val result = ObjectArrayList<R>()
35+
for (element in this) {
36+
for (item in transform(element)) {
37+
if (item != null) result.add(item)
38+
}
39+
}
40+
return result
41+
}
42+
43+
inline fun <T, R> Iterable<T>.flatMapSetFast(transform: (T) -> Iterable<R>): ObjectLinkedOpenHashSet<R> {
44+
return flatMapTo(ObjectLinkedOpenHashSet<R>(), transform)
45+
}
46+
47+
inline fun <T, R> Iterable<T>.mapFast(transform: (T) -> R): ObjectArrayList<R> {
48+
return mapTo(ObjectArrayList<R>((this as? Collection)?.size ?: 10), transform)
49+
}
50+
51+
inline fun <T, R : Any> Iterable<T>.mapNotNullFast(transform: (T) -> R?): ObjectArrayList<R> {
52+
return mapNotNullTo(ObjectArrayList<R>(), transform)
53+
}
54+
55+
inline fun <T, R> Iterable<T>.mapFastSet(transform: (T) -> R): ObjectOpenHashSet<R> {
56+
return mapTo(ObjectOpenHashSet<R>((this as? Collection)?.size ?: 10), transform)
57+
}
58+
59+
inline fun <T, reified R> Iterable<T>.toTypedArrayIndexed(transform: (Int, T) -> R): Array<R> {
60+
val result = arrayOfNulls<R>(this.count())
61+
var index = 0
62+
for (item in this) result[index] = transform(index, item).also { index++ }
63+
return result as Array<R>
64+
}
65+
66+
inline fun <T, reified R> Iterable<T>.toTypedArray(transform: (T) -> R): Array<R> {
67+
val result = arrayOfNulls<R>(this.count())
68+
var index = 0
69+
for (item in this) result[index++] = transform(item)
70+
return result as Array<R>
71+
}
72+
73+
inline fun <T, reified R> Array<T>.toTypedArray(transform: (T) -> R): Array<R> {
74+
val result = arrayOfNulls<R>(this.count())
75+
var index = 0
76+
for (item in this) result[index++] = transform(item)
77+
return result as Array<R>
78+
}
79+
80+
inline fun <T, reified R : Any> Iterable<T>.toTypedArrayNotNull(transform: (T) -> R?): Array<R> {
81+
var result = arrayOfNulls<R>(this.count())
82+
var index = 0
83+
84+
for (item in this) {
85+
transform(item)?.let {
86+
if (index >= result.size) {
87+
result = result.copyOf(kotlin.comparisons.maxOf(result.size * 2, this.count()))
88+
}
89+
result[index++] = it
90+
}
91+
}
92+
93+
// Trim to exact size
94+
return result.copyOf(index) as Array<R>
95+
}
96+
97+
98+
inline fun <T, K, V> Iterable<T>.associateFast(transform: (T) -> Pair<K, V>): Object2ObjectOpenHashMap<K, V> {
99+
val capacity = mapCapacity((this as? Collection)?.size ?: 10).coerceAtLeast(16)
100+
return associateTo(Object2ObjectOpenHashMap<K, V>(capacity), transform)
101+
}
102+
103+
inline fun <T, K, V> Array<T>.associateFast(transform: (T) -> Pair<K, V>): Object2ObjectOpenHashMap<K, V> {
104+
val capacity = mapCapacity(size).coerceAtLeast(16)
105+
return associateTo(Object2ObjectOpenHashMap<K, V>(capacity), transform)
106+
}
107+
108+
inline fun <T, K> Iterable<T>.associateFastBy(keySelector: (T) -> K): Object2ObjectOpenHashMap<K, T> {
109+
val result = Object2ObjectOpenHashMap<K, T>(mapCapacity((this as? Collection)?.size ?: 10).coerceAtLeast(16))
110+
return associateByTo(result, keySelector)
111+
}
112+
113+
inline fun <K, V> Iterable<K>.associateFastWith(valueSelector: (K) -> V): Object2ObjectOpenHashMap<K, V> {
114+
val result = Object2ObjectOpenHashMap<K, V>(mapCapacity((this as? Collection)?.size ?: 10).coerceAtLeast(16))
115+
return associateWithTo(result, valueSelector)
116+
}
117+
118+
inline fun <T, K, V> Iterable<T>.associateFastLinked(pairSelector: (T) -> Pair<K, V>): Object2ObjectLinkedOpenHashMap<K, V> {
119+
val result = Object2ObjectLinkedOpenHashMap<K, V>(mapCapacity((this as? Collection)?.size ?: 10).coerceAtLeast(16))
120+
return associateTo(result, pairSelector)
121+
}
122+
123+
inline fun <K, V> Iterable<K>.associateFastLinkedWith(valueSelector: (K) -> V): Object2ObjectLinkedOpenHashMap<K, V> {
124+
val result = Object2ObjectLinkedOpenHashMap<K, V>(mapCapacity((this as? Collection)?.size ?: 10).coerceAtLeast(16))
125+
return associateWithTo(result, valueSelector)
126+
}
127+
128+
inline fun <T, K, V> Iterable<T>.associateFastNotNull(
129+
pairSelector: (T) -> Pair<K?, V?>?
130+
): Object2ObjectOpenHashMap<K, V> {
131+
val result = Object2ObjectOpenHashMap<K, V>(mapCapacity((this as? Collection)?.size ?: 10).coerceAtLeast(16))
132+
for (element in this) {
133+
val (key, value) = pairSelector(element)?.let { (it.first ?: continue) to (it.second ?: continue) } ?: continue
134+
result[key] = value
135+
}
136+
return result
137+
}
138+
139+
inline fun <T, K, V> Iterable<T>.associateFastLinkedNotNull(
140+
pairSelector: (T) -> Pair<K?, V?>?
141+
): Object2ObjectLinkedOpenHashMap<K, V> {
142+
val result = Object2ObjectLinkedOpenHashMap<K, V>(mapCapacity((this as? Collection)?.size ?: 10).coerceAtLeast(16))
143+
for (element in this) {
144+
val (key, value) = pairSelector(element)?.let { (it.first ?: continue) to (it.second ?: continue) } ?: continue
145+
result[key] = value
146+
}
147+
return result
148+
}
149+
150+
inline fun <T, K, V> Iterable<T>.associateFastByNotNull(
151+
keySelector: (T) -> K?,
152+
valueSelector: (T) -> V?
153+
): Object2ObjectOpenHashMap<K, V> {
154+
val result = Object2ObjectOpenHashMap<K, V>(mapCapacity((this as? Collection)?.size ?: 10).coerceAtLeast(16))
155+
for (element in this) {
156+
val key = keySelector(element) ?: continue
157+
val value = valueSelector(element) ?: continue
158+
result[key] = value
159+
}
160+
return result
161+
}
162+
163+
inline fun <reified R> Iterable<*>.filterFastIsInstance(): ObjectArrayList<R> {
164+
return filterIsInstanceTo(ObjectArrayList<R>())
165+
}
166+
167+
inline fun <reified R> Iterable<*>.filterFastIsInstance(predicate: (R) -> Boolean): ObjectArrayList<R> {
168+
val result = ObjectArrayList<R>()
169+
for (element in this) if (element is R && predicate(element)) result.add(element)
170+
return result
171+
}
172+
173+
inline fun <T> Iterable<T>.filterFast(predicate: (T) -> Boolean): ObjectArrayList<T> {
174+
return filterTo(ObjectArrayList<T>(), predicate)
175+
}
176+
177+
inline fun <T> Iterable<T>.filterFastSet(predicate: (T) -> Boolean): ObjectOpenHashSet<T> {
178+
return filterTo(ObjectOpenHashSet<T>(), predicate)
179+
}
180+
181+
inline fun <reified R> Sequence<*>.filterFastIsInstance(predicate: (R) -> Boolean): ObjectArrayList<R> {
182+
val result = ObjectArrayList<R>()
183+
for (element in this) if (element is R && predicate(element)) result.add(element)
184+
return result
185+
}
186+
187+
inline fun <T> Sequence<T>.filterFast(predicate: (T) -> Boolean): ObjectArrayList<T> {
188+
return filterTo(ObjectArrayList<T>(), predicate)
189+
}
190+
191+
inline fun <T> Sequence<T>.filterFastSet(predicate: (T) -> Boolean): ObjectOpenHashSet<T> {
192+
return filterTo(ObjectOpenHashSet<T>(), predicate)
193+
}
194+
195+
inline fun <K, V> Map<out K, V>.filterFast(predicate: (Map.Entry<K, V>) -> Boolean): Object2ObjectOpenHashMap<K, V> {
196+
return filterTo(Object2ObjectOpenHashMap<K, V>(), predicate)
197+
}
198+
199+
fun <K, V> Iterable<Pair<K, V>>.toFastMap(): Object2ObjectOpenHashMap<K, V> {
200+
if (this is Collection) {
201+
return when (size) {
202+
0 -> Object2ObjectOpenHashMap()
203+
1 -> fastMapOf(if (this is List) this[0] else iterator().next())
204+
else -> toMap(Object2ObjectOpenHashMap<K, V>(mapCapacity(size)))
205+
}
206+
}
207+
return toMap(LinkedHashMap<K, V>()).optimizeReadOnlyMap()
208+
}
209+
210+
fun <K, V> fastMapOf(pair: Pair<K, V>): Object2ObjectOpenHashMap<K, V> = Object2ObjectOpenHashMap<K, V>().apply { put(pair.first, pair.second) }
211+
212+
fun mapCapacity(expectedSize: Int): Int = when {
213+
// We are not coercing the value to a valid one and not throwing an exception. It is up to the caller to
214+
// properly handle negative values.
215+
expectedSize < 0 -> expectedSize
216+
expectedSize < 3 -> expectedSize + 1
217+
expectedSize < INT_MAX_POWER_OF_TWO -> ((expectedSize / 0.75F) + 1.0F).toInt()
218+
// any large value
219+
else -> Int.MAX_VALUE
220+
}
221+
222+
internal fun <K, V> Map<K, V>.optimizeReadOnlyMap() = when (size) {
223+
0 -> Object2ObjectOpenHashMap()
224+
1 -> Object2ObjectOpenHashMap(with(entries.iterator().next()) {
225+
Collections.singletonMap(key, value)
226+
})
227+
else -> Object2ObjectOpenHashMap(this)
228+
}
229+
230+
private const val INT_MAX_POWER_OF_TWO: Int = 1 shl (Int.SIZE_BITS - 2)
231+
232+
fun <T> List<T>.plusFast(elements: Iterable<T>): ObjectArrayList<T> {
233+
if (elements is Collection) {
234+
val result = ObjectArrayList<T>(this.size + elements.size)
235+
result.addAll(this)
236+
result.addAll(elements)
237+
return result
238+
} else {
239+
val result = ObjectArrayList<T>(this)
240+
result.addAll(elements)
241+
return result
242+
}
243+
}
244+
245+
fun <T> Set<T>.plusFast(elements: Iterable<T>): ObjectOpenHashSet<T> {
246+
if (elements is Collection) {
247+
val result = ObjectOpenHashSet<T>(this.size + elements.size)
248+
result.addAll(this)
249+
result.addAll(elements)
250+
return result
251+
} else {
252+
val result = ObjectOpenHashSet<T>(this)
253+
result.addAll(elements)
254+
return result
255+
}
256+
}
257+
258+
inline fun <T, K> Iterable<T>.groupByFast(keySelector: (T) -> K): Object2ObjectLinkedOpenHashMap<K, ObjectArrayList<T>> {
259+
val map = Object2ObjectLinkedOpenHashMap<K, ObjectArrayList<T>>()
260+
for (element in this) {
261+
val key = keySelector(element)
262+
map.computeIfAbsent(key) { ObjectArrayList() }.add(element)
263+
}
264+
return map
265+
}
266+
267+
inline fun <T, K> Iterable<T>.groupByFastSet(keySelector: (T) -> K): Object2ObjectLinkedOpenHashMap<K, ObjectOpenHashSet<T>> {
268+
val map = Object2ObjectLinkedOpenHashMap<K, ObjectOpenHashSet<T>>()
269+
for (element in this) {
270+
val key = keySelector(element)
271+
map.computeIfAbsent(key) { ObjectOpenHashSet() }.add(element)
272+
}
273+
return map
274+
}

0 commit comments

Comments
 (0)