Skip to content

Commit f27a2e6

Browse files
committed
Support reordering of element writing (in pessimisation case)
1 parent 1b6b2dd commit f27a2e6

File tree

1 file changed

+75
-13
lines changed

1 file changed

+75
-13
lines changed

formats/json-tests/commonTest/src/kotlinx/serialization/efficientBinaryFormat/EfficientBinaryFormat.kt

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,87 @@ class EfficientBinaryFormat(
3838
return deserializer.deserialize(decoder)
3939
}
4040

41-
class Encoder(override val serializersModule: SerializersModule): AbstractEncoder() {
42-
val byteBuffer = ByteWritingBuffer()
43-
override fun encodeBoolean(value: Boolean) = byteBuffer.writeByte(if (value) 1 else 0)
44-
override fun encodeByte(value: Byte) = byteBuffer.writeByte(value)
45-
override fun encodeShort(value: Short) = byteBuffer.writeShort(value)
46-
override fun encodeInt(value: Int) = byteBuffer.writeInt(value)
47-
override fun encodeLong(value: Long) = byteBuffer.writeLong(value)
48-
override fun encodeFloat(value: Float) = byteBuffer.writeFloat(value)
49-
override fun encodeDouble(value: Double) = byteBuffer.writeDouble(value)
50-
override fun encodeChar(value: Char) = byteBuffer.writeChar(value)
51-
override fun encodeString(value: String) = byteBuffer.writeString(value)
52-
override fun encodeEnum(enumDescriptor: SerialDescriptor, index: Int) = byteBuffer.writeInt(index)
41+
class Encoder(
42+
override val serializersModule: SerializersModule,
43+
internal val byteBuffer: ByteWritingBuffer = ByteWritingBuffer(),
44+
elementsCount: Int = -1
45+
): AbstractEncoder() {
46+
var lastWrittenIndex = -1
47+
var currentIndex = -1
48+
val notInStruct = elementsCount < 0
49+
50+
val pending : Array<(() -> Unit)?> = when {
51+
elementsCount <=0 -> emptyArray()
52+
else -> arrayOfNulls(elementsCount)
53+
}
54+
55+
override fun encodeBoolean(value: Boolean) = writeOrSuspend { byteBuffer.writeByte(if (value) 1 else 0) }
56+
override fun encodeByte(value: Byte) = writeOrSuspend { byteBuffer.writeByte(value) }
57+
override fun encodeShort(value: Short) = writeOrSuspend { byteBuffer.writeShort(value) }
58+
override fun encodeInt(value: Int) = writeOrSuspend { byteBuffer.writeInt(value) }
59+
override fun encodeLong(value: Long) = writeOrSuspend { byteBuffer.writeLong(value) }
60+
override fun encodeFloat(value: Float) = writeOrSuspend { byteBuffer.writeFloat(value) }
61+
override fun encodeDouble(value: Double) = writeOrSuspend { byteBuffer.writeDouble(value) }
62+
override fun encodeChar(value: Char) = writeOrSuspend { byteBuffer.writeChar(value) }
63+
override fun encodeString(value: String) = writeOrSuspend { byteBuffer.writeString(value) }
64+
override fun encodeEnum(enumDescriptor: SerialDescriptor, index: Int) = writeOrSuspend {
65+
byteBuffer.writeInt(index)
66+
}
67+
68+
@ExperimentalSerializationApi
69+
override fun <T : Any> encodeNullableSerializableValue(
70+
serializer: SerializationStrategy<T>,
71+
value: T?
72+
) {
73+
writeOrSuspend {
74+
super.encodeNullableSerializableValue(serializer, value)
75+
}
76+
}
77+
78+
override fun <T> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T) {
79+
writeOrSuspend {
80+
super.encodeSerializableValue(serializer, value)
81+
}
82+
}
83+
84+
@Suppress("NOTHING_TO_INLINE")
85+
private inline fun writeOrSuspend(noinline action: () -> Unit) {
86+
val c = currentIndex
87+
currentIndex = -1
88+
when {
89+
notInStruct || c<0 -> action()
90+
lastWrittenIndex < -1 -> pending[c] = action
91+
lastWrittenIndex + 1 == c -> {
92+
++lastWrittenIndex
93+
action()
94+
}
95+
c < pending.size -> pending[c] = action
96+
else -> error("Unexpected index")
97+
}
98+
}
99+
100+
override fun encodeElement(descriptor: SerialDescriptor, index: Int): Boolean {
101+
currentIndex = index
102+
return true
103+
}
53104

54105
@ExperimentalSerializationApi
55106
override fun shouldEncodeElementDefault(descriptor: SerialDescriptor, index: Int): Boolean = true
56107

108+
override fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder {
109+
return Encoder(serializersModule, byteBuffer, descriptor.elementsCount)
110+
}
111+
57112
override fun beginCollection(descriptor: SerialDescriptor, collectionSize: Int): CompositeEncoder {
58113
encodeInt(collectionSize)
59-
return this
114+
return Encoder(serializersModule, byteBuffer, -1)
115+
}
116+
117+
override fun endStructure(descriptor: SerialDescriptor) {
118+
currentIndex = -2 // mark negative to ensure writing
119+
for (i in 0 until pending.size) {
120+
pending[i]?.invoke()
121+
}
60122
}
61123

62124
override fun encodeNull() = encodeBoolean(false)

0 commit comments

Comments
 (0)