diff --git a/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt index 2d5485c16..ae8de4719 100644 --- a/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt @@ -50,7 +50,7 @@ internal class OkioSerialReader(private val source: BufferedSource): SerialReade override fun read(buffer: CharArray, bufferOffset: Int, count: Int): Int { var i = 0 while (i < count && !source.exhausted()) { - buffer[i] = source.readUtf8CodePoint().toChar() + buffer[bufferOffset + i] = source.readUtf8CodePoint().toChar() i++ } return if (i > 0) i else -1 diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonHugeDataSerializationTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonHugeDataSerializationTest.kt new file mode 100644 index 000000000..cfe8ab32f --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonHugeDataSerializationTest.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json + +import kotlinx.serialization.Serializable +import kotlinx.serialization.encodeToString +import kotlin.test.Test + + +class JsonHugeDataSerializationTest : JsonTestBase() { + + @Serializable + private data class Node( + val children: List? + ) + + private fun createNodes(count: Int, depth: Int): List { + val ret = mutableListOf() + if (depth == 0) return ret + for (i in 0 until count) { + ret.add(Node(createNodes(1, depth - 1))) + } + return ret + } + + @Test + fun test() { + // create some huge instance + val rootNode = Node(createNodes(1000, 10)) + + // Encoding will always be true for a standard `encodeToString` - we leave this assumption so as not to insert a huge string into the sources + val expectedJson = Json.encodeToString(rootNode) + + assertJsonFormAndRestored(Node.serializer(), rootNode, expectedJson) + } +} diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt index 977347a55..4e8d23823 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt @@ -184,7 +184,6 @@ internal abstract class AbstractJsonLexer { open fun consumeNextToken(expected: Char) { ensureHaveChars() - val source = source var cpos = currentPosition while (true) { cpos = prefetchOrEof(cpos) diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt index e02364ee4..88a6c8432 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt @@ -67,7 +67,9 @@ internal class ReaderJsonLexer( private fun preload(spaceLeft: Int) { val buffer = _source - buffer.copyInto(buffer, 0, currentPosition, currentPosition + spaceLeft) + if (spaceLeft != 0) { + buffer.copyInto(buffer, 0, currentPosition, currentPosition + spaceLeft) + } var read = spaceLeft val sizeTotal = _source.size while (read != sizeTotal) {