A TOML 1.0 parser library for Kotlin

Overview

4koma

Docs Release Build Status Coverage License

A small, stand-alone, easy to use TOML parser library for Kotlin.

4koma supports an array of convenient features, such as full TOML 1.0 compliance, type-safe decoding of configurations into arbitrary data classes using Kotlin generics, and easy access to individual properties for when you don't need the entire document.

4koma follows the UNIX philosophy, in that it tries to do one thing (i.e. TOML processing for Kotlin projects), and do it well. If you need support for multiple configuration formats, or are using a JVM language other than Kotlin, some of the projects listed in the Alternatives section might serve you better.

Usage

Getting started with 4koma is super easy.

1. Add a dependency on 4koma

For build.gradle.kts:

repositories {
    maven {
        url = uri("https://jitpack.io")
    }
}

dependencies {
    implementation("cc.ekblad:4koma:0.3.0")
}

2. Obtain a TOML file

[settings]
maxLoginTries = 3

[[user]]
name = "Alice"
password = "password123"

[[user]]
name = "Bob"
password = "correct horse battery staple"

3. Write some code

import cc.ekblad.toml.TomlDecoder
import cc.ekblad.toml.TomlValue
import cc.ekblad.toml.decode
import cc.ekblad.toml.withMapping
import cc.ekblad.toml.get
import java.nio.file.Path

data class Config(
    val settings: Settings,
    val user: List<User>
) {
    data class User(val name: String, val password: String)
    data class Settings(val maxLoginRetries: Int)
}

fun main() {
    // Parse a TOML document from a string, stream, or file
    val tomlDocument = TomlValue.from(Path.of("test.toml"))

    // Decode it to your config type
    val config = tomlDocument.decode<Config>()

    // If you're lazy, just decode it to a map
    val mapConfig = tomlDocument.decode<Map<String, Any>>()

    // ...or access properties directly
    val maxLoginTries = tomlDocument["settings", "maxLoginTries"]

    // ...or just grab a part of the document and decode it to some convenient data class
    val settings = tomlDocument.get<Config.Settings>("settings")
    val users = tomlDocument.get<List<User>>("user")

    // You can also access properties on objects inside lists
    val userNames = tomlDocument["user", "name"] // <- returns listOf("Alice", "Bob")

    // Need to remap some names between your config file and your model types?
    data class RemappedConfig(val users: List<User>) {
        data class User(val userName: String, val userSecret: String)
    }
    val remappingDecoder = TomlDecoder.default
        .withMapping<RemappedConfig>("user" to "users")
        .withMapping<RemappedConfig.User>("name" to "userName", "password" to "userSecret")
    val remappedConfig = tomlDocument.decode<RemappedConfig>(remappingDecoder)

    // You can also use entirely custom decoder functions
    val censoringDecoder = TomlDecoder.default.with { it: TomlValue.String -> 
        if (it.value in listOfBadWords) {
            // We don't allow any swearing in our strings!
            it.value.map { '*' }.joinToString("")
        } else {
            it.value
        }
    }
    val censoredConfig = tomlDocument.decode<Config>(censoringDecoder)
}

For more detailed information, see the API documentation.

Alternatives

Why should you use 4koma? Maybe you shouldn't! When it comes to TOML libraries there are several to choose from. This table compares 4koma with a number of alternatives that (a) can parse TOML, (b) can be reasonably easily used in a Kotlin/JVM project, and (c) have seen at least one new commit in the last four years.

If you'd like your library to be on your list, or it's already there and you believe it's being misrepresented, please open a pull request to rectify the situation.

Feature 4koma KToml konf konfy toml4j tomlj jtoml Night Config Jackson
TOML 1.0 compliant
TOML 0.4 compliant
Inline tables
Table arrays
Date/time literals
Easy property access¹
Decodes to Kotlin types
...without extra boilerplate²
...without modification to type
Type-safe generic decoding³
Kotlin multiplatform
Serialization
Online API docs
Small and lean⁴
Everything but the kitchen sink⁵

(¹) Individual properties can be accessed by means of parsedConfig.get("foo.bar") or similar, without requiring the entire document to be decoded into some model type.

(²) The library does not require annotations or other modifications to existing code in order to support decoding to complex model types.

(³) The library does not rely on type-erased JVM generics for decoding to complex model types.

(⁴) The library focuses on reading/writing/processing TOML and does not contain any "unnecessary" features unrelated to that scope.

(⁵) The library aims to provide a comprehensive configuration platform, with support for multiple configuration file formats and all sorts of associated bells and whistles.

Comments
  • How to control whether to generate inline list/map or not?

    How to control whether to generate inline list/map or not?

    My data classes:

    data class MetadataDetailDto(
        val authors: List<String>,
        val collections: Map<String, Map<String, ChapterMetadataDto>>,
    )
    data class ChapterMetadataDto(
        val name: String,
        val title: String,
    )
    

    I would like to generate files like this:

    authors = [ "author1",  "author2"]
    
    [collections.collection1]
    chapter1 = {name = "name", title = "title"}
    

    But it generates this:

    [[authors]]
     = "author1"
    
    [[authors]]
     = "author2"
    
    [collections]
    collection1.chapter1.name = "name"
    collection1.chapter1.title = "title"
    

    So is there a way to control whether to generate inline list/map or not?

    opened by FishHawk 5
  • Support for optional data class parameters, tests for null encoding in data classes

    Support for optional data class parameters, tests for null encoding in data classes

    • Added support for optional data class parameters (default arguments) - allows specifying default values per-field rather than per-type
    • Improved exception thrown when unknown value/target pair is encountered
    • Changed to Any? for parameter decoding to better reflect how decoders can decode to null (though I think it is unchecked at compile-time and doesn't complain with Any)
    • Added tests for the above
    opened by comp500 3
  • Fix problem with private members.

    Fix problem with private members.

    The existing code encodes all the properties of a data class even ones not in the primary constructor but only ever uses the primary constructor. Any private properties cause this code to fail as we do not have access to them (the isAccessible trick doesn't work on private properties that do not have a backing store).

    This changes the code to only encode the properties of the primary constructor's parameters. As data classes only have property parameters in the primary constructor, this is sufficient.

    As part of reading the values the isAccessible flag is adjusted to make the values accessible and now the logic resets the isAccessible flag to its original value after processing.

    Also added a check for IllegalAccessException that displays the parameter that caused the problem to help with debugging in the future. In theory this won't happen, but if something changes in how properties are handled in the future this should help identify the issue.

    opened by jlkeesey 2
  • Data classes with private properties not handled by encoding

    Data classes with private properties not handled by encoding

    If you have a data class with a private field and use it in encoding (like in decodeWithDefaults()) it will fail with an IllegalAccessException. This is true whether the property has a backing field or not. The below code reproduces this problem. If the commented out line is uncommented encoding of the default value will fail. I don't know if this never came up or something changed in the way that Kotlin handles properties but it fails under the more recent Kotlins. I tested with under Kotlin v1.6.21.

    In checking the code I see that the encode() method tries to encode all properties of the data class. However, the decode() process only ever uses the primary constructor so encoding any value not used in the constructor is unnecessary as the value will not be used.

    I have a change which fixes this by only encoding the primary constructor properties. I will submit the PR as well.

    import cc.ekblad.toml.model.TomlValue
    import cc.ekblad.toml.serialization.from
    import cc.ekblad.toml.tomlMapper
    
    data class Config(
        val flag: Boolean = true,
        val text: String = "A Test",
    ) {
        // If the next line is uncommented, decode fails
        // private val combined: String = "$text $flag"
    }
    
    fun main() {
        val mapper = tomlMapper {}
        mapper.decodeWithDefaults(Config(), TomlValue.from(""))
    }
    
    opened by jlkeesey 2
  • TomlMapper chaining/delegation

    TomlMapper chaining/delegation

    I'd like to structure the mappers for my types in a bottom-up way, rather than specifying everything from the top level, and pass various context data down. This is the sort of thing I have currently:

    data class IndexFileLoc(
    	val file: PackwizPath,
    	val hashFormat: String,
    	val hash: String,
    ) {
    	companion object {
    		fun mapper(base: PackwizPath.Base) = tomlMapper {
    			mapping<IndexFileLoc>("hash-format" to "hashFormat")
    			val pathMapper = PackwizPath.mapper(base)
    			decoder { it: TomlValue.String -> pathMapper.decode<PackwizPath>(it) }
    			encoder { it: PackwizPath -> pathMapper.encode(it) }
    		}
    	}
    }
    

    It'd be great if there was a cleaner way to handle this, such as a delegate method that specifies a mapper to delegate mapping of a given type to (or infer from the types encoders/decoders/mappings are specified for?)

    opened by comp500 2
  • Comments are not allowed to contain newlines

    Comments are not allowed to contain newlines

    Comments are not allowed to contain newlines or carriage returns. Try saving a file with these contents:

    # This file contains the configuration for all items.
    # It is highly recommended to edit this in-game.
    

    then parsing it using this code:

    TomlValue.from(itemConfigurationPath)
    

    will result in this error:

    cc.ekblad.toml.model.TomlException$ParseError: toml parse error, on line 1: disallowed character(s) encountered: 13
    	at cc.ekblad.toml.serialization.TomlParserAdapterKt.throwOnBadChar(TomlParserAdapter.kt:181) ~[4koma-1.0.1.jar:?]
    	at cc.ekblad.toml.serialization.TomlParserAdapterKt.extractExpression(TomlParserAdapter.kt:21) ~[4koma-1.0.1.jar:?]
    	at cc.ekblad.toml.serialization.TomlParserAdapterKt.extractDocument(TomlParserAdapter.kt:15) ~[4koma-1.0.1.jar:?]
    	at cc.ekblad.toml.serialization.TomlDeserializerKt.from(TomlDeserializer.kt:51) ~[4koma-1.0.1.jar:?]
    	at cc.ekblad.toml.serialization.TomlDeserializerKt.from(TomlDeserializer.kt:36) ~[4koma-1.0.1.jar:?]
    

    Note: I am on Windows 10.

    opened by Sculas 2
  • Only depend on antlr4-runtime at runtime

    Only depend on antlr4-runtime at runtime

    By default, the Gradle ANTLR plugin depends on the full ANTLR4 binary, which significantly bloats the dependency size where only the ANTLR runtime is required - see https://github.com/gradle/gradle/issues/820. This PR removes the ANTLR dependency from the api configuration used for Maven repository POMs, and adds a dependency on antlr4-runtime.

    opened by comp500 1
  • Each error should be its own subtype

    Each error should be its own subtype

    It is reasonable to rewrite error messages to whatever users find more understandable (e.g. less technical jargon, add use-case recommendations, translate to a different language). Catching DecodingError with a string description is not friendly to that, because descriptions can be revised in future changes. Imo the cleanest solution is to subclass. Maybe something like this:

    sealed class DecodingError(params: Params): TomlException() {
        internal data class Params (
            val reason: String,
            val sourceValue: TomlValue,
            val targetType: KType,
            val cause: Throwable? = null
        )
        val reason = params.reason
        val sourceValue = params.sourceValue
        val targetType = params.targetType
        override val cause: Throwable? = params.cause
    }
    
    class NoValueForNonNullableParameter internal constructor(params: Params): DecodingError(params)
    
    ....
        throw NoValueForNonNullableParameter(DecodingError.Params(
            "no value found for non-nullable parameter '${constructorParameter.name}'",
            tomlMap,
            kType
            ))
    
    opened by edgarsi 0
  • Serializer quoting keys with underscores

    Serializer quoting keys with underscores

    Underscores are valid without quotations but it seems that the serializer is forcing quotes for any key with an underscore.

    Example: 'some_key' = true when some_key = true is perfectly valid.

    opened by Joshua-F 0
  • 4koma outputs invalid TOML for `key = [

    4koma outputs invalid TOML for `key = [ "foo" ]` on top level

    #2 is both a bug report and a feature request. This issue is about the bug part (4koma generates non-TOML output), and #2 is about the feature request.

    tl;dr 4koma tries to serialize all top level key = [ list elements here ] pairs as array tables. This obviously doesn't work if any of the elements in the list are not maps.

    My data classes:

    data class MetadataDetailDto(
        val authors: List<String>,
        val collections: Map<String, Map<String, ChapterMetadataDto>>,
    )
    data class ChapterMetadataDto(
        val name: String,
        val title: String,
    )
    

    I would like to generate files like this:

    authors = [ "author1",  "author2"]
    
    [collections.collection1]
    chapter1 = {name = "name", title = "title"}
    

    But it generates this:

    [[authors]]
     = "author1"
    
    [[authors]]
     = "author2"
    
    [collections]
    collection1.chapter1.name = "name"
    collection1.chapter1.title = "title"
    
    opened by valderman 0
  • Toml Parse Error with seemingly valid .toml file

    Toml Parse Error with seemingly valid .toml file

    Hello! Im encountering a strange error, and after about an hour of attempting to fix it, have gotten nowhere. The code im running is below aswell as the entire error message. This issue also happens with decodeWithDefaults.

            val tomlMapper = tomlMapper {}
    
            val tomlFile = File(Bukkit.getServer().pluginManager.getPlugin("DawnPlugin").dataFolder, "config.toml")
            if(!tomlFile.exists()) {
                tomlFile.createNewFile()
            }
            val tomlFilePath = tomlFile.absolutePath
    
            tomlMapper.decode<Config>(tomlFilePath)
            println(config)
            
            //CONFIG CLASS
            
            data class Config(
              val messages: Messages,
             ) {
                data class Messages(val joinMessage: String, val leaveMessage: String, val chatFormat: String)
             }
    
            val defaultConfig = Config(
               messages = Config.Messages(
                 joinMessage = "<green>[+] %playerName%",
                leaveMessage = "<red>[-] %playerName%",
                chatFormat = "%displayName% : %message%"
               )
             )
    

    using this produces the error message below:

    cc.ekblad.toml.model.TomlException$ParseError: toml parse error, on line 1: token recognition error at: ':'
    	at cc.ekblad.toml.serialization.TomlErrorListener.syntaxError(TomlErrorListener.kt:21) ~[?:?]
    	at org.antlr.v4.runtime.ProxyErrorListener.syntaxError(ProxyErrorListener.java:41) ~[?:?]
    	at org.antlr.v4.runtime.Lexer.notifyListeners(Lexer.java:364) ~[?:?]
    	at org.antlr.v4.runtime.Lexer.nextToken(Lexer.java:144) ~[?:?]
    	at org.antlr.v4.runtime.BufferedTokenStream.fetch(BufferedTokenStream.java:169) ~[?:?]
    	at org.antlr.v4.runtime.BufferedTokenStream.sync(BufferedTokenStream.java:152) ~[?:?]
    	at org.antlr.v4.runtime.BufferedTokenStream.consume(BufferedTokenStream.java:136) ~[?:?]
    	at org.antlr.v4.runtime.atn.ParserATNSimulator.execATN(ParserATNSimulator.java:537) ~[?:?]
    	at org.antlr.v4.runtime.atn.ParserATNSimulator.adaptivePredict(ParserATNSimulator.java:393) ~[?:?]
    	at cc.ekblad.toml.parser.TomlParser.key(TomlParser.java:378) ~[?:?]
    	at cc.ekblad.toml.parser.TomlParser.key_value(TomlParser.java:333) ~[?:?]
    	at cc.ekblad.toml.parser.TomlParser.expression(TomlParser.java:221) ~[?:?]
    	at cc.ekblad.toml.parser.TomlParser.document(TomlParser.java:143) ~[?:?]
    	at cc.ekblad.toml.serialization.TomlDeserializerKt.from(TomlDeserializer.kt:49) ~[?:?]
    	at cc.ekblad.toml.serialization.TomlDeserializerKt.from(TomlDeserializer.kt:20) ~[?:?]
    	at me.ders.Main.onEnable(Main.kt:59) ~[?:?]
    	at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:321) ~[spigot-1.8.9.jar:git-Spigot-21fe707-741a1bd]
    	at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:340) [spigot-1.8.9.jar:git-Spigot-21fe707-741a1bd]
    	at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:405) [spigot-1.8.9.jar:git-Spigot-21fe707-741a1bd]
    	at org.bukkit.craftbukkit.v1_8_R3.CraftServer.loadPlugin(CraftServer.java:357) [spigot-1.8.9.jar:git-Spigot-21fe707-741a1bd]
    	at org.bukkit.craftbukkit.v1_8_R3.CraftServer.enablePlugins(CraftServer.java:317) [spigot-1.8.9.jar:git-Spigot-21fe707-741a1bd]
    	at net.minecraft.server.v1_8_R3.MinecraftServer.s(MinecraftServer.java:414) [spigot-1.8.9.jar:git-Spigot-21fe707-741a1bd]
    	at net.minecraft.server.v1_8_R3.MinecraftServer.k(MinecraftServer.java:378) [spigot-1.8.9.jar:git-Spigot-21fe707-741a1bd]
    	at net.minecraft.server.v1_8_R3.MinecraftServer.a(MinecraftServer.java:333) [spigot-1.8.9.jar:git-Spigot-21fe707-741a1bd]
    	at net.minecraft.server.v1_8_R3.DedicatedServer.init(DedicatedServer.java:263) [spigot-1.8.9.jar:git-Spigot-21fe707-741a1bd]
    	at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:525) [spigot-1.8.9.jar:git-Spigot-21fe707-741a1bd]
    	at java.lang.Thread.run(Thread.java:750) [?:1.8.0_352]
    Caused by: org.antlr.v4.runtime.LexerNoViableAltException
    	at org.antlr.v4.runtime.atn.LexerATNSimulator.failOrAccept(LexerATNSimulator.java:309) ~[?:?]
    	at org.antlr.v4.runtime.atn.LexerATNSimulator.execATN(LexerATNSimulator.java:230) ~[?:?]
    	at org.antlr.v4.runtime.atn.LexerATNSimulator.match(LexerATNSimulator.java:114) ~[?:?]
    	at org.antlr.v4.runtime.Lexer.nextToken(Lexer.java:141) ~[?:?]
    	... 23 more
    
    [messages]
    joinMessage = "<green>[+] %playerName%"
    leaveMessage = "<red>[-] %playerName%"
    chatFormat = "%displayName% : %message%"
    
    opened by DersWasTaken 2
  • Antlr? seriously :D

    Antlr? seriously :D

    You will have problems with MPP. Probably, it's time to migrate to https://github.com/kotlinx/ast and help them grow 😄

    PS: KToml forever! :) Thank you for mentioning us in your project

    opened by akuleshov7 2
  • Whether to consider support for Java Type parameters?

    Whether to consider support for Java Type parameters?

    KType restricts the work of some Java dynamic proxy frameworks, such as Retrofit.

    Doing so breaks the nature of Type-safe and cause the default functionality to not work, but it does make the framework more flexible.

    But this work is not simple. Gson and Jackson have done a lot of work to support different Type in Java.

    help wanted 
    opened by hushenghao 1
Releases(1.1.0)
  • 1.1.0(Jul 5, 2022)

    What's Changed

    • Fix override order of custom encoders/decoders
    • Support transcoding to/from Lazy<T>
    • Fix decoding of parameterized data classes
    • Support configuration of serialization format
    • Support delegating de/serialization to another mapper
    • Faster creation of TomlMappers
    • Only depend on antlr4-runtime at runtime by @comp500 in https://github.com/valderman/4koma/pull/4
    • Fix problem with private members. by @jlkeesey in https://github.com/valderman/4koma/pull/8
    • Support for optional data class parameters, tests for null encoding in data classes by @comp500 in https://github.com/valderman/4koma/pull/6
    • Run tests on pr by @valderman in https://github.com/valderman/4koma/pull/9
    • Enum support by @valderman in https://github.com/valderman/4koma/pull/10

    New Contributors

    • @comp500 made their first contribution in https://github.com/valderman/4koma/pull/4
    • @jlkeesey made their first contribution in https://github.com/valderman/4koma/pull/8

    Full Changelog: https://github.com/valderman/4koma/compare/1.0.2...1.1.0

    Source code(tar.gz)
    Source code(zip)
  • 1.0.2(Apr 26, 2022)

  • 1.0.1(Apr 19, 2022)

  • 1.0.0(Apr 19, 2022)

    • Added support for default values when decoding TOML documents.
    • Simplified usage by making the newly introduced TomlMapper, with extensions, the main entry point of the library and hiding away the details of TomlValue, etc. until you really need it.
    • Added TomlMapper.atomicallyEncodeTo method to atomically overwrite files with new TOML documents.
    • Simplified package structure. This should be the last package structure change for quite some time.

    Full Changelog: https://github.com/valderman/4koma/compare/0.4.2...1.0.0

    Source code(tar.gz)
    Source code(zip)
  • 0.4.2(Feb 10, 2022)

  • 0.4.1(Dec 21, 2021)

  • 0.4.0(Dec 17, 2021)

    • Add serialization support
    • Allow decoding to nullable types
    • Throw early errors if you try to register a custom mapping which obviously won't work
    • Minor bugfixes WRT custom decoder mappings
    • Reorganize everything into subpackages
    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Nov 19, 2021)

    Changelog:

    • Support custom TOML decoders
    • Support easy remapping between TOML values and properties of Kotlin model types
    • Improved docs and test suite
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Nov 11, 2021)

    Changelog:

    • Create javadoc JAR as part of build.
    • Allow converting TOML value to any class with a primary constructor.
    • Make TomlErrorListener internal.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Nov 11, 2021)

    Initial release: full support for parsing TOML 1.0, traversing the resulting data structure, and converting it into some common Kotlin data types, including custom data classes.

    Source code(tar.gz)
    Source code(zip)
Owner
Anton Ekblad
Functional programmer, computer science PhD, magical girl.
Anton Ekblad
Run Kotlin/JS libraries in Kotlin/JVM and Kotlin/Native programs

Zipline This library streamlines using Kotlin/JS libraries from Kotlin/JVM and Kotlin/Native programs. It makes it possible to do continuous deploymen

Cash App 1.5k Dec 30, 2022
A somewhat copy past of Jetbrain's code from the kotlin plugin repo to make it humanly possible to test Intellij IDEA kotlin plugins that work on kotlin

A somewhat copy past of Jetbrain's code from the kotlin plugin repo to make it humanly possible to test Intellij IDEA kotlin plugins that work on kotlin

common sense OSS 0 Jan 20, 2022
Real life Kotlin Multiplatform project with an iOS application developed in Swift with SwiftUI, an Android application developed in Kotlin with Jetpack Compose and a backed in Kotlin hosted on AppEngine.

Conferences4Hall Real life Kotlin Multiplatform project with an iOS application developed in Swift with SwiftUI, an Android application developed in K

Gérard Paligot 98 Dec 15, 2022
[Android Library] A SharedPreferences helper library to save and fetch the values easily.

Preference Helper A SharedPreferences helper library to save and fetch the values easily. Featured in Use in your project Add this to your module's bu

Naveen T P 13 Apr 4, 2020
Kotlin library for Android

KAndroid Kotlin library for Android providing useful extensions to eliminate boilerplate code in Android SDK and focus on productivity. Download Downl

Paweł Gajda 890 Nov 13, 2022
A Kotlin DSL wrapper around the mikepenz/MaterialDrawer library.

MaterialDrawerKt Create navigation drawers in your Activities and Fragments without having to write any XML, in pure Kotlin code, with access to all t

Márton Braun 517 Nov 19, 2022
🔓 Kotlin version of the popular google/easypermissions wrapper library to simplify basic system permissions logic on Android M or higher.

EasyPermissions-ktx Kotlin version of the popular googlesample/easypermissions wrapper library to simplify basic system permissions logic on Android M

Madalin Valceleanu 326 Dec 23, 2022
Android Spinner Dialog Library supported on both Java and Kotlin, Use for single or multi selection of choice

SpinnerDialog Android Spinner Dialog Library, Use for single or multi selection of choice Android UI Download To include SpinnerDialog in your project

Hamza Khan 55 Sep 15, 2022
A Kotlin library for reactive and boilerplate-free SharedPreferences in Android

KPreferences A Kotlin library for reactive and boilerplate-free Shared Preferences in Android. With KPreferences you can use Kotlin's marvelous delega

Mohamad Amin Mohamadi 19 Dec 16, 2020
AbstractMvp 0.8 0.0 Kotlin is a library that provides abstract components for MVP architecture realization, with problems solutions that are exist in classic MVP.

MinSDK 14+ AbstractMvp AbstractMvp is a library that provides abstract components for MVP architecture realization, with problems solutions that are e

Robert 12 Apr 5, 2022
The most complete and powerful data-binding library and persistence infra for Kotlin 1.3, Android & Splitties Views DSL, JavaFX & TornadoFX, JSON, JDBC & SQLite, SharedPreferences.

Lychee (ex. reactive-properties) Lychee is a library to rule all the data. ToC Approach to declaring data Properties Other data-binding libraries Prop

Mike 112 Dec 9, 2022
A Bluetooth kotlin multiplatform "Cross-Platform" library for iOS and Android

Blue-Falcon A Bluetooth "Cross Platform" Kotlin Multiplatform library for iOS, Android, MacOS, Raspberry Pi and Javascript. Bluetooth in general has t

Andrew Reed 220 Dec 28, 2022
A lightweight cache library written in Kotlin

[NEW] Released to Maven Central: 'com.github.yundom:kache:1.x.x' Kache A runtime in-memory cache. Installation Put this in your build.gradle implemen

Dennis 22 Nov 19, 2022
A Kotlin Android library for content provider queries with reactive streams and coroutines.

Pickpocket An Android library for content provider queries with reactive streams and coroutines. Calendar Contacts SMS MMS Files/Media Call Log Bookma

Chris Basinger 27 Nov 14, 2022
A Kotlin Android library for heuristics evasion that prevents your code from being tested.

EvadeMe An Android library for heuristics evasion that prevents your code from being tested. User Instructions Add the maven repository to your projec

Chris Basinger 29 Dec 26, 2022
Easy lightweight SharedPreferences library for Android in Kotlin using delegated properties

Easy lightweight SharedPreferences library for Android in Kotlin using delegated properties Idea Delegated properties in Kotlin allow you to execute a

null 25 Dec 27, 2022
Android AsyncTask wrapper library, written in Kotlin

KillerTask This is a Kotlin Android library to create async background tasks. Inspired by TinyTask, but more beautiful and easy to use for Kotlin Andr

Inaka 26 Oct 3, 2022
A Kotlin work manager library for Android with progress notifications and Hilt support.

Boot Laces A kotlin work manager library for Android that includes notifications and Hilt support. User Instructions Add the JitPack repository to you

Chris Basinger 35 Oct 8, 2022
Stateful is a Kotlin library which makes Android application development faster and easier.

Stateful Stateful is a Kotlin library which makes Android application development faster and easier. It helps you delete all the boilerplate code for

PicsArt 67 Oct 3, 2022