Skip to content

Commit

Permalink
Fixed ByteArrayParcel implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
chRyNaN committed Sep 12, 2022
1 parent 48b87e8 commit 245a081
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 70 deletions.
11 changes: 10 additions & 1 deletion parcelable-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ kotlin {
android()
jvm()
js(BOTH) {
browser()
browser {
testTask {
useKarma { useFirefox() }
}
}
nodejs()
}
ios()
Expand All @@ -31,6 +35,11 @@ kotlin {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val iosMain by sourceSets.getting
val iosSimulatorArm64Main by sourceSets.getting
iosSimulatorArm64Main.dependsOn(iosMain)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.chrynan.parcelable.core

import kotlin.experimental.and

/**
* A [Parcel] implementation that stores its underlying data into a [ByteArray].
*
Expand Down Expand Up @@ -118,43 +116,43 @@ class ByteArrayParcel internal constructor(initial: ByteArray = byteArrayOf()) :
override fun writeShort(value: Short) {
data.add(dataPosition, value.toByteArray())

dataPosition
dataPosition++
}

override fun writeInt(value: Int) {
data.add(dataPosition, value.toByteArray())

dataPosition
dataPosition++
}

override fun writeLong(value: Long) {
data.add(dataPosition, value.toByteArray())

dataPosition
dataPosition++
}

override fun writeFloat(value: Float) {
data.add(dataPosition, value.toByteArray())

dataPosition
dataPosition++
}

override fun writeDouble(value: Double) {
data.add(dataPosition, value.toByteArray())

dataPosition
dataPosition++
}

override fun writeChar(value: Char) {
data.add(dataPosition, value.toByteArray())

dataPosition
dataPosition++
}

override fun writeString(value: String) {
data.add(dataPosition, value.toByteArray())

dataPosition
dataPosition++
}

override fun recycle() {
Expand All @@ -172,7 +170,7 @@ class ByteArrayParcel internal constructor(initial: ByteArray = byteArrayOf()) :
}

data.forEach { dataItemArray ->
byteList.size.toByteArray().forEach {
dataItemArray.size.toByteArray().forEach {
byteList.add(it)
}

Expand All @@ -186,22 +184,25 @@ class ByteArrayParcel internal constructor(initial: ByteArray = byteArrayOf()) :

private fun setDataFromByteArray(value: ByteArray) {
data.clear()
dataPosition = 0

if (value.size >= 4) {
val size = value.copyOfRange(fromIndex = 0, toIndex = 4).toIntValue()
val dataListSize = value.copyOfRange(fromIndex = 0, toIndex = 4).toIntValue()

if (size > 0) {
if (dataListSize > 0) {
var i = 4

while (i < value.size) {
val s = value.copyOfRange(fromIndex = i, toIndex = i + 4).toIntValue()
val subListSize = value.copyOfRange(fromIndex = i, toIndex = i + 4).toIntValue()

i += 4

if (s > 0) {
data.add(value.copyOfRange(fromIndex = i, toIndex = i + s))
if (subListSize > 0) {
data.add(value.copyOfRange(fromIndex = i, toIndex = i + subListSize))

i += s
i += subListSize
} else {
data.add(byteArrayOf())
}
}
}
Expand All @@ -212,35 +213,9 @@ class ByteArrayParcel internal constructor(initial: ByteArray = byteArrayOf()) :

private fun Short.toByteArray(): ByteArray = toInt().toByteArray()

private fun Int.toByteArray(): ByteArray {
val size = Int.SIZE_BYTES
val result = ByteArray(size)
var l = this

for (i in size - 1 downTo 0) {
result[i] = (l and 0xFF).toByte()
l = l shr size
}

return result
}

private fun Long.toByteArray(): ByteArray {
val size = Long.SIZE_BYTES
val result = ByteArray(size)
var l = this

for (i in size - 1 downTo 0) {
result[i] = (l and 0xFF).toByte()
l = l shr size
}

return result
}

private fun Float.toByteArray(): ByteArray = toRawBits().toByteArray()

private fun Double.toByteArray(): ByteArray = toRawBits().toByteArray()
private fun Double.toByteArray(): ByteArray = toBits().toByteArray()

@Suppress("DEPRECATION")
private fun Char.toByteArray(): ByteArray = toInt().toByteArray()
Expand All @@ -251,28 +226,6 @@ class ByteArrayParcel internal constructor(initial: ByteArray = byteArrayOf()) :

private fun ByteArray.toShortValue(): Short = toIntValue().toShort()

private fun ByteArray.toIntValue(): Int {
var result = 0

for (i in 0 until Int.SIZE_BYTES) {
result = result shl Int.SIZE_BYTES
result = (result or (this[i] and 0xFF.toByte()).toInt())
}

return result
}

private fun ByteArray.toLongValue(): Long {
var result = 0L

for (i in 0 until Long.SIZE_BYTES) {
result = result shl Long.SIZE_BYTES
result = (result or (this[i] and 0xFF.toByte()).toLong())
}

return result
}

private fun ByteArray.toFloatValue(): Float = Float.fromBits(toIntValue())

private fun ByteArray.toDoubleValue(): Double = Double.fromBits(toLongValue())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.chrynan.parcelable.core

import kotlin.experimental.and

/**
* Converts this [Int] value into a [ByteArray] representation.
*/
internal fun Int.toByteArray(): ByteArray {
val result = ByteArray(Int.SIZE_BYTES)
var value = this

for (i in Int.SIZE_BYTES - 1 downTo 0) {
result[i] = (value and 0xFF).toByte()
value = value shr Byte.SIZE_BITS
}

return result
}

/**
* Converts this [Long] value into a [ByteArray] representation.
*/
internal fun Long.toByteArray(): ByteArray {
val result = ByteArray(Long.SIZE_BYTES)
var value = this

for (i in 0 until Long.SIZE_BYTES) {
result[Long.SIZE_BYTES - i - 1] = (value and 0xFF).toByte()
value = value ushr Byte.SIZE_BITS
}

return result
}

/**
* Converts this [ByteArray] representation of a [Long] value into a [Long] value.
*/
internal fun ByteArray.toLongValue(): Long {
require(this.size == Long.SIZE_BYTES) { "ByteArray must have a size of 8 to convert to a Long." }

var result = 0L

for (i in 0 until Long.SIZE_BYTES) {
result = result shl Byte.SIZE_BITS
result = (result or (this[i].toLong() and 0xFF))
}

return result
}

/**
* Converts this [ByteArray] representation of an [Int] value into an [Int] value.
*
* **Note:** This function is not safe for use outside this library as it doesn't expose, make guarantees about, or
* provide a way to change the endianness ordering.
*/
internal fun ByteArray.toIntValue(): Int {
var result = 0

for (i in 0 until Int.SIZE_BYTES) {
result = result shl Byte.SIZE_BITS
result = (result or (this[i] and 0xFF.toByte()).toInt())
}

return result
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ sealed class Parcelable(internal val configuration: ParcelableConfiguration) : S
* @return The decoded value of [T].
*/
fun <T> decodeFromParcel(parcel: Parcel, deserializer: DeserializationStrategy<T>): T {
val decoder = ParcelDecoder(serializersModule = serializersModule, input = parcel)
val newParcel = Parcel(parcel.toByteArray())
val decoder = ParcelDecoder(serializersModule = serializersModule, input = newParcel)
return decoder.decodeSerializableValue(deserializer)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.chrynan.parcelable.core

import kotlin.test.Test
import kotlin.test.assertEquals

class NumberUtilsTest {

@Test
fun longConversionShouldWork() {
val longValue = 500_000L

val byteArray = longValue.toByteArray()

assertEquals(expected = longValue, actual = byteArray.toLongValue())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ actual fun AnnotatedString.Builder.appendJsonText(
JsonGrammar.Token.PUNCTUATION -> builder.pushStyle(SpanStyle(color = colors.punctuationColor))
JsonGrammar.Token.STRING -> builder.pushStyle(SpanStyle(color = colors.stringColor))
JsonGrammar.Token.NUMBER -> builder.pushStyle(SpanStyle(color = colors.numberColor))
JsonGrammar.Token.PROPERTY -> builder.pushStyle(SpanStyle())
JsonGrammar.Token.PROPERTY -> builder.pushStyle(SpanStyle(color = colors.propertyColor))
JsonGrammar.Token.NULL -> builder.pushStyle(SpanStyle(color = colors.nullColor))
else -> {}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import com.chrynan.parcelable.compose.rememberSavable
import com.chrynan.parcelable.core.Parcel
import com.chrynan.parcelable.core.encodeToParcel
import com.chrynan.parcelable.sample.core.ExpectedModel
import com.chrynan.parcelable.sample.core.Model
import com.chrynan.parcelable.sample.core.SerializerUtils
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ actual fun AnnotatedString.Builder.appendJsonText(
JsonGrammar.Token.PUNCTUATION -> builder.pushStyle(SpanStyle(color = colors.punctuationColor))
JsonGrammar.Token.STRING -> builder.pushStyle(SpanStyle(color = colors.stringColor))
JsonGrammar.Token.NUMBER -> builder.pushStyle(SpanStyle(color = colors.numberColor))
JsonGrammar.Token.PROPERTY -> builder.pushStyle(SpanStyle())
JsonGrammar.Token.PROPERTY -> builder.pushStyle(SpanStyle(color = colors.propertyColor))
JsonGrammar.Token.NULL -> builder.pushStyle(SpanStyle(color = colors.nullColor))
else -> {}
}
Expand Down

0 comments on commit 245a081

Please sign in to comment.