diff --git a/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt b/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt index 783888b4e..c192fc03a 100644 --- a/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt +++ b/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.* import com.fasterxml.jackson.module.kotlin.* import kotlinx.serialization.* import kotlinx.serialization.json.* -import kotlinx.serialization.json.okio.encodeToSink +import kotlinx.serialization.json.okio.encodeToBufferedSink import okio.blackholeSink import okio.buffer import org.openjdk.jmh.annotations.* @@ -97,7 +97,7 @@ open class JacksonComparisonBenchmark { fun kotlinToStream() = Json.encodeToStream(DefaultPixelEvent.serializer(), data, devNullStream) @Benchmark - fun kotlinToOkio() = Json.encodeToSink(DefaultPixelEvent.serializer(), data, devNullSink) + fun kotlinToOkio() = Json.encodeToBufferedSink(DefaultPixelEvent.serializer(), data, devNullSink) @Benchmark fun kotlinToStringWithEscapes(): String = Json.encodeToString(DefaultPixelEvent.serializer(), dataWithEscapes) @@ -109,7 +109,7 @@ open class JacksonComparisonBenchmark { fun kotlinSmallToStream() = Json.encodeToStream(SmallDataClass.serializer(), smallData, devNullStream) @Benchmark - fun kotlinSmallToOkio() = Json.encodeToSink(SmallDataClass.serializer(), smallData, devNullSink) + fun kotlinSmallToOkio() = Json.encodeToBufferedSink(SmallDataClass.serializer(), smallData, devNullSink) @Benchmark fun jacksonFromString(): DefaultPixelEvent = objectMapper.readValue(stringData, DefaultPixelEvent::class.java) diff --git a/formats/json-okio/api/kotlinx-serialization-json-okio.api b/formats/json-okio/api/kotlinx-serialization-json-okio.api index 4b3f0a2c3..75effa13f 100644 --- a/formats/json-okio/api/kotlinx-serialization-json-okio.api +++ b/formats/json-okio/api/kotlinx-serialization-json-okio.api @@ -1,7 +1,7 @@ public final class kotlinx/serialization/json/okio/OkioStreamsKt { - public static final fun decodeFromSource (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Lokio/Source;)Ljava/lang/Object; - public static final fun decodeSourceToSequence (Lkotlinx/serialization/json/Json;Lokio/Source;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; - public static synthetic fun decodeSourceToSequence$default (Lkotlinx/serialization/json/Json;Lokio/Source;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;ILjava/lang/Object;)Lkotlin/sequences/Sequence; - public static final fun encodeToSink (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lokio/Sink;)V + public static final fun decodeBufferedSourceToSequence (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; + public static synthetic fun decodeBufferedSourceToSequence$default (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;ILjava/lang/Object;)Lkotlin/sequences/Sequence; + public static final fun decodeFromBufferedSource (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Lokio/BufferedSource;)Ljava/lang/Object; + public static final fun encodeToBufferedSink (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lokio/BufferedSink;)V } diff --git a/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt index b666d839a..47d2072d2 100644 --- a/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt @@ -2,6 +2,8 @@ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") + package kotlinx.serialization.json.okio import kotlinx.serialization.* @@ -16,19 +18,16 @@ import okio.* /** * Serializes the [value] with [serializer] into a [target] using JSON format and UTF-8 encoding. * - * If [target] is not a [BufferedSink] then called [Sink.buffer] for it to create buffered wrapper. - * * @throws [SerializationException] if the given value cannot be serialized to JSON. * @throws [okio.IOException] If an I/O error occurs and sink can't be written to. */ @ExperimentalSerializationApi -public fun Json.encodeToSink( +public fun Json.encodeToBufferedSink( serializer: SerializationStrategy, value: T, - target: Sink + target: BufferedSink ) { - val buffered = if (target is BufferedSink) target else target.buffer() - val writer = JsonToOkioStreamWriter(buffered) + val writer = JsonToOkioStreamWriter(target) try { encodeByWriter(writer, serializer, value) } finally { @@ -45,17 +44,15 @@ public fun Json.encodeToSink( * @throws [okio.IOException] If an I/O error occurs and sink can't be written to. */ @ExperimentalSerializationApi -public inline fun Json.encodeToSink( +public inline fun Json.encodeToBufferedSink( value: T, - target: Sink -): Unit = encodeToSink(serializersModule.serializer(), value, target) + target: BufferedSink +): Unit = encodeToBufferedSink(serializersModule.serializer(), value, target) /** * Deserializes JSON from [source] using UTF-8 encoding to a value of type [T] using [deserializer]. * - * If [source] is not a [BufferedSource] then called [Source.buffer] for it to create buffered wrapper. - * * Note that this functions expects that exactly one object would be present in the source * and throws an exception if there are any dangling bytes after an object. * @@ -63,20 +60,17 @@ public inline fun Json.encodeToSink( * @throws [okio.IOException] If an I/O error occurs and source can't be read from. */ @ExperimentalSerializationApi -public fun Json.decodeFromSource( +public fun Json.decodeFromBufferedSource( deserializer: DeserializationStrategy, - source: Source + source: BufferedSource ): T { - val buffered = if (source is BufferedSource) source else source.buffer() - return decodeByReader(deserializer, OkioSerialReader(buffered)) + return decodeByReader(deserializer, OkioSerialReader(source)) } /** * Deserializes the contents of given [source] to the value of type [T] using UTF-8 encoding and * deserializer retrieved from the reified type parameter. * - * If [source] is not a [BufferedSource] then called [Source.buffer] for it to create buffered wrapper. - * * Note that this functions expects that exactly one object would be present in the stream * and throws an exception if there are any dangling bytes after an object. * @@ -84,56 +78,51 @@ public fun Json.decodeFromSource( * @throws [okio.IOException] If an I/O error occurs and source can't be read from. */ @ExperimentalSerializationApi -public inline fun Json.decodeFromSource(source: Source): T = - decodeFromSource(serializersModule.serializer(), source) +public inline fun Json.decodeFromBufferedSource(source: BufferedSource): T = + decodeFromBufferedSource(serializersModule.serializer(), source) /** * Transforms the given [source] into lazily deserialized sequence of elements of type [T] using UTF-8 encoding and [deserializer]. - * Unlike [decodeFromSource], [source] is allowed to have more than one element, separated as [format] declares. - * - * If [source] is not a [BufferedSource] then called [Source.buffer] for it to create buffered wrapper. + * Unlike [decodeFromBufferedSource], [source] is allowed to have more than one element, separated as [format] declares. * * Elements must all be of type [T]. * Elements are parsed lazily when resulting [Sequence] is evaluated. * Resulting sequence is tied to the stream and can be evaluated only once. * * **Resource caution:** this method neither closes the [source] when the parsing is finished nor provides a method to close it manually. - * It is a caller responsibility to hold a reference to a stream and close it. Moreover, because stream is parsed lazily, + * It is a caller responsibility to hold a reference to a source and close it. Moreover, because source is parsed lazily, * closing it before returned sequence is evaluated completely will result in [Exception] from decoder. * * @throws [SerializationException] if the given JSON input cannot be deserialized to the value of type [T]. * @throws [okio.IOException] If an I/O error occurs and source can't be read from. */ @ExperimentalSerializationApi -public fun Json.decodeSourceToSequence( - source: Source, +public fun Json.decodeBufferedSourceToSequence( + source: BufferedSource, deserializer: DeserializationStrategy, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT ): Sequence { - val buffered = if (source is BufferedSource) source else source.buffer() - return decodeToSequenceByReader(OkioSerialReader(buffered), deserializer, format) + return decodeToSequenceByReader(OkioSerialReader(source), deserializer, format) } /** * Transforms the given [source] into lazily deserialized sequence of elements of type [T] using UTF-8 encoding and deserializer retrieved from the reified type parameter. - * Unlike [decodeFromSource], [source] is allowed to have more than one element, separated as [format] declares. - * - * If [source] is not a [BufferedSource] then called [Source.buffer] for it to create buffered wrapper. + * Unlike [decodeFromBufferedSource], [source] is allowed to have more than one element, separated as [format] declares. * * Elements must all be of type [T]. * Elements are parsed lazily when resulting [Sequence] is evaluated. * Resulting sequence is tied to the stream and constrained to be evaluated only once. * * **Resource caution:** this method does not close [source] when the parsing is finished neither provides method to close it manually. - * It is a caller responsibility to hold a reference to a stream and close it. Moreover, because stream is parsed lazily, + * It is a caller responsibility to hold a reference to a source and close it. Moreover, because source is parsed lazily, * closing it before returned sequence is evaluated fully would result in [Exception] from decoder. * * @throws [SerializationException] if the given JSON input cannot be deserialized to the value of type [T]. * @throws [okio.IOException] If an I/O error occurs and source can't be read from. */ @ExperimentalSerializationApi -public inline fun Json.decodeSourceToSequence( - source: Source, +public inline fun Json.decodeBufferedSourceToSequence( + source: BufferedSource, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT -): Sequence = decodeSourceToSequence(source, serializersModule.serializer(), format) +): Sequence = decodeBufferedSourceToSequence(source, serializersModule.serializer(), format) 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 3537392b2..2d5485c16 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 @@ -2,7 +2,7 @@ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "CANNOT_OVERRIDE_INVISIBLE_MEMBER") package kotlinx.serialization.json.okio.internal @@ -42,7 +42,7 @@ internal class JsonToOkioStreamWriter(private val target: BufferedSink) : JsonWr } override fun release() { - target.flush() + // no-op, see https://github.com/Kotlin/kotlinx.serialization/pull/1982#discussion_r915043700 } } diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt index 33f23b819..59726d41f 100644 --- a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt @@ -6,8 +6,8 @@ package kotlinx.serialization.json import kotlinx.serialization.* import kotlinx.serialization.json.internal.* -import kotlinx.serialization.json.okio.decodeFromSource -import kotlinx.serialization.json.okio.encodeToSink +import kotlinx.serialization.json.okio.decodeFromBufferedSource +import kotlinx.serialization.json.okio.encodeToBufferedSink import kotlinx.serialization.modules.EmptySerializersModule import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.test.* @@ -53,7 +53,7 @@ abstract class JsonTestBase { } JsonTestingMode.OKIO_STREAMS -> { val buffer = Buffer() - encodeToSink(serializer, value, buffer) + encodeToBufferedSink(serializer, value, buffer) buffer.readUtf8() } } @@ -82,7 +82,7 @@ abstract class JsonTestBase { JsonTestingMode.OKIO_STREAMS -> { val buffer = Buffer() buffer.writeUtf8(source) - decodeFromSource(deserializer, buffer) + decodeFromBufferedSource(deserializer, buffer) } } diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt index 0cf2b5d7f..c641f4fcc 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt @@ -4,25 +4,22 @@ import kotlinx.serialization.* import kotlinx.serialization.json.DecodeSequenceMode import kotlinx.serialization.json.Json -/** @suppress */ -@InternalSerializationApi -public interface JsonWriter { - public fun writeLong(value: Long) - public fun writeChar(char: Char) - public fun write(text: String) - public fun writeQuoted(text: String) - public fun release() +@PublishedApi +internal interface JsonWriter { + fun writeLong(value: Long) + fun writeChar(char: Char) + fun write(text: String) + fun writeQuoted(text: String) + fun release() } -/** @suppress */ -@InternalSerializationApi -public interface SerialReader { - public fun read(buffer: CharArray, bufferOffset: Int, count: Int): Int +@PublishedApi +internal interface SerialReader { + fun read(buffer: CharArray, bufferOffset: Int, count: Int): Int } -/** @suppress */ -@InternalSerializationApi -public fun Json.encodeByWriter(writer: JsonWriter, serializer: SerializationStrategy, value: T) { +@PublishedApi +internal fun Json.encodeByWriter(writer: JsonWriter, serializer: SerializationStrategy, value: T) { val encoder = StreamingJsonEncoder( writer, this, WriteMode.OBJ, @@ -31,9 +28,8 @@ public fun Json.encodeByWriter(writer: JsonWriter, serializer: Serialization encoder.encodeSerializableValue(serializer, value) } -/** @suppress */ -@InternalSerializationApi -public fun Json.decodeByReader( +@PublishedApi +internal fun Json.decodeByReader( deserializer: DeserializationStrategy, reader: SerialReader ): T { @@ -44,10 +40,9 @@ public fun Json.decodeByReader( return result } -/** @suppress */ -@InternalSerializationApi +@PublishedApi @ExperimentalSerializationApi -public fun Json.decodeToSequenceByReader( +internal fun Json.decodeToSequenceByReader( reader: SerialReader, deserializer: DeserializationStrategy, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT @@ -57,10 +52,9 @@ public fun Json.decodeToSequenceByReader( return Sequence { iter }.constrainOnce() } -/** @suppress */ -@InternalSerializationApi +@PublishedApi @ExperimentalSerializationApi -public inline fun Json.decodeToSequenceByReader( +internal inline fun Json.decodeToSequenceByReader( reader: SerialReader, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT ): Sequence = decodeToSequenceByReader(reader, serializersModule.serializer(), format)