summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Shanshin <sergey.shanshin@jetbrains.com>2022-07-12 19:00:02 +0300
committerGitHub <noreply@github.com>2022-07-12 19:00:02 +0300
commitdf3a161012b3d2fc2a18aefac86f27526659e127 (patch)
tree44de4938c31fe317438ab34a983c224aa563c240
parent4524b654da77ba1b120381e3b4c13482f2f9af1a (diff)
downloadkotlinx.serialization-df3a161012b3d2fc2a18aefac86f27526659e127.tar.gz
Improved okio support (#1982)
-rw-r--r--benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt6
-rw-r--r--formats/json-okio/api/kotlinx-serialization-json-okio.api8
-rw-r--r--formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt57
-rw-r--r--formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt4
-rw-r--r--formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt8
-rw-r--r--formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt42
6 files changed, 54 insertions, 71 deletions
diff --git a/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt b/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt
index 783888b4..c192fc03 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 4b3f0a2c..75effa13 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 b666d839..47d2072d 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 <T> Json.encodeToSink(
+public fun <T> Json.encodeToBufferedSink(
serializer: SerializationStrategy<T>,
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 <T> Json.encodeToSink(
* @throws [okio.IOException] If an I/O error occurs and sink can't be written to.
*/
@ExperimentalSerializationApi
-public inline fun <reified T> Json.encodeToSink(
+public inline fun <reified T> 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 <reified T> Json.encodeToSink(
* @throws [okio.IOException] If an I/O error occurs and source can't be read from.
*/
@ExperimentalSerializationApi
-public fun <T> Json.decodeFromSource(
+public fun <T> Json.decodeFromBufferedSource(
deserializer: DeserializationStrategy<T>,
- 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 <T> Json.decodeFromSource(
* @throws [okio.IOException] If an I/O error occurs and source can't be read from.
*/
@ExperimentalSerializationApi
-public inline fun <reified T> Json.decodeFromSource(source: Source): T =
- decodeFromSource(serializersModule.serializer(), source)
+public inline fun <reified T> 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 <T> Json.decodeSourceToSequence(
- source: Source,
+public fun <T> Json.decodeBufferedSourceToSequence(
+ source: BufferedSource,
deserializer: DeserializationStrategy<T>,
format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT
): Sequence<T> {
- 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 <reified T> Json.decodeSourceToSequence(
- source: Source,
+public inline fun <reified T> Json.decodeBufferedSourceToSequence(
+ source: BufferedSource,
format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT
-): Sequence<T> = decodeSourceToSequence(source, serializersModule.serializer(), format)
+): Sequence<T> = 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 3537392b..2d5485c1 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 33f23b81..59726d41 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 0cf2b5d7..c641f4fc 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 <T> Json.encodeByWriter(writer: JsonWriter, serializer: SerializationStrategy<T>, value: T) {
+@PublishedApi
+internal fun <T> Json.encodeByWriter(writer: JsonWriter, serializer: SerializationStrategy<T>, value: T) {
val encoder = StreamingJsonEncoder(
writer, this,
WriteMode.OBJ,
@@ -31,9 +28,8 @@ public fun <T> Json.encodeByWriter(writer: JsonWriter, serializer: Serialization
encoder.encodeSerializableValue(serializer, value)
}
-/** @suppress */
-@InternalSerializationApi
-public fun <T> Json.decodeByReader(
+@PublishedApi
+internal fun <T> Json.decodeByReader(
deserializer: DeserializationStrategy<T>,
reader: SerialReader
): T {
@@ -44,10 +40,9 @@ public fun <T> Json.decodeByReader(
return result
}
-/** @suppress */
-@InternalSerializationApi
+@PublishedApi
@ExperimentalSerializationApi
-public fun <T> Json.decodeToSequenceByReader(
+internal fun <T> Json.decodeToSequenceByReader(
reader: SerialReader,
deserializer: DeserializationStrategy<T>,
format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT
@@ -57,10 +52,9 @@ public fun <T> Json.decodeToSequenceByReader(
return Sequence { iter }.constrainOnce()
}
-/** @suppress */
-@InternalSerializationApi
+@PublishedApi
@ExperimentalSerializationApi
-public inline fun <reified T> Json.decodeToSequenceByReader(
+internal inline fun <reified T> Json.decodeToSequenceByReader(
reader: SerialReader,
format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT
): Sequence<T> = decodeToSequenceByReader(reader, serializersModule.serializer(), format)