diff --git a/core/api/kotlinx-serialization-core.api b/core/api/kotlinx-serialization-core.api index 4d07ae122..0cec51e3f 100644 --- a/core/api/kotlinx-serialization-core.api +++ b/core/api/kotlinx-serialization-core.api @@ -513,6 +513,8 @@ public final class kotlinx/serialization/encoding/Encoder$DefaultImpls { } public final class kotlinx/serialization/encoding/EncodingKt { + public static final fun encodeCollection (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlin/jvm/functions/Function1;)V + public static final fun encodeCollection (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/serialization/descriptors/SerialDescriptor;Ljava/util/Collection;Lkotlin/jvm/functions/Function3;)V public static final fun encodeStructure (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlin/jvm/functions/Function1;)V } diff --git a/core/commonMain/src/kotlinx/serialization/encoding/Encoding.kt b/core/commonMain/src/kotlinx/serialization/encoding/Encoding.kt index c06011e09..e7055c591 100644 --- a/core/commonMain/src/kotlinx/serialization/encoding/Encoding.kt +++ b/core/commonMain/src/kotlinx/serialization/encoding/Encoding.kt @@ -486,3 +486,32 @@ public inline fun Encoder.encodeStructure(descriptor: SerialDescriptor, block: C if (ex == null) composite.endStructure(descriptor) } } + +/** + * Begins a collection, encodes it using the given [block] and ends it. + */ +public inline fun Encoder.encodeCollection( + descriptor: SerialDescriptor, + collectionSize: Int, + crossinline block: CompositeEncoder.() -> Unit +) { + with(beginCollection(descriptor, collectionSize)) { + block() + endStructure(descriptor) + } +} + +/** + * Begins a collection, calls [block] with each item and ends the collections. + */ +public inline fun Encoder.encodeCollection( + descriptor: SerialDescriptor, + collection: Collection, + crossinline block: CompositeEncoder.(index: Int, E) -> Unit +) { + encodeCollection(descriptor, collection.size) { + collection.forEachIndexed { index, e -> + block(index, e) + } + } +} diff --git a/core/commonMain/src/kotlinx/serialization/internal/CollectionSerializers.kt b/core/commonMain/src/kotlinx/serialization/internal/CollectionSerializers.kt index b507a4987..fbd16c58a 100644 --- a/core/commonMain/src/kotlinx/serialization/internal/CollectionSerializers.kt +++ b/core/commonMain/src/kotlinx/serialization/internal/CollectionSerializers.kt @@ -63,11 +63,11 @@ internal sealed class ListLikeSerializer( override fun serialize(encoder: Encoder, value: Collection) { val size = value.collectionSize() - val composite = encoder.beginCollection(descriptor, size) - val iterator = value.collectionIterator() - for (index in 0 until size) - composite.encodeSerializableElement(descriptor, index, elementSerializer, iterator.next()) - composite.endStructure(descriptor) + encoder.encodeCollection(descriptor, size) { + val iterator = value.collectionIterator() + for (index in 0 until size) + encodeSerializableElement(descriptor, index, elementSerializer, iterator.next()) + } } protected final override fun readAll(decoder: CompositeDecoder, builder: Builder, startIndex: Int, size: Int) { @@ -115,14 +115,14 @@ public sealed class MapLikeSerializer - composite.encodeSerializableElement(descriptor, index++, keySerializer, k) - composite.encodeSerializableElement(descriptor, index++, valueSerializer, v) + encoder.encodeCollection(descriptor, size) { + val iterator = value.collectionIterator() + var index = 0 + iterator.forEach { (k, v) -> + encodeSerializableElement(descriptor, index++, keySerializer, k) + encodeSerializableElement(descriptor, index++, valueSerializer, v) + } } - composite.endStructure(descriptor) } } @@ -171,9 +171,9 @@ internal abstract class PrimitiveArraySerializer> { + override val descriptor: SerialDescriptor = ListSerializer(String.serializer()).descriptor + + override fun serialize(encoder: Encoder, value: List) { + encoder.encodeCollection(descriptor, value) { index, item -> + encodeStringElement(descriptor, index, item) + } + } + + override fun deserialize(decoder: Decoder): List = throw NotImplementedError() + } + + @Test + fun testEncoding() { + assertEquals("""["Hello","World!"]""", Json.encodeToString(ListSerializer, listOf("Hello", "World!"))) + } +}