package net.sergeych.bintools import kotlinx.browser.localStorage import net.sergeych.mp_tools.decodeBase64Compact import net.sergeych.mp_tools.encodeToBase64Compact import org.w3c.dom.Storage import org.w3c.dom.set /** * Create per-platform default named storage. * * - In the browser, it uses the `Window.localStorage` prefixing items * by a string containing the [name] * * - In the JVM environment it uses folder-based storage on the file system. The name * is considered to be a folder name (the whole path which will be automatically created) * using the following rules: * - when the name starts with slash (`/`) it is treated as an absolute path to a folder * - when the name contains slash, it is considered to be a relative folder to the * `User.home` directory, like "`~/`" on unix systems. * - otherwise, the folder will be created in "`~/.local_storage`" parent directory * (which also will be created if needed). * * - For the native platorms it is not yet implemented (but will be soon). * * See [DataKVStorage] and [DataProvider] to implement a KVStorage on filesystems and like, * and `FileDataProvider` class on JVM target. */ actual fun defaultNamedStorage(name: String): KVStorage = BrowserKVStorage(name, localStorage) /** * Default KV storage in browser. Use if with `localStorage` or `sessionStorage`. It uses * prefix for storage values not to collide with other data, beware of it. */ class BrowserKVStorage(keyPrefix: String, private val bst: Storage) : KVStorage { private val prefix = "$keyPrefix:" fun k(key: String) = "$prefix$key" override fun get(key: String): ByteArray? { return bst.getItem(k(key))?.decodeBase64Compact() } override fun set(key: String, value: ByteArray?) { val corrected = k(key) if (value == null) bst.removeItem(corrected) else bst.set(corrected, value.encodeToBase64Compact()) } override val keys: Set get() { val kk = mutableListOf() for (i in 0 until bst.length) { val k = bst.key(i) ?: break if( k.startsWith(prefix)) { kk += k.substring(prefix.length) } } return kk.toSet() } }