Skip to content

Commit

Permalink
Implement Kotlinx-io (#926)
Browse files Browse the repository at this point in the history
  • Loading branch information
iNoles authored Jul 23, 2024
1 parent 8311446 commit 300690b
Show file tree
Hide file tree
Showing 44 changed files with 886 additions and 810 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.github.kittinunf.forge.Forge
import com.github.kittinunf.forge.core.DeserializedResult
import com.github.kittinunf.forge.core.JSON
import fuel.HttpResponse
import kotlinx.io.readString

public fun <T : Any> HttpResponse.toForge(deserializer: JSON.() -> DeserializedResult<T>): DeserializedResult<T> =
Forge.modelFromJson(body.string(), deserializer)
Forge.modelFromJson(source.readString(), deserializer)
28 changes: 15 additions & 13 deletions fuel-forge-jvm/src/test/kotlin/fuel/forge/FuelForgeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,21 @@ class FuelForgeTest {

@OptIn(ExperimentalOkHttpApi::class)
@Test
fun testForgeResponse() = runBlocking {
val mockWebServer = MockWebServer().apply {
enqueue(MockResponse(body = "{\"userAgent\": \"Fuel\", \"status\": \"OK\"}"))
start()
}
fun testForgeResponse() =
runBlocking {
val mockWebServer =
MockWebServer().apply {
enqueue(MockResponse(body = "{\"userAgent\": \"Fuel\", \"status\": \"OK\"}"))
start()
}

val binUserAgentModel = HttpBinUserAgentModel("Fuel", "OK")
val response = Fuel.get(mockWebServer.url("user-agent").toString())
when (val forge = response.toForge(httpBinUserDeserializer)) {
is Result.Success -> assertEquals(binUserAgentModel, forge.value)
is Result.Failure -> fail(forge.error.localizedMessage)
}
val binUserAgentModel = HttpBinUserAgentModel("Fuel", "OK")
val response = Fuel.get(mockWebServer.url("user-agent").toString())
when (val forge = response.toForge(httpBinUserDeserializer)) {
is Result.Success -> assertEquals(binUserAgentModel, forge.value)
is Result.Failure -> fail(forge.error.localizedMessage)
}

mockWebServer.shutdown()
}
mockWebServer.shutdown()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import com.fasterxml.jackson.module.kotlin.readValue
import com.github.kittinunf.result.Result
import com.github.kittinunf.result.runCatching
import fuel.HttpResponse
import kotlinx.io.readString

public inline fun <reified T : Any> HttpResponse.toJackson(
mapper: ObjectMapper = jacksonObjectMapper()
): Result<T?, Throwable> =
public inline fun <reified T : Any> HttpResponse.toJackson(mapper: ObjectMapper = jacksonObjectMapper()): Result<T?, Throwable> =
runCatching {
mapper.readValue(body.string())
mapper.readValue(source.readString())
}
75 changes: 39 additions & 36 deletions fuel-jackson-jvm/src/test/kotlin/fuel/jackson/FuelJacksonTest.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@file:OptIn(ExperimentalOkHttpApi::class)

package fuel.jackson

import com.fasterxml.jackson.databind.DeserializationFeature
Expand All @@ -16,52 +14,57 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.fail
import org.junit.Test

@ExperimentalOkHttpApi
class FuelJacksonTest {

private val createCustomMapper: ObjectMapper = ObjectMapper().registerKotlinModule()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).apply {
propertyNamingStrategy = PropertyNamingStrategies.SNAKE_CASE
}
private val createCustomMapper: ObjectMapper =
ObjectMapper().registerKotlinModule()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).apply {
propertyNamingStrategy = PropertyNamingStrategies.SNAKE_CASE
}

data class HttpBinUserAgentModel(
val userAgent: String = "",
val http_status: String = ""
)

@Test
fun jacksonTestResponseObject() = runBlocking {
val mockWebServer = MockWebServer().apply {
enqueue(MockResponse(body = "{\"userAgent\": \"Fuel\"}"))
start()
}
fun jacksonTestResponseObject() =
runBlocking {
val mockWebServer =
MockWebServer().apply {
enqueue(MockResponse(body = "{\"userAgent\": \"Fuel\"}"))
start()
}

val response = Fuel.get(mockWebServer.url("user-agent").toString())
val jackson = response.toJackson<HttpBinUserAgentModel>()
jackson.fold({
assertEquals("Fuel", it?.userAgent)
}, {
fail(it.localizedMessage)
})
val response = Fuel.get(mockWebServer.url("user-agent").toString())
val jackson = response.toJackson<HttpBinUserAgentModel>()
jackson.fold({
assertEquals("Fuel", it?.userAgent)
}, {
fail(it.localizedMessage)
})

mockWebServer.shutdown()
}
mockWebServer.shutdown()
}

@Test
fun jacksonTestResponseObjectWithCustomMapper() = runBlocking {
val mockWebServer = MockWebServer().apply {
enqueue(MockResponse(body = "{\"userAgent\": \"Fuel\", \"http_status\": \"OK\"}"))
start()
}
fun jacksonTestResponseObjectWithCustomMapper() =
runBlocking {
val mockWebServer =
MockWebServer().apply {
enqueue(MockResponse(body = "{\"userAgent\": \"Fuel\", \"http_status\": \"OK\"}"))
start()
}

val response = Fuel.get(mockWebServer.url("user-agent").toString())
val jackson = response.toJackson<HttpBinUserAgentModel>(createCustomMapper)
jackson.fold({
assertEquals("", it?.userAgent)
assertEquals("OK", it?.http_status)
}, {
fail(it.localizedMessage)
})
val response = Fuel.get(mockWebServer.url("user-agent").toString())
val jackson = response.toJackson<HttpBinUserAgentModel>(createCustomMapper)
jackson.fold({
assertEquals("", it?.userAgent)
assertEquals("OK", it?.http_status)
}, {
fail(it.localizedMessage)
})

mockWebServer.shutdown()
}
mockWebServer.shutdown()
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package fuel.serialization

import fuel.HttpResponse
import kotlinx.io.Buffer
import kotlinx.io.writeString
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlin.test.Test
Expand All @@ -16,10 +18,12 @@ class FuelKotlinxSerializationTest {

@Test
fun testSerializableResponse() {
val httpResponse = HttpResponse().apply {
statusCode = 200
body = "{\"userAgent\": \"Fuel\"}"
}
val jsonBuffer = Buffer().also { it.writeString("{\"userAgent\": \"Fuel\"}") }
val httpResponse =
HttpResponse().apply {
statusCode = 200
source = jsonBuffer
}
val json = httpResponse.toJson(Json.Default, HttpBinUserAgentModel.serializer())
json.fold({
assertEquals("Fuel", it?.userAgent)
Expand All @@ -30,13 +34,23 @@ class FuelKotlinxSerializationTest {

@Test
fun testSpaceXDetail() {
val httpResponse = HttpResponse().apply {
statusCode = 200
body = "{\"rocket\":\"5e9d0d95eda69973a809d1ec\", \"success\":true,\"details\":\"Second GTO launch for Falcon 9. The USAF evaluated launch data from this flight as part of a separate certification program for SpaceX to qualify to fly U.S. military payloads and found that the Thaicom 6 launch had \\\"unacceptable fuel reserves at engine cutoff of the stage 2 second burnoff\\\"\"}"
}
val jsonBuffer =
Buffer().also {
it.writeString(
"{\"rocket\":\"5e9d0d95eda69973a809d1ec\", \"success\":true,\"details\":\"Second GTO launch for Falcon 9. The USAF evaluated launch data from this flight as part of a separate certification program for SpaceX to qualify to fly U.S. military payloads and found that the Thaicom 6 launch had \\\"unacceptable fuel reserves at engine cutoff of the stage 2 second burnoff\\\"\"}"
)
}
val httpResponse =
HttpResponse().apply {
statusCode = 200
source = jsonBuffer
}
val json = httpResponse.toJson(Json.Default, RocketLaunch.serializer())
json.fold({
assertEquals("Second GTO launch for Falcon 9. The USAF evaluated launch data from this flight as part of a separate certification program for SpaceX to qualify to fly U.S. military payloads and found that the Thaicom 6 launch had \"unacceptable fuel reserves at engine cutoff of the stage 2 second burnoff\"", it?.details)
assertEquals(
"Second GTO launch for Falcon 9. The USAF evaluated launch data from this flight as part of a separate certification program for SpaceX to qualify to fly U.S. military payloads and found that the Thaicom 6 launch had \"unacceptable fuel reserves at engine cutoff of the stage 2 second burnoff\"",
it?.details
)
}, {
fail(it.message)
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package fuel.serialization

import com.github.kittinunf.result.Result
import com.github.kittinunf.result.runCatching
import fuel.HttpResponse
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.io.decodeFromSource

public expect fun <T : Any> HttpResponse.toJson(
@OptIn(ExperimentalSerializationApi::class)
public fun <T : Any> HttpResponse.toJson(
json: Json = Json,
deserializationStrategy: DeserializationStrategy<T>
): Result<T?, Throwable>
): Result<T?, Throwable> =
runCatching {
json.decodeFromSource(source = source, deserializer = deserializationStrategy)
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,42 @@ class FuelKotlinxSerializationTest {
data class HttpBinUserAgentModel(var userAgent: String = "")

@Test
fun testSerializableResponse() = runBlocking {
val mockWebServer = MockWebServer().apply {
enqueue(MockResponse(body = "{\"userAgent\": \"Fuel\"}"))
start()
fun testSerializableResponse() =
runBlocking {
val mockWebServer =
MockWebServer().apply {
enqueue(MockResponse(body = "{\"userAgent\": \"Fuel\"}"))
start()
}

val response = Fuel.get(mockWebServer.url("user-agent").toString())
val json = response.toJson(Json.Default, HttpBinUserAgentModel.serializer())
json.fold({
assertEquals("Fuel", it?.userAgent)
}, {
fail(it.message)
})

mockWebServer.shutdown()
}

val response = Fuel.get(mockWebServer.url("user-agent").toString())
val json = response.toJson(Json.Default, HttpBinUserAgentModel.serializer())
json.fold({
assertEquals("Fuel", it?.userAgent)
}, {
fail(it.message)
})

mockWebServer.shutdown()
}

@Test
fun testSerializableResponseWithDefaultJson() = runBlocking {
val mockWebServer = MockWebServer().apply {
enqueue(MockResponse(body = "{\"userAgent\": \"Fuel2\"}"))
start()
fun testSerializableResponseWithDefaultJson() =
runBlocking {
val mockWebServer =
MockWebServer().apply {
enqueue(MockResponse(body = "{\"userAgent\": \"Fuel2\"}"))
start()
}

val response = Fuel.get(mockWebServer.url("user-agent").toString())
val json = response.toJson(deserializationStrategy = HttpBinUserAgentModel.serializer())
json.fold({
assertEquals("Fuel2", it?.userAgent)
}, {
fail(it.message)
})

mockWebServer.shutdown()
}

val response = Fuel.get(mockWebServer.url("user-agent").toString())
val json = response.toJson(deserializationStrategy = HttpBinUserAgentModel.serializer())
json.fold({
assertEquals("Fuel2", it?.userAgent)
}, {
fail(it.message)
})

mockWebServer.shutdown()
}
}

This file was deleted.

16 changes: 9 additions & 7 deletions fuel-moshi-jvm/src/main/kotlin/fuel/moshi/ResponseExtension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ import com.github.kittinunf.result.runCatching
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import fuel.HttpResponse
import kotlinx.io.readByteArray
import okio.Buffer
import java.lang.reflect.Type

public val defaultMoshi: Moshi.Builder = Moshi.Builder()

public inline fun <reified T : Any> HttpResponse.toMoshi(): Result<T?, Throwable> = toMoshi(T::class.java)

public fun <T : Any> HttpResponse.toMoshi(clazz: Class<T>): Result<T?, Throwable> =
toMoshi(defaultMoshi.build().adapter(clazz))
public fun <T : Any> HttpResponse.toMoshi(clazz: Class<T>): Result<T?, Throwable> = toMoshi(defaultMoshi.build().adapter(clazz))

public fun <T : Any> HttpResponse.toMoshi(type: Type): Result<T?, Throwable> =
toMoshi(defaultMoshi.build().adapter(type))
public fun <T : Any> HttpResponse.toMoshi(type: Type): Result<T?, Throwable> = toMoshi(defaultMoshi.build().adapter(type))

public fun <T : Any> HttpResponse.toMoshi(jsonAdapter: JsonAdapter<T>): Result<T?, Throwable> =
runCatching {
jsonAdapter.fromJson(body.source())
public fun <T : Any> HttpResponse.toMoshi(jsonAdapter: JsonAdapter<T>): Result<T?, Throwable> {
val buffer = Buffer().apply { write(source.readByteArray()) }
return runCatching {
jsonAdapter.fromJson(buffer)
}
}
Loading

0 comments on commit 300690b

Please sign in to comment.