Support Serializable Throwables

This commit is contained in:
Mygod
2020-06-26 09:01:30 +08:00
parent 8f8ede2c8c
commit bcea005d6e

View File

@@ -35,7 +35,9 @@ class RootServer @JvmOverloads constructor(private val warnLogger: (String) -> U
SUCCESS -> callback.complete(input.readParcelable(classLoader)) SUCCESS -> callback.complete(input.readParcelable(classLoader))
EX_GENERIC -> callback.completeExceptionally(RemoteException(input.readUTF())) EX_GENERIC -> callback.completeExceptionally(RemoteException(input.readUTF()))
EX_PARCELABLE -> callback.completeExceptionally(RemoteException().initCause( EX_PARCELABLE -> callback.completeExceptionally(RemoteException().initCause(
input.readParcelable<Parcelable>(classLoader) as Throwable?)) input.readParcelable<Parcelable>(classLoader) as Throwable))
EX_SERIALIZABLE -> callback.completeExceptionally(RemoteException().initCause(
input.readSerializable(classLoader) as Throwable))
else -> throw IllegalArgumentException("Unexpected result $result") else -> throw IllegalArgumentException("Unexpected result $result")
} }
} }
@@ -62,7 +64,9 @@ class RootServer @JvmOverloads constructor(private val warnLogger: (String) -> U
}) })
EX_GENERIC -> finish.completeExceptionally(RemoteException(input.readUTF())) EX_GENERIC -> finish.completeExceptionally(RemoteException(input.readUTF()))
EX_PARCELABLE -> finish.completeExceptionally(RemoteException().initCause( EX_PARCELABLE -> finish.completeExceptionally(RemoteException().initCause(
input.readParcelable<Parcelable>(classLoader) as Throwable?)) input.readParcelable<Parcelable>(classLoader) as Throwable))
EX_SERIALIZABLE -> finish.completeExceptionally(RemoteException().initCause(
input.readSerializable(classLoader) as Throwable))
CHANNEL_CONSUMED -> finish.complete(Unit) CHANNEL_CONSUMED -> finish.complete(Unit)
else -> throw IllegalArgumentException("Unexpected result $result") else -> throw IllegalArgumentException("Unexpected result $result")
} }
@@ -294,17 +298,24 @@ class RootServer @JvmOverloads constructor(private val warnLogger: (String) -> U
private const val SUCCESS = 0 private const val SUCCESS = 0
private const val EX_GENERIC = 1 private const val EX_GENERIC = 1
private const val EX_PARCELABLE = 2 private const val EX_PARCELABLE = 2
private const val EX_SERIALIZABLE = 4
private const val CHANNEL_CONSUMED = 3 private const val CHANNEL_CONSUMED = 3
private fun DataInputStream.readByteArray() = ByteArray(readInt()).also { readFully(it) }
private inline fun <reified T : Parcelable> DataInputStream.readParcelable( private inline fun <reified T : Parcelable> DataInputStream.readParcelable(
classLoader: ClassLoader? = T::class.java.classLoader classLoader: ClassLoader? = T::class.java.classLoader) = readByteArray().toParcelable<T>(classLoader)
) = ByteArray(readInt()).also { readFully(it) }.toParcelable<T>(classLoader)
private fun DataOutputStream.writeParcelable(data: Parcelable?, parcelableFlags: Int = 0) { private fun DataOutputStream.writeParcelable(data: Parcelable?, parcelableFlags: Int = 0) {
val bytes = data.toByteArray(parcelableFlags) val bytes = data.toByteArray(parcelableFlags)
writeInt(bytes.size) writeInt(bytes.size)
write(bytes) write(bytes)
} }
private fun DataInputStream.readSerializable(classLoader: ClassLoader?) =
object : ObjectInputStream(ByteArrayInputStream(readByteArray())) {
override fun resolveClass(desc: ObjectStreamClass) = Class.forName(desc.name, false, classLoader)
}.readObject()
private inline fun <T> Mutex.synchronized(crossinline block: () -> T): T = runBlocking { private inline fun <T> Mutex.synchronized(crossinline block: () -> T): T = runBlocking {
withLock { block() } withLock { block() }
} }
@@ -324,7 +335,14 @@ class RootServer @JvmOverloads constructor(private val warnLogger: (String) -> U
if (e is Parcelable) { if (e is Parcelable) {
writeByte(EX_PARCELABLE) writeByte(EX_PARCELABLE)
writeParcelable(e) writeParcelable(e)
} else { } else try {
val bytes = ByteArrayOutputStream().apply {
ObjectOutputStream(this).use { it.writeObject(e) }
}.toByteArray()
writeByte(EX_SERIALIZABLE)
writeInt(bytes.size)
write(bytes)
} catch (_: NotSerializableException) {
writeByte(EX_GENERIC) writeByte(EX_GENERIC)
writeUTF(StringWriter().also { writeUTF(StringWriter().also {
e.printStackTrace(PrintWriter(it)) e.printStackTrace(PrintWriter(it))