Skip to content

Commit

Permalink
support Kotlin/Wasm for apollo-adapters (#5803)
Browse files Browse the repository at this point in the history
* support Kotlin/Wasm for apollo-adaptors

* Share JS and Wasm tests

---------

Co-authored-by: John O'Reilly <john@neat.no>
Co-authored-by: Martin Bonnin <martin@mbonnin.net>
  • Loading branch information
3 people authored Apr 15, 2024
1 parent 0a20ef1 commit a5f3d9e
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 2 deletions.
9 changes: 8 additions & 1 deletion build-logic/src/main/kotlin/Mpp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,14 @@ private fun KotlinMultiplatformExtension.configureSourceSetGraph() {
withAndroidTarget()
}
}
group("js")
group("jsCommon") {
group("js") {
withJs()
}
group("wasmJs") {
withWasmJs()
}
}
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion libraries/apollo-adapters/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
apolloLibrary(
namespace = "com.apollographql.apollo3.adapter",
withLinux = false,
withWasm = false
withWasm = true
)

kotlin {
Expand All @@ -22,5 +22,10 @@ kotlin {
implementation(npm("big.js", "5.2.2"))
}
}
findByName("wasmJsMain")?.apply {
dependencies {
implementation(npm("big.js", "5.2.2"))
}
}
}
}
103 changes: 103 additions & 0 deletions libraries/apollo-adapters/src/wasmJsMain/kotlin/adapter/BigDecimal.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.apollographql.apollo3.adapter

@JsModule("big.js")
internal external fun Big(raw: JsAny): Big

@JsName("Number")
internal external fun jsNumber(raw: Big): JsNumber

internal external class Big {
fun plus(other: Big): Big
fun minus(other: Big): Big
fun times(other: Big): Big
fun div(other: Big): Big
fun cmp(other: Big): Int
fun eq(other: Big): Boolean
fun round(dp: Int, rm: Int): Big
}

actual class BigDecimal {
internal val raw: Big

internal constructor(raw: Big) {
this.raw = raw
}

constructor() : this(raw = Big())

actual constructor(strVal: String) : this(raw = Big(strVal.toJsString()))

actual constructor(doubleVal: Double) {
check(!doubleVal.isNaN() && !doubleVal.isInfinite())
raw = Big(doubleVal.toJsNumber())
}

actual constructor(intVal: Int) : this(raw = Big(intVal.toJsNumber()))

// JS does not support 64-bit integer natively.
actual constructor(longVal: Long) : this(raw = Big(longVal.toString().toJsString()))

actual fun add(augend: BigDecimal): BigDecimal = BigDecimal(raw = raw.plus(augend.raw))

actual fun subtract(subtrahend: BigDecimal): BigDecimal = BigDecimal(raw = raw.minus(subtrahend.raw))

actual fun multiply(multiplicand: BigDecimal): BigDecimal = BigDecimal(raw = raw.times(multiplicand.raw))

actual fun divide(divisor: BigDecimal): BigDecimal = BigDecimal(raw = raw.div(divisor.raw))

actual fun negate(): BigDecimal = BigDecimal().subtract(this)

actual fun signum(): Int {
return raw.cmp(Big())
}

fun toInt(): Int {
return jsNumber(raw).toInt()
}

fun toLong(): Long {
// JSNumber is double precision, so it cannot exactly represent 64-bit `Long`.
return toString().toLong()
}

fun toShort(): Short {
return jsNumber(raw).toInt().toShort()
}

fun toByte(): Byte {
return jsNumber(raw).toInt().toByte()
}

fun toChar(): Char {
return jsNumber(raw).toInt().toChar()
}

fun toDouble(): Double {
return jsNumber(raw).toDouble()
}

fun toFloat(): Float {
return jsNumber(raw).toDouble().toFloat()
}

override fun equals(other: Any?): Boolean {
if (other is BigDecimal) {
return raw.eq(other.raw)
}
return false
}

override fun hashCode(): Int = raw.toString().hashCode()

override fun toString(): String = raw.toString()
}

actual fun BigDecimal.toNumber(): Number {
val rounded = raw.round(0, 0)

return if (raw.minus(rounded).eq(Big())) {
toLong()
} else {
toDouble()
}
}

0 comments on commit a5f3d9e

Please sign in to comment.