Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.dokka)
alias(libs.plugins.kotlin.serialization)
}

val javaTarget = JvmTarget.fromTarget(libs.versions.jvmTarget.get())
Expand Down Expand Up @@ -206,9 +207,12 @@ dependencies {
testImplementation(libs.junit)
testImplementation(libs.json)
androidTestImplementation(libs.core)
implementation(libs.junit.ktx)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
androidTestImplementation(libs.kotlin.test)
androidTestImplementation(libs.classgraph)
androidTestImplementation(libs.instancio.core)
implementation(libs.junit.ktx)

// Android Core & Lifecycle
implementation(libs.core.ktx)
Expand All @@ -219,6 +223,7 @@ dependencies {
implementation(libs.bundles.lifecycle)
implementation(libs.bundles.navigation)
implementation(libs.kotlinx.collections.immutable)
implementation(libs.kotlinx.serialization.json) // JSON Parser

// Design & UI
implementation(libs.preference.ktx)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package com.lagradost.cloudstream3

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.lagradost.cloudstream3.utils.AppUtils.toJson
import io.github.classgraph.ClassGraph
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.serializer
import kotlinx.serialization.serializerOrNull
import org.instancio.Instancio
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.reflect.KClass
import kotlin.reflect.jvm.jvmName
import kotlin.test.assertEquals
import kotlin.test.assertNotNull

@RunWith(AndroidJUnit4::class)
class SerializationClassTester {
// Same as app, or using app reference
val jacksonMapper = mapper
val kotlinxMapper = json

@Test
fun isIdenticalSerialization() {
val serializableClasses = findSerializableClasses("com.lagradost")
println("Number of serializable classes: ${serializableClasses.size}")

serializableClasses.forEach { kClass ->
val instance = Instancio.create(kClass.java)

val jacksonJson = jacksonMapper.writeValueAsString(instance)
val kotlinxJson = serializeWithKotlinx(kClass, instance)

assertEquals(
jacksonJson,
kotlinxJson,
"""
Serialization mismatch for:
${kClass.qualifiedName}

Jackson:
$jacksonJson

Kotlinx:
$kotlinxJson

""".trimIndent()
)
println("Identical serialization for: ${kClass.jvmName}")
}
}

@OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
@Test
fun isIdenticalDeserialization() {
val serializableClasses = findSerializableClasses("com.lagradost")
println("Number of serializable classes: ${serializableClasses.size}")

serializableClasses.forEach { kClass ->
val instance = Instancio.create(kClass.java)
// Convert to JSON to get example JSON object
// We prefer jackson here because the app may have many jackson JSON strings in local storage
val originalJson = jacksonMapper.writeValueAsString(instance)

// Create an object from the JSON using kotlinx
val serializer =
kClass.serializerOrNull() ?: kotlinxMapper.serializersModule.getContextual(kClass)
assertNotNull(serializer, "The class: ${kClass.jvmName} must be serializable!")
val kotlinxDecoded = kotlinxMapper.decodeFromString(serializer, originalJson)

// Create an object from the JSON using jackson
val mapperDecoded = jacksonMapper.readValue(originalJson, kClass.java)


// Deep inspect both object using the mapper toJson function.
// This deep equality check can be performed using other methods, but this just works.
val jacksonJson = mapperDecoded.toJson()
val kotlinxJson = kotlinxDecoded.toJson()

assertEquals(
jacksonJson,
kotlinxJson,
"""
Serialization mismatch for:
${kClass.qualifiedName}

Jackson:
$jacksonJson

Kotlinx:
$kotlinxJson

""".trimIndent()
)
println("Identical deserialization for: ${kClass.jvmName}")
}
}

private fun findSerializableClasses(packageName: String): List<KClass<*>> {
val context = InstrumentationRegistry
.getInstrumentation()
.targetContext

return ClassGraph()
.enableClassInfo()
.enableAnnotationInfo()
.overrideClassLoaders(context.classLoader)
.acceptPackages(packageName)
.scan()
.getClassesWithAnnotation(Serializable::class.java.name)
.mapNotNull { runCatching { Class.forName(it.name, false, context.classLoader).kotlin }.getOrNull() }
}

@OptIn(InternalSerializationApi::class)
@Suppress("UNCHECKED_CAST")
private fun serializeWithKotlinx(
kClass: KClass<*>,
value: Any
): String {
val serializer = kClass.serializer() as KSerializer<Any>
return kotlinxMapper.encodeToString(serializer, value)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ object PluginManager {
return false
}
InputStreamReader(stream).use { reader ->
manifest = parseJson(reader, BasePlugin.Manifest::class.java)
manifest = parseJson<BasePlugin.Manifest>(reader.readText())
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import com.lagradost.cloudstream3.Score
import com.lagradost.cloudstream3.SimklSyncServices
import com.lagradost.cloudstream3.TvType
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.mapper
import com.lagradost.cloudstream3.mvvm.debugPrint
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.APP_STRING
Expand All @@ -30,6 +29,7 @@ import com.lagradost.cloudstream3.syncproviders.SyncIdName
import com.lagradost.cloudstream3.ui.SyncWatchType
import com.lagradost.cloudstream3.ui.library.ListSorting
import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.DataStoreHelper.toYear
import com.lagradost.cloudstream3.utils.txt
import java.math.BigInteger
Expand Down Expand Up @@ -117,13 +117,8 @@ class SimklApi : SyncAPI() {
* Gets cached object, if object is not fresh returns null and removes it from cache
*/
inline fun <reified T : Any> getKey(path: String): T? {
// Required for generic otherwise "LinkedHashMap cannot be cast to MediaObject"
val type = mapper.typeFactory.constructParametricType(
SimklCacheWrapper::class.java,
T::class.java
)
val cache = getKey<String>(SIMKL_CACHE_KEY, path)?.let {
mapper.readValue<SimklCacheWrapper<T>>(it, type)
tryParseJson<SimklCacheWrapper<T>>(it)
}

return if (cache?.isFresh() == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.ListView
import androidx.appcompat.app.AlertDialog
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.module.kotlin.kotlinModule
import com.google.android.gms.cast.MediaLoadOptions
import com.google.android.gms.cast.MediaQueueItem
import com.google.android.gms.cast.MediaSeekOptions
Expand Down Expand Up @@ -105,9 +102,6 @@ data class MetadataHolder(

class SelectSourceController(val view: ImageView, val activity: ControllerActivity) :
UIController() {
private val mapper: JsonMapper = JsonMapper.builder().addModule(kotlinModule())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build()

init {
view.setImageResource(R.drawable.ic_baseline_playlist_play_24)
view.setOnClickListener {
Expand Down Expand Up @@ -449,4 +443,4 @@ class ControllerActivity : ExpandedControllerActivity() {
SkipNextEpisodeController(skipOpButton)
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ import com.lagradost.cloudstream3.utils.AppContextUtils.getNameFull
import com.lagradost.cloudstream3.utils.AppContextUtils.isConnectedToChromecast
import com.lagradost.cloudstream3.utils.AppContextUtils.setDefaultFocus
import com.lagradost.cloudstream3.utils.AppContextUtils.sortSubs
import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.CastHelper.startCast
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.Coroutines.ioWork
Expand Down Expand Up @@ -1324,7 +1325,7 @@ class ResultViewModel2 : ViewModel() {
episodeIds: Array<String>,
watchState: VideoWatchState
) {
val watchStateString = DataStore.mapper.writeValueAsString(watchState)
val watchStateString = watchState.toJson()
episodeIds.forEach {
if (getVideoWatchState(it.toInt()) != watchState) {
editor.setKeyRaw(
Expand Down Expand Up @@ -2706,4 +2707,4 @@ class ResultViewModel2 : ViewModel() {
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import androidx.core.net.toUri
import androidx.fragment.app.FragmentActivity
import androidx.preference.PreferenceManager
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.CloudStreamApp.Companion.getActivity
import com.lagradost.cloudstream3.CommonActivity.showToast
import com.lagradost.cloudstream3.R
Expand All @@ -21,11 +20,12 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_CACHED_LIST
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_CACHED_LIST
import com.lagradost.cloudstream3.syncproviders.providers.KitsuApi.Companion.KITSU_CACHED_LIST
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.DataStore.getDefaultSharedPrefs
import com.lagradost.cloudstream3.utils.DataStore.getSharedPrefs
import com.lagradost.cloudstream3.utils.DataStore.mapper
import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
import com.lagradost.cloudstream3.utils.downloader.VideoDownloadManager.setupStream
Expand Down Expand Up @@ -133,9 +133,7 @@ object BackupUtils {
)

@Suppress("UNCHECKED_CAST")
private fun getBackup(context: Context?): BackupFile? {
if (context == null) return null

private fun getBackup(context: Context): BackupFile {
val allData = context.getSharedPrefs().all.filter { it.key.isTransferable() }
val allSettings = context.getDefaultSharedPrefs().all.filter { it.key.isTransferable() }

Expand Down Expand Up @@ -214,7 +212,7 @@ object BackupUtils {

fileStream = stream.openNew()
printStream = PrintWriter(fileStream)
printStream.print(mapper.writeValueAsString(backupFile))
printStream.print(backupFile.toJson())

showToast(
R.string.backup_success,
Expand Down Expand Up @@ -259,8 +257,8 @@ object BackupUtils {
val input = activity.contentResolver.openInputStream(uri)
?: return@ioSafe

val restoredValue =
mapper.readValue<BackupFile>(input)
val text = input.bufferedReader().readText()
val restoredValue = parseJson<BackupFile>(text)

restore(
activity,
Expand Down
Loading