From ca2c6011c244728d2c84848c23cbe3f71467fa2f Mon Sep 17 00:00:00 2001 From: Andrey Kuleshov Date: Tue, 3 Jan 2023 20:40:12 +0800 Subject: [PATCH 1/4] Adding the support for Char ### What's done: - conversion from string to char - enabling some old tests - still we need unicode conversion --- .../com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt | 5 ++++- .../com/akuleshov7/ktoml/decoders/TomlMainDecoder.kt | 2 +- .../akuleshov7/ktoml/decoders/ArrayOfTablesDecoderTest.kt | 5 ----- .../com/akuleshov7/ktoml/decoders/CustomSerializerTest.kt | 1 + .../akuleshov7/ktoml/decoders/SurrogateSerializerTest.kt | 7 ++++--- .../com/akuleshov7/ktoml/encoders/TomlDocsEncoderTest.kt | 3 +-- .../kotlin/com/akuleshov7/ktoml/parsers/TomlTableTest.kt | 4 ++-- 7 files changed, 13 insertions(+), 14 deletions(-) diff --git a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt index 97e63594..bde97c20 100644 --- a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt +++ b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt @@ -32,7 +32,10 @@ public abstract class TomlAbstractDecoder : AbstractDecoder() { override fun decodeShort(): Short = decodePrimitiveType() override fun decodeInt(): Int = decodePrimitiveType() override fun decodeFloat(): Float = decodePrimitiveType() - override fun decodeChar(): Char = invalidType("Char", "String") + override fun decodeChar(): Char { + val value = decodeKeyValue().value.content as String + return value.single() + } // Valid Toml types that should be properly decoded override fun decodeBoolean(): Boolean = decodePrimitiveType() diff --git a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlMainDecoder.kt b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlMainDecoder.kt index 5f59c844..137d450f 100644 --- a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlMainDecoder.kt +++ b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlMainDecoder.kt @@ -81,7 +81,7 @@ public class TomlMainDecoder( private fun getCurrentNode() = rootNode.getNeighbourNodes().elementAt(elementIndex - 1) /** - * Trying to decode the value (ite + * Trying to decode the value using elementIndex * |--- child1, child2, ... , childN * ------------elementIndex-------> * diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ArrayOfTablesDecoderTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ArrayOfTablesDecoderTest.kt index 82d0ddd3..f7594599 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ArrayOfTablesDecoderTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ArrayOfTablesDecoderTest.kt @@ -1,13 +1,8 @@ package com.akuleshov7.ktoml.decoders -import com.akuleshov7.ktoml.Toml -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlin.test.Ignore import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith @Serializable data class TomlArrayOfTables(val a: List) diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CustomSerializerTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CustomSerializerTest.kt index 9c200ed9..8b73de1d 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CustomSerializerTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CustomSerializerTest.kt @@ -66,6 +66,7 @@ class CustomSerializerTest { """.trimIndent() ) ) + UInt.MAX_VALUE } @Serializable diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/SurrogateSerializerTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/SurrogateSerializerTest.kt index 61dd567e..d2b3dce2 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/SurrogateSerializerTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/SurrogateSerializerTest.kt @@ -7,6 +7,7 @@ import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import kotlin.test.Ignore import kotlin.test.Test +import kotlin.test.assertEquals class SurrogateTest { object ColorSerializer : KSerializer { @@ -35,14 +36,14 @@ class SurrogateTest { class Color(val rgb: Int) @Test - @Ignore fun testDecodingWithCustomSerializer() { - println(Toml.decodeFromString( + val test = Toml.decodeFromString( """ r = 5 g = 6 b = 7 """.trimIndent() - )) + ) + assertEquals(Color(329223).rgb, test.rgb) } } diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/encoders/TomlDocsEncoderTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/encoders/TomlDocsEncoderTest.kt index 3801ab0b..12cc6138 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/encoders/TomlDocsEncoderTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/encoders/TomlDocsEncoderTest.kt @@ -117,7 +117,6 @@ class TomlDocsEncoderTest { } @Test - @Ignore fun basicStringTest() { @Serializable data class File( @@ -131,7 +130,7 @@ class TomlDocsEncoderTest { expectedToml = """ str1 = "I'm a string." str2 = "You can \"quote\" me." - str3 = "Name\tJos\u00E9\nLoc\tSF." + str3 = "Name José\nLoc SF." """.trimIndent() ) } diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/parsers/TomlTableTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/parsers/TomlTableTest.kt index 646234c9..b410fba2 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/parsers/TomlTableTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/parsers/TomlTableTest.kt @@ -27,7 +27,6 @@ class TomlTableTest { } @Test - @Ignore fun nestedTomlTable() { val string = """ [a] @@ -43,7 +42,8 @@ class TomlTableTest { assertEquals(""" | - TomlFile (rootNode) | - TomlTablePrimitive ([a]) - | - TomlTablePrimitive ( [a.b]) + | - TomlStubEmptyNode (technical_node) + | - TomlTablePrimitive ([a.b]) | - TomlStubEmptyNode (technical_node) | - TomlKeyValuePrimitive (c=3) | From 313a985740a7e3b47563e606b42a6a004b6c706f Mon Sep 17 00:00:00 2001 From: Andrey Kuleshov Date: Thu, 5 Jan 2023 14:29:02 +0800 Subject: [PATCH 2/4] Adding the support for Char ### What's done: - conversion from a literal string to char - enabling some old tests - still we need unicode conversion and fixes for literal strings --- .../ktoml/decoders/TomlAbstractDecoder.kt | 41 ++++++++++--- .../akuleshov7/ktoml/parsers/StringUtils.kt | 2 +- .../com/akuleshov7/ktoml/utils/Types.kt | 1 + .../ktoml/decoders/ArrayDecoderTest.kt | 40 ++++++------- .../ktoml/decoders/CharDecoderTest.kt | 46 ++++++++++++++ .../ktoml/decoders/DottedKeysDecoderTest.kt | 60 +++++++++---------- .../ktoml/decoders/GeneralDecoderTest.kt | 38 ++++++------ .../ktoml/decoders/IntegersDecoderTest.kt | 10 ++-- .../ktoml/decoders/ReadMeExampleTest.kt | 31 ++++++---- 9 files changed, 176 insertions(+), 93 deletions(-) create mode 100644 ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CharDecoderTest.kt diff --git a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt index bde97c20..c80dedc7 100644 --- a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt +++ b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt @@ -2,7 +2,9 @@ package com.akuleshov7.ktoml.decoders import com.akuleshov7.ktoml.exceptions.IllegalTypeException import com.akuleshov7.ktoml.tree.nodes.TomlKeyValue +import com.akuleshov7.ktoml.tree.nodes.pairs.values.TomlBasicString import com.akuleshov7.ktoml.tree.nodes.pairs.values.TomlDouble +import com.akuleshov7.ktoml.tree.nodes.pairs.values.TomlLiteralString import com.akuleshov7.ktoml.tree.nodes.pairs.values.TomlLong import com.akuleshov7.ktoml.utils.FloatingPointLimitsEnum import com.akuleshov7.ktoml.utils.FloatingPointLimitsEnum.* @@ -33,8 +35,33 @@ public abstract class TomlAbstractDecoder : AbstractDecoder() { override fun decodeInt(): Int = decodePrimitiveType() override fun decodeFloat(): Float = decodePrimitiveType() override fun decodeChar(): Char { - val value = decodeKeyValue().value.content as String - return value.single() + val keyValue = decodeKeyValue() + return when (val value = keyValue.value) { + // converting to Char from a parsed Long number and checking bounds for the Char (MIN-MAX range) + is TomlLong -> validateAndConvertInteger(value.content as Long, keyValue.lineNo, CHAR) { Char(it.toInt()) } + // converting to Char from a parsed Literal String (with single quotes: '') + is TomlLiteralString -> + try { + (value.content as String).single() + } catch (ex: NoSuchElementException) { + throw IllegalTypeException("Empty value is not allowed for type [Char], " + + "please check the value: [${value.content}] or use [String] type for deserialization of " + + "[${keyValue.key}] instead", keyValue.lineNo) + } catch (ex: IllegalArgumentException) { + throw IllegalTypeException("[Char] type should be used for decoding of single character, but " + + "received multiple characters instead: [${value.content}]. " + + "If you really want to decode multiple chars, use [String] instead.", keyValue.lineNo) + } + // to avoid confusion, we prohibit basic strings with double quotes for decoding to a Char type + is TomlBasicString -> throw IllegalTypeException("Double quotes were used in the input for deserialization " + + "of [Char], use [String] type or single quotes ('') instead for: [${value.content}]", keyValue.lineNo) + // all other toml tree types are not supported + else -> throw IllegalTypeException( + "Cannot decode the key [${keyValue.key.last()}] with the value [${keyValue.value.content}]" + + " and with the provided type [Char]. Please check the type in your Serializable class or it's nullability", + keyValue.lineNo + ) + } } // Valid Toml types that should be properly decoded @@ -81,7 +108,7 @@ public abstract class TomlAbstractDecoder : AbstractDecoder() { } catch (e: ClassCastException) { throw IllegalTypeException( "Cannot decode the key [${keyValue.key.last()}] with the value [${keyValue.value.content}]" + - " with the provided type [${T::class}]. Please check the type in your Serializable class or it's nullability", + " and with the provided type [${T::class}]. Please check the type in your Serializable class or it's nullability", keyValue.lineNo ) } @@ -121,10 +148,10 @@ public abstract class TomlAbstractDecoder : AbstractDecoder() { */ private inline fun decodeInteger(content: Long, lineNo: Int): T = when (T::class) { - Byte::class -> validateAndConvertInteger(content, lineNo, BYTE) { num: Long -> num.toByte() as T } - Short::class -> validateAndConvertInteger(content, lineNo, SHORT) { num: Long -> num.toShort() as T } - Int::class -> validateAndConvertInteger(content, lineNo, INT) { num: Long -> num.toInt() as T } - Long::class -> validateAndConvertInteger(content, lineNo, LONG) { num: Long -> num as T } + Byte::class -> validateAndConvertInteger(content, lineNo, BYTE) { it.toByte() as T } + Short::class -> validateAndConvertInteger(content, lineNo, SHORT) { it.toShort() as T } + Int::class -> validateAndConvertInteger(content, lineNo, INT) { it.toInt() as T } + Long::class -> validateAndConvertInteger(content, lineNo, LONG) { it as T } Double::class, Float::class -> throw IllegalTypeException( "Expected floating-point number, but received integer literal: <$content>. " + "Deserialized floating-point number should have a dot: <$content.0>", diff --git a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/parsers/StringUtils.kt b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/parsers/StringUtils.kt index b8c4c930..781db4d0 100644 --- a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/parsers/StringUtils.kt +++ b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/parsers/StringUtils.kt @@ -175,7 +175,7 @@ private fun String.validateSymbols(lineNo: Int) { throw ParseException( "Not able to parse the key: [$this] as it contains invalid symbols." + " In case you would like to use special symbols - use quotes as" + - " it is required by TOML standard: \"My key ~ with special % symbols\"", + " it is required by TOML standard: \"My key with special (%, ±) symbols\" = \"value\"", lineNo ) } diff --git a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/utils/Types.kt b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/utils/Types.kt index 1e4f813b..ad28372a 100644 --- a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/utils/Types.kt +++ b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/utils/Types.kt @@ -10,6 +10,7 @@ package com.akuleshov7.ktoml.utils */ public enum class IntegerLimitsEnum(public val min: Long, public val max: Long) { BYTE(Byte.MIN_VALUE.toLong(), Byte.MAX_VALUE.toLong()), + CHAR(Char.MIN_VALUE.code.toLong(), Char.MAX_VALUE.code.toLong()), INT(Int.MIN_VALUE.toLong(), Int.MAX_VALUE.toLong()), LONG(Long.MIN_VALUE, Long.MAX_VALUE), SHORT(Short.MIN_VALUE.toLong(), Short.MAX_VALUE.toLong()), diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ArrayDecoderTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ArrayDecoderTest.kt index cefb064a..a1cdfe6f 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ArrayDecoderTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ArrayDecoderTest.kt @@ -356,10 +356,10 @@ class SimpleArrayDecoderTest { @Test fun testSimpleArrayDecoderInNestedTable() { var test = """ - |[table] - |name = "my name" - |configurationList = ["a", "b", "c"] - """.trimMargin() + [table] + name = "my name" + configurationList = ["a", "b", "c"] + """ assertEquals( ArrayInInlineTable( @@ -369,10 +369,10 @@ class SimpleArrayDecoderTest { test = """ - |[table] - |configurationList = ["a", "b", "c"] - |name = "my name" - """.trimMargin() + [table] + configurationList = ["a", "b", "c"] + name = "my name" + """ assertEquals( ArrayInInlineTable( @@ -381,11 +381,11 @@ class SimpleArrayDecoderTest { ) val testTable = """ - |configurationList1 = ["a", "b", "c"] - |configurationList2 = ["a", "b", "c"] - |[table] - |name = "my name" - """.trimMargin() + configurationList1 = ["a", "b", "c"] + configurationList2 = ["a", "b", "c"] + [table] + name = "my name" + """ assertEquals( TestArrays( @@ -396,13 +396,13 @@ class SimpleArrayDecoderTest { ) val testTableAndVariables = """ - |name1 = "simple" - |configurationList1 = ["a", "b", "c"] - |name2 = "simple" - |configurationList2 = ["a", "b", "c"] - |[table] - |name = "my name" - """.trimMargin() + name1 = "simple" + configurationList1 = ["a", "b", "c"] + name2 = "simple" + configurationList2 = ["a", "b", "c"] + [table] + name = "my name" + """ assertEquals( diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CharDecoderTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CharDecoderTest.kt new file mode 100644 index 00000000..8bb4223c --- /dev/null +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CharDecoderTest.kt @@ -0,0 +1,46 @@ +package com.akuleshov7.ktoml.decoders + +import com.akuleshov7.ktoml.Toml +import kotlinx.serialization.Serializable +import kotlinx.serialization.decodeFromString +import kotlin.test.Ignore +import kotlin.test.Test +import kotlin.test.assertEquals + + +class CharDecoderTest { + @Serializable + data class MyClass( + val a: Char, + val b: Char, + val c: Char, + ) + + @Test + fun charBasicTest() { + val test = + """ + a = 123 + b = '\n' + c = '\t' + """ + + // FixMe #177: actually this logic is invalid, because Literal Strings should not be making a conversion of str + val decoded = Toml.decodeFromString(test) + assertEquals(decoded, MyClass('{', '\n', '\t')) + } + + @Test + @Ignore + fun charUnicodeSymbolsTest() { + val test = + """ + a = '\u0048' + b = '\u0FCA' + c = '\u0002' + """ + + val decoded = Toml.decodeFromString(test) + assertEquals(decoded, MyClass('{', '\n', '\t')) + } +} diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/DottedKeysDecoderTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/DottedKeysDecoderTest.kt index 63b7fa6c..1f8e1b2f 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/DottedKeysDecoderTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/DottedKeysDecoderTest.kt @@ -110,16 +110,16 @@ class DottedKeysDecoderTest { ), Toml().decodeFromString( """ - |table2.b.d = 2 - |[table1] - |a.c = 1 - |[table1.table2] - |b.b.a = 1 - |[table2] - |b.f = 2 - |table2."foo bar".d = 2 - |[table3] - """.trimMargin() + table2.b.d = 2 + [table1] + a.c = 1 + [table1.table2] + b.b.a = 1 + [table2] + b.f = 2 + table2."foo bar".d = 2 + [table3] + """ ) ) } @@ -130,11 +130,11 @@ class DottedKeysDecoderTest { SimpleNestedExample(table2 = Table4(b = B(f = 2, d = 2), e = 5)), Toml(TomlInputConfig(true)).decodeFromString( """ - |table2.b.d = 2 - |[table2] - |e = 5 - |b.f = 2 - """.trimMargin() + table2.b.d = 2 + [table2] + e = 5 + b.f = 2 + """ ) ) } @@ -145,13 +145,13 @@ class DottedKeysDecoderTest { SimpleNestedExample(table2 = Table4(b = B(f = 7, d = 2), e = 6)), Toml(TomlInputConfig(true)).decodeFromString( """ - |[table2] - |table2."foo bar".d = 2 - |e = 6 - |[table2.b] - |d = 2 - |f = 7 - """.trimMargin() + [table2] + table2."foo bar".d = 2 + e = 6 + [table2.b] + d = 2 + f = 7 + """ ) ) } @@ -208,14 +208,14 @@ class DottedKeysDecoderTest { ), Toml.decodeFromString( """ - |[a."b.c..".d."e.f"] - | val = 1 - | [a] - | [a."b.c.."] - | val = 2 - | [a."b.c..".inner] - | val = 3 - """.trimMargin() + [a."b.c..".d."e.f"] + val = 1 + [a] + [a."b.c.."] + val = 2 + [a."b.c..".inner] + val = 3 + """ ) ) } diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/GeneralDecoderTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/GeneralDecoderTest.kt index 9aae9c25..beb39b82 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/GeneralDecoderTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/GeneralDecoderTest.kt @@ -279,11 +279,11 @@ class GeneralDecoderTest { @Test fun testChildTableBeforeParent() { val test = """ - |[a.b] - | c = 5 - | [a] - | a = true - """.trimMargin() + [a.b] + c = 5 + [a] + a = true + """ TomlInputConfig(true) assertEquals(ChildTableBeforeParent(A(B(5), true)), Toml.decodeFromString(test)) @@ -377,20 +377,20 @@ class GeneralDecoderTest { @Test fun severalTablesOnTheSameLevel() { val test = """ - |[table] - |[table.in1] - | a = 1 - | [table.in1.in1] - | a = 1 - | [table.in1.in2] - | a = 1 - |[table.in2] - | a = 1 - | [table.in2.in1] - | a = 1 - | [table.in2.in2] - | a = 1 - """.trimMargin() + [table] + [table.in1] + a = 1 + [table.in1.in1] + a = 1 + [table.in1.in2] + a = 1 + [table.in2] + a = 1 + [table.in2.in1] + a = 1 + [table.in2.in2] + a = 1 + """ assertEquals( MyTest( diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/IntegersDecoderTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/IntegersDecoderTest.kt index 17248d22..3c52a197 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/IntegersDecoderTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/IntegersDecoderTest.kt @@ -22,15 +22,15 @@ class IntegersDecoderTest { fun positiveScenario() { var test = """ s = 5 - b = 5 - i = 5 + b = +5 + i = -5 l = 5 - """.trimMargin() + """ var decoded = Toml.decodeFromString(test) println(decoded) assertEquals( - Integers(5, 5, 5, 5), + Integers(5, 5, -5, 5), decoded ) @@ -39,7 +39,7 @@ class IntegersDecoderTest { b = -128 i = 5 l = 5 - """.trimMargin() + """ decoded = Toml.decodeFromString(test) println(decoded) diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ReadMeExampleTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ReadMeExampleTest.kt index 0fcb3ce1..22126f57 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ReadMeExampleTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/ReadMeExampleTest.kt @@ -24,7 +24,7 @@ class ReadMeExampleTest { val property1: Long?, // please note, that according to the specification of toml integer values should be represented with Long, // but we allow to use Int/Short/etc. Just be careful with overflow - val property2: Int, + val property2: Byte, // no need to pass this value in the input as it has the default value and so it is NOT REQUIRED val property3: Short = 5 ) @@ -34,7 +34,11 @@ class ReadMeExampleTest { val someNumber: Long, @SerialName("akuleshov7.com") val inlineTable: NestedTable, - val otherNumber: Double + val otherNumber: Double, + // Char in a manner of Java/Kotlin is not supported in TOML, because single quotes are used for literal strings. + // However, ktoml supports reading Char from both single-char string and from it's integer code + val charFromString: Char, + val charFromInteger: Char ) @Serializable @@ -60,21 +64,24 @@ class ReadMeExampleTest { gradle-libs-like-property = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } [table1] - property1 = null # null is prohibited by the TOML spec, - property2 = 6 + property1 = null # null is prohibited by the TOML spec, + property2 = 6 [table2] - someNumber = 5 + someNumber = 5 [table2."akuleshov7.com"] - name = 'this is a "literal" string' - # empty lists are also supported - configurationList = ["a", "b", "c", null] + name = 'this is a "literal" string' + # empty lists are also supported + configurationList = ["a", "b", "c", null] # such redeclaration of table2 # is prohibited in toml specification; # but ktoml is allowing it in non-strict mode: [table2] - otherNumber = 5.56 + otherNumber = 5.56 + # use single quotes + charFromString = 'a' + charFromInteger = 123 """.trimMargin() @@ -87,12 +94,14 @@ class ReadMeExampleTest { table2 = Table2( someNumber = 5, inlineTable = NestedTable(name = "this is a \"literal\" string", overriddenName = listOf("a", "b", "c", null)), - otherNumber = 5.56 + otherNumber = 5.56, + charFromString = 'a', + charFromInteger = '{' ), + kotlinJvm = GradlePlugin("org.jetbrains.kotlin.jvm", Version("kotlin")) ), decoded ) } } - From 17b57b7663823c69f6d9ef0352b5be51fc66a60c Mon Sep 17 00:00:00 2001 From: Andrey Kuleshov Date: Thu, 5 Jan 2023 14:59:44 +0800 Subject: [PATCH 3/4] Adding the support for Char ### What's done: - conversion from a literal string to char - enabling some old tests - still we need unicode conversion and fixes for literal strings --- .../com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt | 2 +- .../kotlin/com/akuleshov7/ktoml/decoders/CharDecoderTest.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt index c80dedc7..0b19213c 100644 --- a/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt +++ b/ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/decoders/TomlAbstractDecoder.kt @@ -54,7 +54,7 @@ public abstract class TomlAbstractDecoder : AbstractDecoder() { } // to avoid confusion, we prohibit basic strings with double quotes for decoding to a Char type is TomlBasicString -> throw IllegalTypeException("Double quotes were used in the input for deserialization " + - "of [Char], use [String] type or single quotes ('') instead for: [${value.content}]", keyValue.lineNo) + "of [Char]. Use [String] type or single quotes ('') instead for: [${value.content}]", keyValue.lineNo) // all other toml tree types are not supported else -> throw IllegalTypeException( "Cannot decode the key [${keyValue.key.last()}] with the value [${keyValue.value.content}]" + diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CharDecoderTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CharDecoderTest.kt index 8bb4223c..cacf3b2e 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CharDecoderTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/CharDecoderTest.kt @@ -21,13 +21,13 @@ class CharDecoderTest { val test = """ a = 123 - b = '\n' - c = '\t' + b = '4' + c = 'D' """ // FixMe #177: actually this logic is invalid, because Literal Strings should not be making a conversion of str val decoded = Toml.decodeFromString(test) - assertEquals(decoded, MyClass('{', '\n', '\t')) + assertEquals(decoded, MyClass('{', '4', 'D')) } @Test From b2c673da1def6a02adaa9b230cfbdb373c2be9eb Mon Sep 17 00:00:00 2001 From: Andrey Kuleshov Date: Thu, 5 Jan 2023 17:24:42 +0800 Subject: [PATCH 4/4] Adding the support for Char ### What's done: - conversion from a literal string to char - enabling some old tests - still we need unicode conversion and fixes for literal strings --- .../ktoml/decoders/PrimitivesDecoderTest.kt | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/PrimitivesDecoderTest.kt b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/PrimitivesDecoderTest.kt index 0202a836..ea9cbc19 100644 --- a/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/PrimitivesDecoderTest.kt +++ b/ktoml-core/src/commonTest/kotlin/com/akuleshov7/ktoml/decoders/PrimitivesDecoderTest.kt @@ -51,22 +51,36 @@ class PrimitivesDecoderTest { @Test fun decodeChar() { fun test(expected: Char, input: String) { - val toml = /*language=TOML*/ """value = $input""" + val toml = /*language=TOML*/ "value = $input" + + @Serializable + data class Data(val value: Char) + + val data = Toml.decodeFromString(toml) + assertEquals(expected, data.value) + } + + test('1', "\'1\'") + test((1).toChar(), "1") + test(Char.MAX_VALUE, "65535") + test(Char.MIN_VALUE, "0") + } + + @Test + fun decodeCharFailure() { + fun test(expected: Char, input: String) { + val toml = /*language=TOML*/ "value = $input" @Serializable data class Data(val value: Char) assertFailsWith { - val data = Toml.decodeFromString(toml) - assertEquals(expected, data.value) + Toml.decodeFromString(toml) } } - test((0).toChar(), "0") test((-1).toChar(), "-1") - test((1).toChar(), "1") - test(Char.MAX_VALUE, "0") - test(Char.MIN_VALUE, "1") + test((65536).toChar(), "65536") } @Test