Created
September 26, 2024 13:27
-
-
Save marcellogalhardo/bc965d663038dfea9c3adca9dc98f553 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@file:Suppress( | |
"IMPLICIT_CAST_TO_ANY", | |
"UNCHECKED_CAST", | |
"IMPLICIT_CAST_TO_ANY", | |
"NOTHING_TO_INLINE", | |
"UNUSED_PARAMETER", | |
"KotlinOperator", | |
"KotlinConstantConditions", | |
"unused", | |
) | |
import android.os.Binder | |
import android.os.Bundle | |
import android.os.IBinder | |
import android.os.Parcelable | |
import android.util.Size | |
import android.util.SizeF | |
import android.util.SparseArray | |
import androidx.core.os.BundleCompat | |
import java.io.Serializable | |
object BundleUtils { | |
inline operator fun <reified T> get(bundle: Bundle, key: String): T = | |
with(bundle) { | |
return when (T::class) { | |
// Scalars | |
Boolean::class -> getBoolean(key) | |
Byte::class -> getByte(key) | |
Char::class -> getChar(key) | |
Double::class -> getDouble(key) | |
Float::class -> getFloat(key) | |
Int::class -> getInt(key) | |
Long::class -> getLong(key) | |
Short::class -> getShort(key) | |
// Scalar arrays | |
BooleanArray::class -> getBooleanArray(key) | |
ByteArray::class -> getByteArray(key) | |
CharArray::class -> getCharArray(key) | |
DoubleArray::class -> getDoubleArray(key) | |
FloatArray::class -> getFloatArray(key) | |
IntArray::class -> getIntArray(key) | |
LongArray::class -> getLongArray(key) | |
ShortArray::class -> getShortArray(key) | |
// References | |
Bundle::class -> getBundle(key) | |
CharSequence::class -> getCharSequence(key) | |
String::class -> getString(key) | |
// Reference arrays | |
Array::class -> { | |
val componentType = T::class.java.componentType!! | |
when { | |
Parcelable::class.java.isAssignableFrom(componentType) -> { | |
BundleCompat.getParcelableArray( | |
this, | |
key, | |
componentType as Class<Parcelable> | |
) | |
} | |
String::class.java.isAssignableFrom(componentType) -> { | |
getStringArray(key) | |
} | |
CharSequence::class.java.isAssignableFrom(componentType) -> { | |
getCharSequence(key) | |
} | |
Serializable::class.java.isAssignableFrom(componentType) -> { | |
BundleCompat.getSerializable( | |
this, | |
key, | |
componentType as Class<Serializable> | |
) | |
} | |
else -> { | |
val valueType = componentType.canonicalName | |
throw IllegalArgumentException( | |
"Illegal value array type $valueType for key \"$key\"" | |
) | |
} | |
} | |
} | |
IBinder::class -> getBinder(key) | |
Size::class -> getSize(key) | |
SizeF::class -> getSizeF(key) | |
else -> | |
// Last resort. | |
when { | |
Parcelable::class.java.isAssignableFrom(T::class.java) -> | |
BundleCompat.getParcelable( | |
this, | |
key, | |
T::class.java as Class<out Parcelable> | |
) | |
Serializable::class.java.isAssignableFrom(T::class.java) -> | |
BundleCompat.getSerializable( | |
this, | |
key, | |
T::class.java as Class<out Serializable> | |
) | |
else -> { | |
val valueType = T::class.java.canonicalName | |
throw IllegalArgumentException( | |
"Illegal value type $valueType for key \"$key\"" | |
) | |
} | |
} | |
} | |
as T | |
} | |
inline fun <reified T> put(bundle: Bundle, key: String, value: T) { | |
with(bundle) { | |
when (value) { | |
// Scalars | |
is Boolean -> putBoolean(key, value) | |
is Byte -> putByte(key, value) | |
is Char -> putChar(key, value) | |
is Double -> putDouble(key, value) | |
is Float -> putFloat(key, value) | |
is Int -> putInt(key, value) | |
is Long -> putLong(key, value) | |
is Short -> putShort(key, value) | |
// Scalar arrays | |
is BooleanArray -> putBooleanArray(key, value) | |
is ByteArray -> putByteArray(key, value) | |
is CharArray -> putCharArray(key, value) | |
is DoubleArray -> putDoubleArray(key, value) | |
is FloatArray -> putFloatArray(key, value) | |
is IntArray -> putIntArray(key, value) | |
is LongArray -> putLongArray(key, value) | |
is ShortArray -> putShortArray(key, value) | |
// References | |
is Bundle -> putBundle(key, value) | |
is CharSequence -> putCharSequence(key, value) | |
is Parcelable -> putParcelable(key, value) | |
is String -> putString(key, value) | |
// Reference arrays | |
is Array<*> -> { | |
val componentType = value!!::class.java.componentType!! | |
when { | |
Parcelable::class.java.isAssignableFrom(componentType) -> { | |
putParcelableArray(key, value as Array<Parcelable>) | |
} | |
String::class.java.isAssignableFrom(componentType) -> { | |
putStringArray(key, value as Array<String>) | |
} | |
CharSequence::class.java.isAssignableFrom(componentType) -> { | |
putCharSequenceArray(key, value as Array<CharSequence>) | |
} | |
Serializable::class.java.isAssignableFrom(componentType) -> { | |
putSerializable(key, componentType as Class<Serializable>) | |
} | |
else -> { | |
val valueType = componentType.canonicalName | |
throw IllegalArgumentException( | |
"Illegal value array type $valueType for key \"$key\"" | |
) | |
} | |
} | |
} | |
// Last resort. Also we must check this after Array<*> as all arrays are | |
// serializable. | |
is Serializable -> putSerializable(key, value) | |
is IBinder -> putBinder(key, value) | |
is Size -> putSize(key, value) | |
is SizeF -> putSizeF(key, value) | |
else -> { | |
val valueType = T::class.java.canonicalName | |
throw IllegalArgumentException("Illegal value type $valueType for key \"$key\"") | |
} | |
} | |
} | |
} | |
@PublishedApi | |
internal inline fun <reified T : Any> Collection<*>.toArrayListUnsafe(): ArrayList<T> { | |
return if (this is ArrayList<*>) this as ArrayList<T> else ArrayList(this as Collection<T>) | |
} | |
inline fun isSupported(bundle: Bundle, value: Any?): Boolean { | |
return value == null || SUPPORTED_TYPES.any { type -> type.isInstance(value) } | |
} | |
@PublishedApi | |
internal val SUPPORTED_TYPES = | |
arrayOf( // baseBundle | |
Boolean::class, | |
BooleanArray::class, | |
Double::class, | |
DoubleArray::class, | |
Int::class, | |
IntArray::class, | |
Long::class, | |
LongArray::class, | |
String::class, | |
Array<String>::class, // bundle | |
Binder::class, | |
Bundle::class, | |
Byte::class, | |
ByteArray::class, | |
Char::class, | |
CharArray::class, | |
CharSequence::class, | |
Array<CharSequence>::class, | |
// type erasure ¯\_(ツ)_/¯, we won't eagerly check elements contents | |
ArrayList::class, | |
Float::class, | |
FloatArray::class, | |
Parcelable::class, | |
Array<Parcelable>::class, | |
Serializable::class, | |
Short::class, | |
ShortArray::class, | |
SparseArray::class, | |
Size::class, | |
SizeF::class, | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment