-
Notifications
You must be signed in to change notification settings - Fork 624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add integration with kotlinx-io library #2707
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
public final class kotlinx/serialization/json/io/IoStreamsKt { | ||
public static final fun decodeFromSource (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/io/Source;)Ljava/lang/Object; | ||
public static final fun decodeSourceToSequence (Lkotlinx/serialization/json/Json;Lkotlinx/io/Source;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; | ||
public static synthetic fun decodeSourceToSequence$default (Lkotlinx/serialization/json/Json;Lkotlinx/io/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;Lkotlinx/io/Sink;)V | ||
} | ||
|
14 changes: 14 additions & 0 deletions
14
formats/json-io/api/kotlinx-serialization-json-io.klib.api
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Klib ABI Dump | ||
// Targets: [androidNativeArm32, androidNativeArm64, androidNativeX64, androidNativeX86, iosArm64, iosSimulatorArm64, iosX64, js, linuxArm32Hfp, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, wasmWasi, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64] | ||
// Rendering settings: | ||
// - Signature version: 2 | ||
// - Show manifest properties: true | ||
// - Show declarations: true | ||
|
||
// Library unique name: <org.jetbrains.kotlinx:kotlinx-serialization-json-io> | ||
final fun <#A: kotlin/Any?> (kotlinx.serialization.json/Json).kotlinx.serialization.json.io/decodeFromSource(kotlinx.serialization/DeserializationStrategy<#A>, kotlinx.io/Source): #A // kotlinx.serialization.json.io/decodeFromSource|[email protected](kotlinx.serialization.DeserializationStrategy<0:0>;kotlinx.io.Source){0§<kotlin.Any?>}[0] | ||
final fun <#A: kotlin/Any?> (kotlinx.serialization.json/Json).kotlinx.serialization.json.io/decodeSourceToSequence(kotlinx.io/Source, kotlinx.serialization/DeserializationStrategy<#A>, kotlinx.serialization.json/DecodeSequenceMode = ...): kotlin.sequences/Sequence<#A> // kotlinx.serialization.json.io/decodeSourceToSequence|[email protected](kotlinx.io.Source;kotlinx.serialization.DeserializationStrategy<0:0>;kotlinx.serialization.json.DecodeSequenceMode){0§<kotlin.Any?>}[0] | ||
final fun <#A: kotlin/Any?> (kotlinx.serialization.json/Json).kotlinx.serialization.json.io/encodeToSink(kotlinx.serialization/SerializationStrategy<#A>, #A, kotlinx.io/Sink) // kotlinx.serialization.json.io/encodeToSink|[email protected](kotlinx.serialization.SerializationStrategy<0:0>;0:0;kotlinx.io.Sink){0§<kotlin.Any?>}[0] | ||
final inline fun <#A: reified kotlin/Any?> (kotlinx.serialization.json/Json).kotlinx.serialization.json.io/decodeFromSource(kotlinx.io/Source): #A // kotlinx.serialization.json.io/decodeFromSource|[email protected](kotlinx.io.Source){0§<kotlin.Any?>}[0] | ||
final inline fun <#A: reified kotlin/Any?> (kotlinx.serialization.json/Json).kotlinx.serialization.json.io/decodeSourceToSequence(kotlinx.io/Source, kotlinx.serialization.json/DecodeSequenceMode = ...): kotlin.sequences/Sequence<#A> // kotlinx.serialization.json.io/decodeSourceToSequence|[email protected](kotlinx.io.Source;kotlinx.serialization.json.DecodeSequenceMode){0§<kotlin.Any?>}[0] | ||
final inline fun <#A: reified kotlin/Any?> (kotlinx.serialization.json/Json).kotlinx.serialization.json.io/encodeToSink(#A, kotlinx.io/Sink) // kotlinx.serialization.json.io/encodeToSink|[email protected](0:0;kotlinx.io.Sink){0§<kotlin.Any?>}[0] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
import Java9Modularity.configureJava9ModuleInfo | ||
import org.jetbrains.dokka.gradle.* | ||
import java.net.* | ||
|
||
plugins { | ||
kotlin("multiplatform") | ||
kotlin("plugin.serialization") | ||
|
||
id("native-targets-conventions") | ||
id("source-sets-conventions") | ||
} | ||
|
||
kotlin { | ||
sourceSets { | ||
configureEach { | ||
languageSettings { | ||
optIn("kotlinx.serialization.internal.CoreFriendModuleApi") | ||
optIn("kotlinx.serialization.json.internal.JsonFriendModuleApi") | ||
} | ||
} | ||
val commonMain by getting { | ||
dependencies { | ||
api(project(":kotlinx-serialization-core")) | ||
api(project(":kotlinx-serialization-json")) | ||
implementation(libs.kotlinx.io) | ||
} | ||
} | ||
} | ||
} | ||
|
||
project.configureJava9ModuleInfo() | ||
|
||
tasks.named<DokkaTaskPartial>("dokkaHtmlPartial") { | ||
dokkaSourceSets { | ||
configureEach { | ||
externalDocumentationLink { | ||
url.set(URL("https://kotlin.github.io/kotlinx-io/")) | ||
} | ||
} | ||
} | ||
} |
124 changes: 124 additions & 0 deletions
124
formats/json-io/commonMain/src/kotlinx/serialization/json/io/IoStreams.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* | ||
* Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package kotlinx.serialization.json.io | ||
|
||
import kotlinx.serialization.* | ||
import kotlinx.serialization.json.DecodeSequenceMode | ||
import kotlinx.serialization.json.Json | ||
import kotlinx.serialization.json.internal.* | ||
import kotlinx.serialization.json.io.internal.JsonToIoStreamWriter | ||
import kotlinx.serialization.json.internal.decodeToSequenceByReader | ||
import kotlinx.serialization.json.io.internal.IoSerialReader | ||
import kotlinx.io.* | ||
|
||
/** | ||
* Serializes the [value] with [serializer] into a [sink] using JSON format and UTF-8 encoding. | ||
* | ||
* @throws [SerializationException] if the given value cannot be serialized to JSON. | ||
* @throws [kotlinx.io.IOException] If an I/O error occurs and sink can't be written to. | ||
*/ | ||
@ExperimentalSerializationApi | ||
public fun <T> Json.encodeToSink( | ||
serializer: SerializationStrategy<T>, | ||
value: T, | ||
sink: Sink | ||
) { | ||
val writer = JsonToIoStreamWriter(sink) | ||
try { | ||
encodeByWriter(this, writer, serializer, value) | ||
} finally { | ||
writer.release() | ||
} | ||
} | ||
|
||
/** | ||
* Serializes given [value] to a [sink] using UTF-8 encoding and serializer retrieved from the reified type parameter. | ||
* | ||
* @throws [SerializationException] if the given value cannot be serialized to JSON. | ||
* @throws [kotlinx.io.IOException] If an I/O error occurs and sink can't be written to. | ||
*/ | ||
@ExperimentalSerializationApi | ||
public inline fun <reified T> Json.encodeToSink( | ||
value: T, | ||
sink: Sink | ||
): Unit = encodeToSink(serializersModule.serializer(), value, sink) | ||
|
||
|
||
/** | ||
* Deserializes JSON from [source] using UTF-8 encoding to a value of type [T] using [deserializer]. | ||
* | ||
* 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. | ||
* | ||
* @throws [SerializationException] if the given JSON input cannot be deserialized to the value of type [T]. | ||
* @throws [kotlinx.io.IOException] If an I/O error occurs and source can't be read from. | ||
*/ | ||
@ExperimentalSerializationApi | ||
public fun <T> Json.decodeFromSource( | ||
deserializer: DeserializationStrategy<T>, | ||
source: Source | ||
): T { | ||
return decodeByReader(this, deserializer, IoSerialReader(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. | ||
* | ||
* 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. | ||
* | ||
* @throws [SerializationException] if the given JSON input cannot be deserialized to the value of type [T]. | ||
* @throws [kotlinx.io.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) | ||
|
||
|
||
/** | ||
* 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. | ||
* | ||
* 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 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 [kotlinx.io.IOException] If an I/O error occurs and source can't be read from. | ||
*/ | ||
@ExperimentalSerializationApi | ||
public fun <T> Json.decodeSourceToSequence( | ||
source: Source, | ||
deserializer: DeserializationStrategy<T>, | ||
format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT | ||
): Sequence<T> { | ||
return decodeToSequenceByReader(this, IoSerialReader(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 [decodeSourceToSequence], [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 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 [kotlinx.io.IOException] If an I/O error occurs and source can't be read from. | ||
*/ | ||
@ExperimentalSerializationApi | ||
public inline fun <reified T> Json.decodeSourceToSequence( | ||
source: Source, | ||
format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT | ||
): Sequence<T> = decodeSourceToSequence(source, serializersModule.serializer(), format) |
40 changes: 40 additions & 0 deletions
40
formats/json-io/commonMain/src/kotlinx/serialization/json/io/internal/IoJsonStreams.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package kotlinx.serialization.json.io.internal | ||
|
||
import kotlinx.io.* | ||
import kotlinx.serialization.json.internal.* | ||
|
||
private const val QUOTE_CODE = '"'.code | ||
|
||
internal class JsonToIoStreamWriter(private val sink: Sink) : InternalJsonWriter { | ||
|
||
override fun writeLong(value: Long) { | ||
write(value.toString()) | ||
} | ||
|
||
override fun writeChar(char: Char) { | ||
sink.writeCodePointValue(char.code) | ||
} | ||
|
||
override fun write(text: String) { | ||
sink.writeString(text) | ||
} | ||
|
||
override fun writeQuoted(text: String) { | ||
sink.writeCodePointValue(QUOTE_CODE) | ||
InternalJsonWriter.doWriteEscaping(text) { s, start, end -> sink.writeString(s, start, end) } | ||
sink.writeCodePointValue(QUOTE_CODE) | ||
} | ||
|
||
override fun release() { | ||
// no-op, see https://github.com/Kotlin/kotlinx.serialization/pull/1982#discussion_r915043700 | ||
} | ||
} | ||
|
||
internal class IoSerialReader(private val source: Source): InternalJsonReaderCodePointImpl() { | ||
override fun exhausted(): Boolean = source.exhausted() | ||
override fun nextCodePoint(): Int = source.readCodePointValue() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason, this particular benchmark shows worse results compared to Okio version. It doesn't block integration in any way, I'll check the root cause later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a perf issue on the kotlinx-io size: an extension function to read code point values is defined only on
Source
and it performs a few actions to fill the inner buffer before decoding the code point. In Okio, that's a member function with a different (and optimized) implementation forBuffer
.kx-io should do the same: Kotlin/kotlinx-io#342.