diff options
Diffstat (limited to 'common/src/commonMain/kotlin/net/taler/lib/common')
4 files changed, 51 insertions, 47 deletions
diff --git a/common/src/commonMain/kotlin/net/taler/lib/common/Amount.kt b/common/src/commonMain/kotlin/net/taler/lib/common/Amount.kt index 213abb3..7635f8c 100644 --- a/common/src/commonMain/kotlin/net/taler/lib/common/Amount.kt +++ b/common/src/commonMain/kotlin/net/taler/lib/common/Amount.kt @@ -16,20 +16,20 @@ package net.taler.lib.common -import kotlinx.serialization.Decoder -import kotlinx.serialization.Encoder import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import kotlin.math.floor import kotlin.math.pow import kotlin.math.roundToInt -class AmountParserException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) -class AmountOverflowException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) +public class AmountParserException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) +public class AmountOverflowException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) @Serializable(with = KotlinXAmountSerializer::class) -data class Amount( +public data class Amount( /** * name of the currency using either a three-character ISO 4217 currency code, * or a regional currency identifier starting with a "*" followed by at most 10 characters. @@ -53,26 +53,26 @@ data class Amount( val fraction: Int ) : Comparable<Amount> { - companion object { + public companion object { private const val FRACTIONAL_BASE: Int = 100000000 // 1e8 private val REGEX_CURRENCY = Regex("""^[-_*A-Za-z0-9]{1,12}$""") - val MAX_VALUE = 2.0.pow(52).toLong() + public val MAX_VALUE: Long = 2.0.pow(52).toLong() private const val MAX_FRACTION_LENGTH = 8 - const val MAX_FRACTION = 99_999_999 + public const val MAX_FRACTION: Int = 99_999_999 - fun zero(currency: String): Amount { + public fun zero(currency: String): Amount { return Amount(checkCurrency(currency), 0, 0) } - fun fromJSONString(str: String): Amount { + public fun fromJSONString(str: String): Amount { val split = str.split(":") if (split.size != 2) throw AmountParserException("Invalid Amount Format") return fromString(split[0], split[1]) } - fun fromString(currency: String, str: String): Amount { + public fun fromString(currency: String, str: String): Amount { // value val valueSplit = str.split(".") val value = checkValue(valueSplit[0].toLongOrNull()) @@ -89,8 +89,8 @@ data class Amount( return Amount(checkCurrency(currency), value, fraction) } - fun min(currency: String): Amount = Amount(currency, 0, 1) - fun max(currency: String): Amount = Amount(currency, MAX_VALUE, MAX_FRACTION) + public fun min(currency: String): Amount = Amount(currency, 0, 1) + public fun max(currency: String): Amount = Amount(currency, MAX_VALUE, MAX_FRACTION) internal fun checkCurrency(currency: String): String { @@ -113,7 +113,7 @@ data class Amount( } - val amountStr: String + public val amountStr: String get() = if (fraction == 0) "$value" else { var f = fraction var fractionStr = "" @@ -124,7 +124,7 @@ data class Amount( "$value.$fractionStr" } - operator fun plus(other: Amount): Amount { + public operator fun plus(other: Amount): Amount { check(currency == other.currency) { "Can only subtract from same currency" } val resultValue = value + other.value + floor((fraction + other.fraction).toDouble() / FRACTIONAL_BASE).toLong() if (resultValue > MAX_VALUE) @@ -133,7 +133,7 @@ data class Amount( return Amount(currency, resultValue, resultFraction) } - operator fun times(factor: Int): Amount { + public operator fun times(factor: Int): Amount { // TODO consider replacing with a faster implementation if (factor == 0) return zero(currency) var result = this @@ -141,7 +141,7 @@ data class Amount( return result } - operator fun minus(other: Amount): Amount { + public operator fun minus(other: Amount): Amount { check(currency == other.currency) { "Can only subtract from same currency" } var resultValue = value var resultFraction = fraction @@ -159,11 +159,11 @@ data class Amount( return Amount(currency, resultValue, resultFraction) } - fun isZero(): Boolean { + public fun isZero(): Boolean { return value == 0L && fraction == 0 } - fun toJSONString(): String { + public fun toJSONString(): String { return "$currency:$amountStr" } @@ -186,8 +186,9 @@ data class Amount( } +@Suppress("EXPERIMENTAL_API_USAGE") @Serializer(forClass = Amount::class) -object KotlinXAmountSerializer: KSerializer<Amount> { +internal object KotlinXAmountSerializer : KSerializer<Amount> { override fun serialize(encoder: Encoder, value: Amount) { encoder.encodeString(value.toJSONString()) } diff --git a/common/src/commonMain/kotlin/net/taler/lib/common/TalerUri.kt b/common/src/commonMain/kotlin/net/taler/lib/common/TalerUri.kt index 8255dc0..724820e 100644 --- a/common/src/commonMain/kotlin/net/taler/lib/common/TalerUri.kt +++ b/common/src/commonMain/kotlin/net/taler/lib/common/TalerUri.kt @@ -16,7 +16,7 @@ package net.taler.lib.common -object TalerUri { +public object TalerUri { private const val SCHEME = "taler://" private const val SCHEME_INSECURE = "taler+http://" @@ -25,7 +25,7 @@ object TalerUri { private const val AUTHORITY_REFUND = "refund" private const val AUTHORITY_TIP = "tip" - data class WithdrawUriResult( + public data class WithdrawUriResult( val bankIntegrationApiBaseUrl: String, val withdrawalOperationId: String ) @@ -33,7 +33,7 @@ object TalerUri { /** * Parses a withdraw URI and returns a bank status URL or null if the URI was invalid. */ - fun parseWithdrawUri(uri: String): WithdrawUriResult? { + public fun parseWithdrawUri(uri: String): WithdrawUriResult? { val (resultScheme, prefix) = when { uri.startsWith(SCHEME, ignoreCase = true) -> { Pair("https://", "${SCHEME}${AUTHORITY_WITHDRAW}/") diff --git a/common/src/commonMain/kotlin/net/taler/lib/common/Time.kt b/common/src/commonMain/kotlin/net/taler/lib/common/Time.kt index 0e5e07c..704a91a 100644 --- a/common/src/commonMain/kotlin/net/taler/lib/common/Time.kt +++ b/common/src/commonMain/kotlin/net/taler/lib/common/Time.kt @@ -24,38 +24,40 @@ import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.JsonTransformingSerializer import kotlinx.serialization.json.contentOrNull +import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.longOrNull import net.taler.lib.common.Duration.Companion.FOREVER import kotlin.math.max @Serializable -data class Timestamp( +public data class Timestamp( @SerialName("t_ms") @Serializable(NeverSerializer::class) val ms: Long ) : Comparable<Timestamp> { - companion object { - const val NEVER: Long = -1 - fun now(): Timestamp = Timestamp(DateTime.nowUnixLong()) + public companion object { + private const val NEVER: Long = -1 + public fun now(): Timestamp = Timestamp(DateTime.nowUnixLong()) + public fun never(): Timestamp = Timestamp(NEVER) } /** * Returns a copy of this [Timestamp] rounded to seconds. */ - fun truncateSeconds(): Timestamp { + public fun truncateSeconds(): Timestamp { if (ms == NEVER) return Timestamp(ms) return Timestamp((ms / 1000L) * 1000L) } - operator fun minus(other: Timestamp): Duration = when { + public operator fun minus(other: Timestamp): Duration = when { ms == NEVER -> Duration(FOREVER) other.ms == NEVER -> throw Error("Invalid argument for timestamp comparision") ms < other.ms -> Duration(0) else -> Duration(ms - other.ms) } - operator fun minus(other: Duration): Timestamp = when { + public operator fun minus(other: Duration): Timestamp = when { ms == NEVER -> this other.ms == FOREVER -> Timestamp(0) else -> Timestamp(max(0, ms - other.ms)) @@ -74,7 +76,7 @@ data class Timestamp( } @Serializable -data class Duration( +public data class Duration( /** * Duration in milliseconds. */ @@ -82,24 +84,25 @@ data class Duration( @Serializable(ForeverSerializer::class) val ms: Long ) { - companion object { - const val FOREVER: Long = -1 + public companion object { + internal const val FOREVER: Long = -1 + public fun forever(): Duration = Duration(FOREVER) } } -abstract class MinusOneSerializer(private val keyword: String) : - JsonTransformingSerializer<Long>(Long.serializer(), keyword) { +internal abstract class MinusOneSerializer(private val keyword: String) : + JsonTransformingSerializer<Long>(Long.serializer()) { - override fun readTransform(element: JsonElement): JsonElement { - return if (element.contentOrNull == keyword) return JsonPrimitive(-1) - else super.readTransform(element) + override fun transformDeserialize(element: JsonElement): JsonElement { + return if (element.jsonPrimitive.contentOrNull == keyword) return JsonPrimitive(-1) + else super.transformDeserialize(element) } - override fun writeTransform(element: JsonElement): JsonElement { - return if (element.longOrNull == -1L) return JsonPrimitive(keyword) + override fun transformSerialize(element: JsonElement): JsonElement { + return if (element.jsonPrimitive.longOrNull == -1L) return JsonPrimitive(keyword) else element } } -object NeverSerializer : MinusOneSerializer("never") -object ForeverSerializer : MinusOneSerializer("forever") +internal object NeverSerializer : MinusOneSerializer("never") +internal object ForeverSerializer : MinusOneSerializer("forever") diff --git a/common/src/commonMain/kotlin/net/taler/lib/common/Version.kt b/common/src/commonMain/kotlin/net/taler/lib/common/Version.kt index d3f0ad2..c4dc53d 100644 --- a/common/src/commonMain/kotlin/net/taler/lib/common/Version.kt +++ b/common/src/commonMain/kotlin/net/taler/lib/common/Version.kt @@ -22,13 +22,13 @@ import kotlin.math.sign * Semantic versioning, but libtool-style. * See https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html */ -data class Version( +public data class Version( val current: Int, val revision: Int, val age: Int ) { - companion object { - fun parse(v: String): Version? { + public companion object { + public fun parse(v: String): Version? { val elements = v.split(":") if (elements.size != 3) return null val (currentStr, revisionStr, ageStr) = elements @@ -45,7 +45,7 @@ data class Version( * * Returns a [VersionMatchResult] or null if the given version was null. */ - fun compare(other: Version?): VersionMatchResult? { + public fun compare(other: Version?): VersionMatchResult? { if (other == null) return null val compatible = current - age <= other.current && current >= other.current - other.age @@ -56,7 +56,7 @@ data class Version( /** * Result of comparing two libtool versions. */ - data class VersionMatchResult( + public data class VersionMatchResult( /** * Is the first version compatible with the second? */ |