Skip to content

Commit

Permalink
Implement encoding (#153)
Browse files Browse the repository at this point in the history
* Create encoders and expose TomlInlineTable's element list

* Add a convenience "encode" function and clarify docs

* Hook encoding into Toml and TomlFileWriter classes

* Add a test and fix errors

- Map keys and values weren't being differentiated
- currentKey wasn't set for elements within non-class structures
- Any element except classes, maps, and lists was throwing an "Unknown kind" exception
- TomlArrayEncoder had two incomplete paths for table array elements

* Add "type" target to annotations

* Add the rest of the tests

* Specify the default parameters explicitly for annotations

A strange compiler error is thrown otherwise:
ERROR_EXPR 'Stub expression for default value of inline'

I'll have to file an issue on YouTrack, but in the meantime this works.

* Fix import ordering... again

* Fix test failures

- TomlArrayEncoder.values was never initialized
- Non-table-arrays were treated as inline table arrays, leading to an
  exception
- Table entries in table arrays didn't include the parent table array
  in their keys
- Annotations weren't detected on property types

The comment annotation tests have been commented out temporarily due to
a ClassCastException in the data class. A string array is being cast to
a string in the serializer. Is this a bug in kotlinx.serialization?

* Clarify the note on TomlComments with an issue ID

* Start encoder rewrite

* Add output config options for ignoring null and default values

* Rewrite encoders and correct some minor test errors

* Fix double indentation on dotted table elements

* Fix date time and annotation tests

- Remove currently unsupported @TomlMultiline from a date time test
property
- Remove test properties of the form `val x: @annotation X`. This
  annotation is inaccessible
- Disable comment tests pending KT-53235
- Remove offset instants from the date time test, since LocalDateTimes
  are offset to UTC when converted to instants regardless of the time
  zone specified

* Cleanup and document encoders

* Add a SerializersModule property to TomlOutputConfig

* Use the serializersModule property in Toml instead

* Add a more comprehensive test set and fix errors

Polymorphic array elements were being wrongly treated as inline tables;
these are now written as nested arrays (i.e. `[ "typeName", value ]`).
"Escapes" were rejected in literal strings during writing, a behavior
inconsistent with the spec. Null values were encoded regardless of the
ignoreNullValues config property.

* Fix encoders and writing, and clean up

Keys with invalid characters were not promoted to basic or literal keys.
Table parents were being explicitly defined; a config property was added
for this behavior. Empty tables would fail to write due to a missing
stub node. Tables nested more than one level in a table array element
were missing the table array key in their headers. Nested inline tables
with a single pair are now converted to dotted pairs. Escapes were
erroneously rejected in literal strings. In-place serialized primitive
lists in polymorphic classes (i.e. sealedTableArrayTest) were serialized
as array tables, causing an exception.

* Make Diktat happy and clean up dead code

* Fix last double indent bug (hopefully)

* Move Attributes to its own file

* Add a test for string examples from the TOML docs

* Explicitly mark enums as @serializable for Native

* fixing diktat issues

* skipping problematic part of test for js:
    temp_targets = { cpu = 79.5, case = 72.0 }

Co-authored-by: Andrey Kuleshov <andrewkuleshov7@gmail.com>
  • Loading branch information
NightEule5 and orchestr7 authored Oct 30, 2022
1 parent b5823e5 commit 9aa530f
Show file tree
Hide file tree
Showing 35 changed files with 2,581 additions and 90 deletions.
6 changes: 4 additions & 2 deletions ktoml-core/src/commonMain/kotlin/com/akuleshov7/ktoml/Toml.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.akuleshov7.ktoml

import com.akuleshov7.ktoml.decoders.TomlMainDecoder
import com.akuleshov7.ktoml.encoders.TomlMainEncoder
import com.akuleshov7.ktoml.exceptions.MissingRequiredPropertyException
import com.akuleshov7.ktoml.parsers.TomlParser
import com.akuleshov7.ktoml.tree.TomlFile
import com.akuleshov7.ktoml.utils.findPrimitiveTableInAstByName
import com.akuleshov7.ktoml.writers.TomlWriter

import kotlin.native.concurrent.ThreadLocal
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.ExperimentalSerializationApi
Expand Down Expand Up @@ -60,7 +60,9 @@ public open class Toml(
}

override fun <T> encodeToString(serializer: SerializationStrategy<T>, value: T): String {
TODO("Not yet implemented")
val toml = TomlMainEncoder.encode(serializer, value, inputConfig, outputConfig, serializersModule)

return tomlWriter.writeToString(file = toml)
}

// ================== custom decoding methods ===============
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public data class TomlInputConfig(
public val allowEmptyValues: Boolean = true,
public val allowNullValues: Boolean = true,
public val allowEmptyToml: Boolean = true,
public val allowEscapedQuotesInLiteralStrings: Boolean = true
public val allowEscapedQuotesInLiteralStrings: Boolean = true,
) {
public companion object {
/**
Expand Down Expand Up @@ -110,24 +110,37 @@ public data class TomlInputConfig(
*
* @property indentation The number of spaces in the indents for the serialization
* @property allowEscapedQuotesInLiteralStrings Whether to allow/prohibit escaping of single quotes in literal strings
* @property ignoreNullValues Whether to ignore null values
* @property ignoreDefaultValues Whether to ignore default values
* @property explicitTables Whether to explicitly define parent tables
*/
public data class TomlOutputConfig(
public val indentation: TomlIndentation = TomlIndentation.FOUR_SPACES,
public val allowEscapedQuotesInLiteralStrings: Boolean = true,
public val ignoreNullValues: Boolean = true,
public val ignoreDefaultValues: Boolean = false,
public val explicitTables: Boolean = false,
) {
public companion object {
/**
* Creates a config populated with values compliant with the TOML spec.
*
* @param indentation The number of spaces in the indents for the serialization
* @param ignoreDefaultValues Whether to ignore default values
* @param explicitTables Whether to explicitly define parent tables
* @return A TOML spec-compliant output config
*/
public fun compliant(
indentation: TomlIndentation = TomlIndentation.FOUR_SPACES
indentation: TomlIndentation = TomlIndentation.FOUR_SPACES,
ignoreDefaultValues: Boolean = false,
explicitTables: Boolean = false,
): TomlOutputConfig =
TomlOutputConfig(
indentation,
allowEscapedQuotesInLiteralStrings = false
allowEscapedQuotesInLiteralStrings = false,
ignoreNullValues = true,
ignoreDefaultValues,
explicitTables
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import kotlin.annotation.AnnotationTarget.PROPERTY
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialInfo

// FixMe: Default parameters after varargs are broken as of 1.7: KT-53235. There's
// no obvious workaround

/**
* Specifies comments to be applied the TOML element produced by a property during
* serialization. Has no effect on deserialization.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import kotlinx.serialization.SerialInfo
@Target(
PROPERTY,
TYPE_PARAMETER,
CLASS
CLASS,
TYPE
)
public annotation class TomlInlineTable
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.akuleshov7.ktoml.annotations

import com.akuleshov7.ktoml.writers.IntegerRepresentation
import com.akuleshov7.ktoml.writers.IntegerRepresentation.DECIMAL
import kotlin.annotation.AnnotationTarget.PROPERTY
import kotlin.annotation.AnnotationTarget.TYPE_PARAMETER

import kotlin.annotation.AnnotationTarget.*
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialInfo

Expand Down Expand Up @@ -36,7 +36,11 @@ import kotlinx.serialization.SerialInfo
*/
@OptIn(ExperimentalSerializationApi::class)
@SerialInfo
@Target(PROPERTY, TYPE_PARAMETER)
@Target(
PROPERTY,
TYPE_PARAMETER,
TYPE
)
public annotation class TomlInteger(
val representation: IntegerRepresentation = DECIMAL
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.akuleshov7.ktoml.annotations

import kotlin.annotation.AnnotationTarget.PROPERTY
import kotlin.annotation.AnnotationTarget.TYPE_PARAMETER
import kotlin.annotation.AnnotationTarget.*
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialInfo

Expand Down Expand Up @@ -31,5 +30,9 @@ import kotlinx.serialization.SerialInfo
*/
@OptIn(ExperimentalSerializationApi::class)
@SerialInfo
@Target(PROPERTY, TYPE_PARAMETER)
@Target(
PROPERTY,
TYPE_PARAMETER,
TYPE
)
public annotation class TomlLiteral
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.akuleshov7.ktoml.annotations

import kotlin.annotation.AnnotationTarget.PROPERTY
import kotlin.annotation.AnnotationTarget.TYPE_PARAMETER
import kotlin.annotation.AnnotationTarget.*
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialInfo

Expand Down Expand Up @@ -58,5 +57,9 @@ import kotlinx.serialization.SerialInfo
*/
@OptIn(ExperimentalSerializationApi::class)
@SerialInfo
@Target(PROPERTY, TYPE_PARAMETER)
@Target(
PROPERTY,
TYPE_PARAMETER,
TYPE
)
public annotation class TomlMultiline
Loading

0 comments on commit 9aa530f

Please sign in to comment.