Skip to content

Commit

Permalink
Merge pull request #48 from Peanuuutz/dev
Browse files Browse the repository at this point in the history
Add initial support for sequential parsing.
  • Loading branch information
Peanuuutz authored Sep 28, 2023
2 parents 01d3379 + 8bf5744 commit 880f8ad
Show file tree
Hide file tree
Showing 13 changed files with 1,420 additions and 903 deletions.
101 changes: 100 additions & 1 deletion core/src/commonMain/kotlin/net/peanuuutz/tomlkt/Toml.kt
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,53 @@ public sealed class Toml(
return decodeFromTomlElement(deserializer, element)
}

/**
* Deserializes the content of the [reader] into a value of type [T] using
* [deserializer].
*
* @param reader **MUST** contain a TOML file, as this method delegates
* parsing to [parseToTomlTable].
*
* @throws TomlDecodingException if the content cannot be parsed into
* [TomlTable] or cannot be deserialized.
*/
@Suppress("OutdatedDocumentation")
public fun <T> decodeFromReader(
deserializer: DeserializationStrategy<T>,
reader: TomlReader
): T {
val table = parseToTomlTable(reader)
return decodeFromTomlElement(deserializer, table)
}

/**
* Parses the content of the [reader] into a [TomlTable] and deserializes
* the corresponding element fetched with [keys] into a value of type [T]
* using [deserializer].
*
* @param reader **MUST** contain a TOML file, as this method delegates
* parsing to [parseToTomlTable].
* @param keys the path which leads to the value. Each one item is a single
* segment. If a [TomlArray] is met, any direct child segment must be [Int]
* or [String] (will be parsed into integer).
*
* @throws TomlDecodingException if the content cannot be parsed into
* [TomlTable] or the element cannot be deserialized.
* @throws NonPrimitiveKeyException if provided non-primitive keys.
*
* @see get
*/
@Suppress("OutdatedDocumentation")
public fun <T> decodeFromReader(
deserializer: DeserializationStrategy<T>,
reader: TomlReader,
vararg keys: Any?
): T {
val table = parseToTomlTable(reader)
val element = table.get(keys = keys)!!
return decodeFromTomlElement(deserializer, element)
}

/**
* Deserializes [element] into a value of type [T] using [deserializer].
*
Expand All @@ -201,7 +248,19 @@ public sealed class Toml(
* [TomlTable].
*/
public fun parseToTomlTable(string: String): TomlTable {
return TomlFileParser(string).parse()
val reader = TomlStringReader(string)
return parseToTomlTable(reader)
}

/**
* Parses the content of the [reader] into equivalent representation of
* [TomlTable].
*
* @throws TomlDecodingException if the content cannot be parsed into
* [TomlTable].
*/
public fun parseToTomlTable(reader: TomlReader): TomlTable {
return TomlFileParser(reader).parse()
}
}

Expand Down Expand Up @@ -267,6 +326,46 @@ public inline fun <reified T> Toml.decodeFromString(
return decodeFromString(serializersModule.serializer(), string, keys = keys)
}

/**
* Deserializes the content of the [reader] into a value of type [T] using the
* serializer retrieved from reified type parameter.
*
* @param reader **MUST** contain a TOML file, as this method delegates parsing
* to [Toml.parseToTomlTable].
*
* @throws TomlDecodingException if the content cannot be parsed into
* [TomlTable] or cannot be deserialized.
*/
@Suppress("OutdatedDocumentation")
public inline fun <reified T> Toml.decodeFromReader(reader: TomlReader): T {
return decodeFromReader(serializersModule.serializer(), reader)
}

/**
* Parses the content of the [reader] into a [TomlTable] and deserializes
* the corresponding element fetched with [keys] into a value of type [T]
* using the serializer retrieved from reified type parameter.
*
* @param reader **MUST** contain a TOML file, as this method delegates
* parsing to [Toml.parseToTomlTable].
* @param keys the path which leads to the value. Each one item is a single
* segment. If a [TomlArray] is met, any direct child segment must be [Int]
* or [String] (will be parsed into integer).
*
* @throws TomlDecodingException if the content cannot be parsed into
* [TomlTable] or the element cannot be deserialized.
* @throws NonPrimitiveKeyException if provided non-primitive keys.
*
* @see get
*/
@Suppress("OutdatedDocumentation")
public inline fun <reified T> Toml.decodeFromReader(
reader: TomlReader,
vararg keys: Any?
): T {
return decodeFromReader(serializersModule.serializer(), reader, keys = keys)
}

/**
* Deserializes [element] into a value of type [T] using the serializer
* retrieved from reified type parameter.
Expand Down
30 changes: 30 additions & 0 deletions core/src/commonMain/kotlin/net/peanuuutz/tomlkt/TomlReader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Copyright 2023 Peanuuutz
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package net.peanuuutz.tomlkt

/**
* A custom reader used when decoding TOML file.
*
* @see TomlStringReader
*/
public interface TomlReader {
/**
* Reads a single character and returns its [code], or returns -1 if EOF is
* met.
*/
public fun read(): Int
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Copyright 2023 Peanuuutz
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package net.peanuuutz.tomlkt

/**
* A [TomlReader] that reads TOML string.
*
* This reader is NOT thread-safe, so any concurrent usage should be avoided.
*
* Use with [Toml.decodeFromReader] to decode objects. Note that it is more
* preferable to use [Toml.decodeFromString] directly as the reader is
* disposable and should not be used twice.
*/
public class TomlStringReader(
private val source: String
) : TomlReader {
private val length: Int = source.length

private var currentIndex: Int = 0

override fun read(): Int {
if (currentIndex >= length) {
return -1
}
return source[currentIndex++].code
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package net.peanuuutz.tomlkt
/**
* A [TomlWriter] that writes TOML as string.
*
* This writer is NOT thread-safe, so any concurrent usage should be avoided.
*
* Use with [Toml.encodeToWriter] to encode objects. This is useful for
* concatenating two TOML strings. However, programmer should prefer
* [Toml.encodeToString] if only one object is being encoded.
Expand Down
33 changes: 33 additions & 0 deletions core/src/commonMain/kotlin/net/peanuuutz/tomlkt/TomlWriter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,44 +24,77 @@ import net.peanuuutz.tomlkt.internal.toStringModified
* @see [TomlStringWriter]
*/
public interface TomlWriter {
/**
* Writes [string].
*/
public fun writeString(string: String)

/**
* Writes [boolean].
*/
public fun writeBoolean(boolean: Boolean) {
writeString(boolean.toString())
}

/**
* Writes [byte] **as literal**.
*/
public fun writeByte(byte: Byte) {
writeString(byte.toString())
}

/**
* Writes [short] **as literal**.
*/
public fun writeShort(short: Short) {
writeString(short.toString())
}

/**
* Writes [int] **as literal**.
*/
public fun writeInt(int: Int) {
writeString(int.toString())
}

/**
* Writes [long] **as literal**.
*/
public fun writeLong(long: Long) {
writeString(long.toString())
}

/**
* Writes [float].
*/
public fun writeFloat(float: Float) {
writeString(float.toStringModified())
}

/**
* Writes [double].
*/
public fun writeDouble(double: Double) {
writeString(double.toStringModified())
}

/**
* Writes [char].
*/
public fun writeChar(char: Char) {
writeString(char.toString())
}

/**
* Writes "null".
*/
public fun writeNull() {
writeString("null")
}

/**
* Writes '\n'.
*/
public fun writeLineFeed() {
writeString("\n")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
Copyright 2023 Peanuuutz
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package net.peanuuutz.tomlkt.internal

// No way a number reach this big...
internal const val BufferSize: Int = 1 * 64

internal expect object BufferPool {
fun take(): CharArray

fun release(buffer: CharArray)
}
Loading

0 comments on commit 880f8ad

Please sign in to comment.