-
Notifications
You must be signed in to change notification settings - Fork 110
kotlinx-serialization support #101
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
Changes from 15 commits
3b65a0e
357b151
73312a1
1881a0d
820516c
c27e81e
ebdf6bf
2eaac88
0452296
038ad25
1459c5c
d486f9a
0518207
6acf818
756af5c
2c35bb4
af231f7
d2cb1eb
c5c8ad2
9ff7e03
b3ce0fe
31d8fa3
8170830
b4b29da
f15d28c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,6 @@ public expect enum class Month { | |
OCTOBER, | ||
NOVEMBER, | ||
DECEMBER; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor: unrelated change |
||
// val value: Int // member missing in java.time.Month has to be an extension | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
/* | ||
* Copyright 2019-2021 JetBrains s.r.o. | ||
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file. | ||
*/ | ||
|
||
package kotlinx.datetime.serializers | ||
|
||
import kotlinx.datetime.DatePeriod | ||
import kotlinx.datetime.DateTimePeriod | ||
import kotlinx.serialization.KSerializer | ||
import kotlinx.serialization.SerializationException | ||
import kotlinx.serialization.descriptors.* | ||
import kotlinx.serialization.encoding.* | ||
|
||
object DateTimePeriodComponentSerializer: KSerializer<DateTimePeriod> { | ||
|
||
override val descriptor: SerialDescriptor = | ||
buildClassSerialDescriptor("DateTimePeriod") { | ||
element<Int>("years", isOptional = true) | ||
element<Int>("months", isOptional = true) | ||
element<Int>("days", isOptional = true) | ||
element<Int>("hours", isOptional = true) | ||
element<Int>("minutes", isOptional = true) | ||
element<Int>("seconds", isOptional = true) | ||
element<Long>("nanoseconds", isOptional = true) | ||
} | ||
|
||
override fun deserialize(decoder: Decoder): DateTimePeriod = | ||
decoder.decodeStructure(descriptor) { | ||
var years = 0 | ||
var months = 0 | ||
var days = 0 | ||
var hours = 0 | ||
var minutes = 0 | ||
var seconds = 0 | ||
var nanoseconds = 0L | ||
loop@while (true) { | ||
when (val index = decodeElementIndex(descriptor)) { | ||
0 -> years = decodeIntElement(descriptor, 0) | ||
1 -> months = decodeIntElement(descriptor, 1) | ||
2 -> days = decodeIntElement(descriptor, 2) | ||
3 -> hours = decodeIntElement(descriptor, 3) | ||
4 -> minutes = decodeIntElement(descriptor, 4) | ||
5 -> seconds = decodeIntElement(descriptor, 5) | ||
6 -> nanoseconds = decodeLongElement(descriptor, 6) | ||
CompositeDecoder.DECODE_DONE -> break@loop // https://youtrack.jetbrains.com/issue/KT-42262 | ||
else -> error("Unexpected index: $index") | ||
sandwwraith marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
DateTimePeriod(years, months, days, hours, minutes, seconds, nanoseconds) | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: DateTimePeriod) { | ||
encoder.encodeStructure(descriptor) { | ||
with(value) { | ||
if (years != 0) encodeIntElement(descriptor, 0, years) | ||
sandwwraith marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (months != 0) encodeIntElement(descriptor, 1, months) | ||
if (days != 0) encodeIntElement(descriptor, 2, days) | ||
if (hours != 0) encodeIntElement(descriptor, 3, hours) | ||
if (minutes != 0) encodeIntElement(descriptor, 4, minutes) | ||
if (seconds != 0) encodeIntElement(descriptor, 5, seconds) | ||
if (nanoseconds != 0) encodeLongElement(descriptor, 6, value.nanoseconds.toLong()) | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
object DateTimePeriodISO8601Serializer: KSerializer<DateTimePeriod> { | ||
|
||
override val descriptor: SerialDescriptor = | ||
PrimitiveSerialDescriptor("DateTimePeriod", PrimitiveKind.STRING) | ||
|
||
override fun deserialize(decoder: Decoder): DateTimePeriod = | ||
DateTimePeriod.parse(decoder.decodeString()) | ||
|
||
override fun serialize(encoder: Encoder, value: DateTimePeriod) { | ||
encoder.encodeString(value.toString()) | ||
} | ||
|
||
} | ||
|
||
object DatePeriodComponentSerializer: KSerializer<DatePeriod> { | ||
|
||
private fun unexpectedNonzero(fieldName: String, value: Long) { | ||
if (value != 0L) { | ||
throw SerializationException("expected field '$fieldName' to be zero, but was $value") | ||
sandwwraith marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
private fun unexpectedNonzero(fieldName: String, value: Int) = unexpectedNonzero(fieldName, value.toLong()) | ||
|
||
override val descriptor: SerialDescriptor = | ||
buildClassSerialDescriptor("DatePeriod") { | ||
element<Int>("years", isOptional = true) | ||
element<Int>("months", isOptional = true) | ||
element<Int>("days", isOptional = true) | ||
element<Int>("hours", isOptional = true) | ||
element<Int>("minutes", isOptional = true) | ||
element<Long>("seconds", isOptional = true) | ||
element<Long>("nanoseconds", isOptional = true) | ||
} | ||
|
||
override fun deserialize(decoder: Decoder): DatePeriod = | ||
decoder.decodeStructure(descriptor) { | ||
var years = 0 | ||
var months = 0 | ||
var days = 0 | ||
loop@while (true) { | ||
when (val index = decodeElementIndex(descriptor)) { | ||
0 -> years = decodeIntElement(descriptor, 0) | ||
1 -> months = decodeIntElement(descriptor, 1) | ||
2 -> days = decodeIntElement(descriptor, 2) | ||
3 -> unexpectedNonzero("hours", decodeIntElement(descriptor, 3)) | ||
4 -> unexpectedNonzero("minutes", decodeIntElement(descriptor, 4)) | ||
5 -> unexpectedNonzero("seconds", decodeLongElement(descriptor, 5)) | ||
6 -> unexpectedNonzero("nanoseconds", decodeLongElement(descriptor, 6)) | ||
CompositeDecoder.DECODE_DONE -> break@loop // https://youtrack.jetbrains.com/issue/KT-42262 | ||
else -> error("Unexpected index: $index") | ||
} | ||
} | ||
DatePeriod(years, months, days) | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: DatePeriod) { | ||
encoder.encodeStructure(descriptor) { | ||
with(value) { | ||
if (years != 0) encodeIntElement(DateTimePeriodComponentSerializer.descriptor, 0, years) | ||
if (months != 0) encodeIntElement(DateTimePeriodComponentSerializer.descriptor, 1, months) | ||
if (days != 0) encodeIntElement(DateTimePeriodComponentSerializer.descriptor, 2, days) | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
object DatePeriodISO8601Serializer: KSerializer<DatePeriod> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what you all use as a style guide, but I try really hard to evangelize the practice of treating acronyms and acronym-like things such as ISO, IPv6, iOS, etc. as words and casing them as such. Google's Java and Kotlin style guide recommend this practice:
That would make this type be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 for DatePeriodIso8601Serializer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree, it would be consistent with What do you think about dropping |
||
|
||
override val descriptor: SerialDescriptor = | ||
PrimitiveSerialDescriptor("DatePeriod", PrimitiveKind.STRING) | ||
|
||
// TODO: consider whether should fail when parsing "P1YT0H0M0.0S" | ||
override fun deserialize(decoder: Decoder): DatePeriod = | ||
when (val period = DateTimePeriod.parse(decoder.decodeString())) { | ||
is DatePeriod -> period | ||
else -> throw IllegalArgumentException("$period is not a date-based period") | ||
sandwwraith marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
override fun serialize(encoder: Encoder, value: DatePeriod) { | ||
encoder.encodeString(value.toString()) | ||
} | ||
|
||
} |
Uh oh!
There was an error while loading. Please reload this page.