Initial let parser use bytebuffer

This commit is contained in:
tarsin committed 2023-07-28 17:24:42 +08:00
1 parent cf8097babc
commit 02855b68e6
5 files changed
+66 -16

No files matched your search

@@ -45,10 +45,14 @@ import com.hippo.ehviewer.client.parser.TorrentParser
import com.hippo.ehviewer.client.parser.TorrentResult
import com.hippo.ehviewer.client.parser.VoteCommentResult
import com.hippo.ehviewer.client.parser.VoteTagParser
import com.hippo.ehviewer.cronet.awaitBodyFully
import com.hippo.ehviewer.cronet.cronetRequest
import com.hippo.ehviewer.cronet.execute
import com.hippo.ehviewer.dailycheck.showEventNotification
import com.hippo.ehviewer.dailycheck.today
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.StatusCodeException
import io.ktor.utils.io.pool.DirectByteBufferPool
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.delay
import kotlinx.serialization.json.add
@@ -65,6 +69,7 @@ import okhttp3.RequestBody.Companion.asRequestBody
import org.jsoup.Jsoup
import splitties.init.appCtx
import java.io.File
import java.nio.ByteBuffer
import kotlin.math.ceil
private const val TAG = "EhEngine"
@@ -124,6 +129,25 @@ private fun rethrowExactly(code: Int, headers: Headers, body: String, e: Throwab
throw e
}
val httpContentPool = DirectByteBufferPool(16, 16384)
suspend inline fun <T> fetchCompat(url: String, referer: String? = null, crossinline parser: (ByteBuffer) -> T): T {
val ret: T
cronetRequest(url, referer).execute {
val buffer = httpContentPool.borrow()
try {
awaitBodyFully {
buffer.put(it)
}
buffer.flip()
ret = parser(buffer)
} finally {
httpContentPool.recycle(buffer)
}
}
return ret
}
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
private suspend inline fun <T> Request.executeAndParsingWith(block: suspend String.() -> T): T {
Log.d(TAG, url.toString())
@@ -151,7 +175,7 @@ object EhEngine {
suspend fun getTorrentList(url: String, gid: Long, token: String?): TorrentResult {
val referer = EhUrl.getGalleryDetailUrl(gid, token)
return ehRequest(url, referer).executeAndParsingWith(TorrentParser::parse)
return fetchCompat(url, referer, TorrentParser::parse)
}
suspend fun getArchiveList(url: String, gid: Long, token: String?) = ehRequest(url, EhUrl.getGalleryDetailUrl(gid, token))
@@ -1,7 +1,9 @@
package com.hippo.ehviewer.client.parser
import java.nio.ByteBuffer
object TorrentParser {
fun parse(body: String) = parseTorrent(body)
fun parse(body: ByteBuffer) = parseTorrent(body)
}
class Torrent(
@@ -18,4 +20,4 @@ fun Torrent.format() = "[$posted] $name [$size] [↑$seeds ↓$peers ✓$downloa
typealias TorrentResult = ArrayList<Torrent>
private external fun parseTorrent(body: String): ArrayList<Torrent>
private external fun parseTorrent(body: ByteBuffer, size: Int = body.limit()): ArrayList<Torrent>
@@ -19,6 +19,8 @@ import org.chromium.net.UrlResponseInfo
import splitties.init.appCtx
import java.nio.ByteBuffer
import java.nio.channels.FileChannel
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
@@ -72,7 +74,7 @@ class CronetRequest {
}
}
inline fun cronetRequest(url: String, referer: String? = null, conf: UrlRequest.Builder.() -> Unit) = CronetRequest().apply {
inline fun cronetRequest(url: String, referer: String? = null, conf: UrlRequest.Builder.() -> Unit = {}) = CronetRequest().apply {
request = cronetHttpClient.newUrlRequestBuilder(url, callback, cronetHttpClientExecutor).apply {
addHeader("Cookie", EhCookieStore.getCookieHeader(url.toHttpUrl()))
addHeader("User-Agent", CHROME_USER_AGENT)
@@ -104,11 +106,16 @@ suspend inline fun CronetRequest.copyToChannel(chan: FileChannel, crossinline li
listener(bytes)
}
suspend inline fun CronetRequest.execute(crossinline callback: suspend CronetRequest.(UrlResponseInfo) -> Unit) = coroutineScope {
onResponse = { launch { callback(it) } }
suspendCancellableCoroutine { cont ->
cont.invokeOnCancellation { request.cancel() }
daemonCont = cont
request.start()
suspend inline fun CronetRequest.execute(crossinline callback: suspend CronetRequest.(UrlResponseInfo) -> Unit): Boolean {
contract {
callsInPlace(callback, InvocationKind.EXACTLY_ONCE)
}
return coroutineScope {
onResponse = { launch { callback(it) } }
suspendCancellableCoroutine { cont ->
cont.invokeOnCancellation { request.cancel() }
daemonCont = cont
request.start()
}
}
}