From 886d84b6716ccdbc3233a210327084a117752f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Petit?= Date: Sun, 14 May 2023 17:15:02 +0200 Subject: [PATCH] Add doc --- .../serialization/properties/Properties.kt | 2 +- .../properties/StringProperties.kt | 88 ++++++++++++++++--- 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/formats/properties/commonMain/src/kotlinx/serialization/properties/Properties.kt b/formats/properties/commonMain/src/kotlinx/serialization/properties/Properties.kt index 8760950c3c..700e805d98 100644 --- a/formats/properties/commonMain/src/kotlinx/serialization/properties/Properties.kt +++ b/formats/properties/commonMain/src/kotlinx/serialization/properties/Properties.kt @@ -26,7 +26,7 @@ import kotlinx.serialization.modules.* * @Serializable * class DataHolder(val data: Data, val property2: String) * - * val map = Properties.store(DataHolder(Data("value1"), "value2")) + * val map = Properties.encodeToMap(DataHolder(Data("value1"), "value2")) * // map contents will be the following: * // property2 = value2 * // data.property1 = value1 diff --git a/formats/properties/commonMain/src/kotlinx/serialization/properties/StringProperties.kt b/formats/properties/commonMain/src/kotlinx/serialization/properties/StringProperties.kt index 1cebf6dcce..5c6531c0ed 100644 --- a/formats/properties/commonMain/src/kotlinx/serialization/properties/StringProperties.kt +++ b/formats/properties/commonMain/src/kotlinx/serialization/properties/StringProperties.kt @@ -10,19 +10,64 @@ import kotlinx.serialization.encoding.* import kotlinx.serialization.internal.* import kotlinx.serialization.modules.* +/** + * Transforms a [Serializable] class' properties into a single flat [String] representing the class data + * in the properties format. + * + * If the given class has non-primitive property `d` of arbitrary type `D`, `D` values are inserted + * into the same map; keys for such values are prefixed with string `d.`: + * + * ``` + * @Serializable + * class Data(val property1: String) + * + * @Serializable + * class DataHolder(val data: Data, val property2: String) + * + * val string = StringProperties.encodeToString(properties) + * // string contents will be the following: + * """ + * property2 = value2 + * data.property1 = value1 + * """ + * ``` + * + * If the given class has a [List] property `l`, each value from the list + * would be prefixed with `l.N.`, where N is an index for a particular value. + * [Map] is treated as a `[key,value,...]` list. + + * Conversely, this class can convert a properties string into a [Serializable] class instance. + * ``` + * @Serializable + * class Data(val property1: String) + * + * @Serializable + * class DataHolder(val data: Data, val property2: String) + * + * val string = """ + * property2 = value2 + * data.property1 = value1 + * """ + * val data = StringProperties.decodeToString(string, DataHolder.serializer()) + * // data contents will be the following: + * // DataHolder(data = Data(property1 = "value1"), property2 = "value2") + * ``` + * + * @param conf A [PropertiesConf] which contain configuration for customising the output string. + */ @ExperimentalSerializationApi @Suppress("UNUSED_PARAMETER") public sealed class StringProperties( private val conf: PropertiesConf, private val properties: Properties = Properties(conf.serializersModule), -) : SerialFormat by properties { +) : SerialFormat by properties, StringFormat { /** * Encodes properties from the given [value] to a properties String using the given [serializer]. * `null` values are omitted from the output. */ @ExperimentalSerializationApi - public fun encodeToString(serializer: SerializationStrategy, value: T): String { + public override fun encodeToString(serializer: SerializationStrategy, value: T): String { val map = properties.encodeToMap(serializer, value) val builder = StringBuilder() for ((k, v) in map) { @@ -45,12 +90,10 @@ public sealed class StringProperties( * [String] values are converted to respective primitive types using default conversion methods. * [T] may contain properties of nullable types; they will be filled by non-null values from the [map], if present. */ - public fun decodeFromString(deserializer: DeserializationStrategy, string: String): T { + public override fun decodeFromString(deserializer: DeserializationStrategy, string: String): T { val result = mutableMapOf() for (line in string.logicalLines()) { - println("line=`$line`") val parsedLine = line.unescaped() - println("parsedLine=`$parsedLine`") var keyEnd = parsedLine.length for (i in parsedLine.indices) { if (parsedLine[i] in separators) { @@ -77,8 +120,6 @@ public sealed class StringProperties( result[parsedLine.substring(0, keyEnd)] = parsedLine.substring(valueBegin) } - println(result) - println(result.keys) return properties.decodeFromStringMap(deserializer, result) } @@ -97,8 +138,8 @@ private class StringPropertiesImpl(conf: PropertiesConf) : StringProperties(conf * TODO: doc */ @ExperimentalSerializationApi -public fun StringProperties(builderAction: PropertiesBuilder.() -> Unit = {}): StringProperties { - val builder = PropertiesBuilder(PropertiesConf()) +public fun StringProperties(builderAction: StringPropertiesBuilder.() -> Unit = {}): StringProperties { + val builder = StringPropertiesBuilder(PropertiesConf()) builder.builderAction() return StringPropertiesImpl(builder.build()) } @@ -121,13 +162,40 @@ public inline fun StringProperties.encodeToString(value: T): String public inline fun StringProperties.decodeFromString(propertiesString: String): T = decodeFromString(serializersModule.serializer(), propertiesString) +/** + * Builder of the [StringProperties] instance provided by `StringProperties { ... }` factory function. + */ @ExperimentalSerializationApi -public class PropertiesBuilder internal constructor(from: PropertiesConf) { +public class StringPropertiesBuilder internal constructor(from: PropertiesConf) { + /** + * A [LineSeparator] to be used for separating lines when encoding to a string. + * Default value is [LineSeparator.LF]. + */ public var lineSeparator: LineSeparator = from.lineSeparator + + /** + * A [KeyValueSeparator] to be used for separating keys and values when encoding to a string. + * Default value is [KeyValueSeparator.EQUALS]. + */ public var keyValueSeparator: KeyValueSeparator = from.keyValueSeparator + + /** + * A number of spaces to be inserted before the [keyValueSeparator] when encoding to a string. + * Default value is `0`. + */ public var spacesBeforeSeparator: Int = from.spacesBeforeSeparator + + /** + * A number of spaces to be inserted after the [keyValueSeparator] when encoding to a string. + * Default value is `0`. + */ public var spacesAfterSeparator: Int = from.spacesAfterSeparator + + /** + * A [SerializersModule] to be used for encoding and decoding. + * Default value is [EmptySerializersModule]. + */ public var module: SerializersModule = from.serializersModule internal fun build(): PropertiesConf {