Skip to content

Commit

Permalink
Merge pull request #53 from Peanuuutz/dev
Browse files Browse the repository at this point in the history
0.3.5 TomlWriter expansion.
  • Loading branch information
Peanuuutz authored Oct 5, 2023
2 parents a2aa96f + edcc207 commit 2cf67f4
Show file tree
Hide file tree
Showing 12 changed files with 763 additions and 234 deletions.
235 changes: 235 additions & 0 deletions core/src/commonMain/kotlin/net/peanuuutz/tomlkt/AbstractTomlWriter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
package net.peanuuutz.tomlkt

import net.peanuuutz.tomlkt.TomlInteger.Base
import net.peanuuutz.tomlkt.TomlInteger.Base.Dec
import net.peanuuutz.tomlkt.internal.Comment
import net.peanuuutz.tomlkt.internal.ElementSeparator
import net.peanuuutz.tomlkt.internal.EndArray
import net.peanuuutz.tomlkt.internal.EndInlineTable
import net.peanuuutz.tomlkt.internal.EndTableHead
import net.peanuuutz.tomlkt.internal.KeySeparator
import net.peanuuutz.tomlkt.internal.KeyValueSeparator
import net.peanuuutz.tomlkt.internal.StartArray
import net.peanuuutz.tomlkt.internal.StartInlineTable
import net.peanuuutz.tomlkt.internal.StartTableHead
import net.peanuuutz.tomlkt.internal.doubleQuoted
import net.peanuuutz.tomlkt.internal.escape
import net.peanuuutz.tomlkt.internal.processIntegerString
import net.peanuuutz.tomlkt.internal.singleQuoted
import net.peanuuutz.tomlkt.internal.toStringModified

/**
* The basic implementation of [TomlWriter], handling all the essential logic
* except [writeString] and (optional) [writeChar].
*/
public abstract class AbstractTomlWriter : TomlWriter {
// -------- Core --------

// Better implementation is welcomed.
override fun writeChar(char: Char) {
writeString(char.toString())
}

// -------- Key --------

final override fun writeKey(key: String) {
writeString(key)
}

final override fun writeKeySeparator() {
writeChar(KeySeparator)
}

// -------- Table Head --------

final override fun startRegularTableHead() {
writeChar(StartTableHead)
}

final override fun endRegularTableHead() {
writeChar(EndTableHead)
}

final override fun startArrayOfTableHead() {
writeChar(StartTableHead)
writeChar(StartTableHead)
}

final override fun endArrayOfTableHead() {
writeChar(EndTableHead)
writeChar(EndTableHead)
}

// -------- Value --------

final override fun writeBooleanValue(boolean: Boolean) {
writeString(boolean.toString())
}

final override fun writeByteValue(
byte: Byte,
base: Base,
group: Int,
uppercase: Boolean
) {
require(group >= 0) { "Group size cannot be negative" }
require(byte >= 0.toByte() || base == Dec) {
"Negative integer cannot be represented by other bases, but found $byte"
}
val string = processIntegerString(
raw = byte.toString(base.value),
base = base,
group = group,
uppercase = uppercase
)
writeString(string)
}

final override fun writeShortValue(
short: Short,
base: Base,
group: Int,
uppercase: Boolean
) {
require(group >= 0) { "Group size cannot be negative" }
require(short >= 0.toShort() || base == Dec) {
"Negative integer cannot be represented by other bases, but found $short"
}
val string = processIntegerString(
raw = short.toString(base.value),
base = base,
group = group,
uppercase = uppercase
)
writeString(string)
}

final override fun writeIntValue(
int: Int,
base: Base,
group: Int,
uppercase: Boolean
) {
require(group >= 0) { "Group size cannot be negative" }
require(int >= 0 || base == Dec) {
"Negative integer cannot be represented by other bases, but found $int"
}
val string = processIntegerString(
raw = int.toString(base.value),
base = base,
group = group,
uppercase = uppercase
)
writeString(string)
}

final override fun writeLongValue(
long: Long,
base: Base,
group: Int,
uppercase: Boolean
) {
require(group >= 0) { "Group size cannot be negative" }
require(long >= 0L || base == Dec) {
"Negative integer cannot be represented by other bases, but found $long"
}
val string = processIntegerString(
raw = long.toString(base.value),
base = base,
group = group,
uppercase = uppercase
)
writeString(string)
}

final override fun writeFloatValue(float: Float) {
writeString(float.toStringModified())
}

final override fun writeDoubleValue(double: Double) {
writeString(double.toStringModified())
}

final override fun writeCharValue(char: Char) {
writeString(char.escape().doubleQuoted)
}

final override fun writeStringValue(string: String, isMultiline: Boolean, isLiteral: Boolean) {
when {
!isMultiline && !isLiteral -> {
writeString(string.escape().doubleQuoted)
}
!isMultiline -> {
require('\'' !in string && '\n' !in string) {
"Cannot have '\\'' or '\\n' in literal string, but found $string"
}
writeString(string.singleQuoted)
}
!isLiteral -> {
writeString("\"\"\"")
writeLineFeed()
writeString(string.escape(multiline = true))
writeString("\"\"\"")
}
else -> {
require("\'\'\'" !in string) {
"Cannot have \"\\'\\'\\'\" in multiline literal string, but found $string"
}
writeString("\'\'\'")
writeLineFeed()
writeString(string)
writeString("\'\'\'")
}
}
}

final override fun writeNullValue() {
writeString("null")
}

// -------- Structure --------

final override fun startArray() {
writeChar(StartArray)
}

final override fun endArray() {
writeChar(EndArray)
}

final override fun startInlineTable() {
writeChar(StartInlineTable)
}

final override fun endInlineTable() {
writeChar(EndInlineTable)
}

final override fun writeKeyValueSeparator() {
writeChar(KeyValueSeparator)
}

final override fun writeElementSeparator() {
writeChar(ElementSeparator)
}

// -------- Comment --------

final override fun startComment() {
writeChar(Comment)
}

// -------- Control --------

final override fun writeSpace() {
writeChar(' ')
}

final override fun writeIndentation(indentation: TomlIndentation) {
writeString(indentation.representation)
}

final override fun writeLineFeed() {
writeChar('\n')
}
}
45 changes: 28 additions & 17 deletions core/src/commonMain/kotlin/net/peanuuutz/tomlkt/Annotations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package net.peanuuutz.tomlkt

import kotlinx.serialization.InheritableSerialInfo
import kotlinx.serialization.SerialInfo
import net.peanuuutz.tomlkt.TomlInteger.Base.Dec

/**
* Adds comments to corresponding property.
Expand Down Expand Up @@ -80,8 +81,8 @@ public annotation class TomlInline
/**
* Modifies the encoding process of corresponding array-like property, either to
* force array of tables to be encoded as block array, or to change how many
* items will be encoded per line (will override
* [TomlConfig][TomlConfigBuilder.itemsPerLineInBlockArray]).
* items will be encoded per line (this will override the default
* [config][TomlConfigBuilder.itemsPerLineInBlockArray]).
*
* Note: If the corresponding property is marked [TomlInline], this annotation
* will not take effect.
Expand Down Expand Up @@ -160,56 +161,66 @@ public annotation class TomlLiteralString
*
* ```kotlin
* class ByteCode(
* @TomlInteger(TomlInteger.Base.Bin)
* val code: Byte
* @TomlInteger(
* base = TomlInteger.Base.Hex,
* group = 2
* )
* val code: Int
* )
* ByteCode(0b1101)
* ByteCode(0xFFE490)
* ```
*
* will produce:
*
* ```toml
* code = 0b1101
* code = 0xFF_E4_90
* ```
*
* @property group the size of a digit group separated by '_'. If set to 0, the
* digits will not be grouped.
*/
@Suppress("OutdatedDocumentation")
@SerialInfo
@Target(AnnotationTarget.PROPERTY)
public annotation class TomlInteger(val base: Base) {
public annotation class TomlInteger(
val base: Base = Dec,
val group: Int = 0
) {
/**
* The representation of a [TOML integer](https://toml.io/en/v1.0.0#integer).
*/
public enum class Base(
public val value: Int,
public val prefix: String
) {
Dec(10, ""),
Hex(16, "0x"),
Bin(2, "0b"),
Oct(8, "0o"),
Dec(10, ""),
Hex(16, "0x"),

@Deprecated(
message = "Unify singleton style.",
replaceWith = ReplaceWith("Dec")
replaceWith = ReplaceWith("Bin")
)
DEC(10, ""),
BIN(2, "0b"),

@Deprecated(
message = "Unify singleton style.",
replaceWith = ReplaceWith("Hex")
replaceWith = ReplaceWith("Oct")
)
HEX(16, "0x"),
OCT(8, "0o"),

@Deprecated(
message = "Unify singleton style.",
replaceWith = ReplaceWith("Bin")
replaceWith = ReplaceWith("Dec")
)
BIN(2, "0b"),
DEC(10, ""),

@Deprecated(
message = "Unify singleton style.",
replaceWith = ReplaceWith("Oct")
replaceWith = ReplaceWith("Hex")
)
OCT(8, "0o");
HEX(16, "0x")
}
}

Expand Down
16 changes: 14 additions & 2 deletions core/src/commonMain/kotlin/net/peanuuutz/tomlkt/TomlConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class TomlConfigBuilder @PublishedApi internal constructor(from: TomlConf
// -------- Common --------

/**
* The [SerializersModule] to be used in the [Toml] instance.
* Specifies the [SerializersModule] to be used in the [Toml] instance.
*
* [EmptySerializersModule] by default.
*/
Expand All @@ -46,7 +46,8 @@ public class TomlConfigBuilder @PublishedApi internal constructor(from: TomlConf
public var explicitNulls: Boolean = from.explicitNulls

/**
* The key of the class discriminator for polymorphic serialization.
* Specifies the key of the class discriminator for polymorphic
* serialization.
*
* "type" by default.
*/
Expand All @@ -68,6 +69,14 @@ public class TomlConfigBuilder @PublishedApi internal constructor(from: TomlConf
*/
public var itemsPerLineInBlockArray: Int = from.itemsPerLineInBlockArray

/**
* Specifies whether the letters in an integer should be encoded as
* uppercase by default.
*
* `true` by default.
*/
public var uppercaseInteger: Boolean = from.uppercaseInteger

// -------- Deserialization --------

/**
Expand All @@ -89,6 +98,7 @@ public class TomlConfigBuilder @PublishedApi internal constructor(from: TomlConf
classDiscriminator = classDiscriminator,
indentation = indentation,
itemsPerLineInBlockArray = itemsPerLineInBlockArray,
uppercaseInteger = uppercaseInteger,
ignoreUnknownKeys = ignoreUnknownKeys
)
}
Expand Down Expand Up @@ -139,6 +149,7 @@ internal class TomlConfig(
val classDiscriminator: String,
val indentation: TomlIndentation,
val itemsPerLineInBlockArray: Int,
val uppercaseInteger: Boolean,
val ignoreUnknownKeys: Boolean
) {
companion object {
Expand All @@ -148,6 +159,7 @@ internal class TomlConfig(
classDiscriminator = "type",
indentation = TomlIndentation.Space4,
itemsPerLineInBlockArray = 1,
uppercaseInteger = true,
ignoreUnknownKeys = false
)
}
Expand Down
Loading

0 comments on commit 2cf67f4

Please sign in to comment.