Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add builtin Android Parcelable support #297

Merged
merged 8 commits into from
Mar 19, 2024
Merged
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
16 changes: 16 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,19 @@ jobs:
if: success() || failure()
with:
sarif_file: build/reports/detekt/detekt.sarif

androidIntegrationTest:
runs-on: macos-latest
needs:
- build
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'adopt'
java-version: 21
- uses: gradle/actions/setup-gradle@v3
with:
gradle-home-cache-cleanup: true
- name: Run Android integration tests
run: ./gradlew :kotlinx-uuid-core:allDevicesCheck
5 changes: 3 additions & 2 deletions detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@
<ID>MagicNumber:SHA1.kt$SHA1.IntArrayView$3</ID>
<ID>MagicNumber:SHA1.kt$SHA1.IntArrayView$4</ID>
<ID>MagicNumber:SHA1.kt$SHA1.IntArrayView$8</ID>
<ID>MagicNumber:SecureRandom.kt$SecureRandomBrowser$31</ID>
<ID>MagicNumber:SecureRandom.kt$SecureRandomBrowser$32</ID>
<ID>MagicNumber:SecureRandom.js.kt$SecureRandomBrowser$31</ID>
<ID>MagicNumber:SecureRandom.js.kt$SecureRandomBrowser$32</ID>
<ID>MagicNumber:UUID.kt$UUID$0x0fffL</ID>
<ID>MagicNumber:UUID.kt$UUID$0x1fff</ID>
<ID>MagicNumber:UUID.kt$UUID$0xf000L</ID>
Expand All @@ -91,6 +91,7 @@
<ID>MagicNumber:UUID7.kt$0x80L</ID>
<ID>MagicNumber:UUID7.kt$12</ID>
<ID>MagicNumber:UUID7.kt$16</ID>
<ID>MatchingDeclarationName:Parcelable.android.kt$Parcelable : Parcelable</ID>
<ID>TooManyFunctions:SHA1.kt$SHA1</ID>
<ID>VariableNaming:UUID7.kt$val rand_a = random.nextBits(12).toLong()</ID>
</CurrentIssues>
Expand Down
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ org.gradle.configureondemand=true
kotlin.native.ignoreDisabledTargets=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1g
group=app.softwork
android.useAndroidX=true
1 change: 1 addition & 0 deletions gradle/build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ plugins {
dependencies {
implementation(libs.plugins.kotlin.jvm.toDep())
implementation(libs.plugins.kotlin.serialization.toDep())
implementation(libs.plugins.android.toDep())
implementation(libs.plugins.binary.toDep())
implementation(libs.plugins.publish.toDep())
implementation(libs.plugins.dokka.toDep())
Expand Down
1 change: 1 addition & 0 deletions gradle/build-logic/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
google()
gradlePluginPortal()
}
versionCatalogs.register("libs") {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
dependencyResolutionManagement {
repositories {
mavenCentral()
google()
}
}
4 changes: 2 additions & 2 deletions gradle/build-logic/src/main/kotlin/publish.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import java.util.*

plugins {
id("org.gradle.maven-publish")
id("org.gradle.signing")
id("maven-publish")
id("signing")
}

val emptyJar by tasks.registering(Jar::class)
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ sqldelight-runtime = { module = "app.cash.sqldelight:runtime", version = "2.0.1"
[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
android = { id = "com.android.application", version = "8.3.1" }
binary = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version = "0.14.0" }
publish = { id = "io.github.gradle-nexus.publish-plugin", version = "1.3.0" }
dokka = { id = "org.jetbrains.dokka", version = "1.9.20" }
Expand Down
130 changes: 130 additions & 0 deletions kotlinx-uuid-core/api/android/kotlinx-uuid-core.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
public final class kotlinx/uuid/BinarySerializer : kotlinx/serialization/KSerializer {
public static final field INSTANCE Lkotlinx/uuid/BinarySerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/uuid/UUID;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/uuid/UUID;)V
}

public final class kotlinx/uuid/EncodingKt {
public static final fun UUID ([B)Lkotlinx/uuid/UUID;
public static final fun UUID ([J)Lkotlinx/uuid/UUID;
public static final fun encodeToByteArray (Lkotlinx/uuid/UUID;)[B
public static final fun encodeToLongArray (Lkotlinx/uuid/UUID;)[J
}

public abstract interface annotation class kotlinx/uuid/InternalAPI : java/lang/annotation/Annotation {
}

public final class kotlinx/uuid/MigrationKt {
public static final fun clockSequence (Lkotlinx/uuid/UUID;)I
public static final fun fromString (Lkotlinx/uuid/UUID$Companion;Ljava/lang/String;)Lkotlinx/uuid/UUID;
public static final fun getLeastSignificantBits (Lkotlinx/uuid/UUID;)J
public static final fun getMostSignificantBits (Lkotlinx/uuid/UUID;)J
public static final fun nameUUIDFromBytes (Lkotlinx/uuid/UUID$Companion;[B)Lkotlinx/uuid/UUID;
public static final fun node (Lkotlinx/uuid/UUID;)J
public static final fun randomUUID (Lkotlinx/uuid/UUID$Companion;)Lkotlinx/uuid/UUID;
public static final fun timestamp (Lkotlinx/uuid/UUID;)J
public static final fun variant (Lkotlinx/uuid/UUID;)I
public static final fun version (Lkotlinx/uuid/UUID;)I
}

public final class kotlinx/uuid/NameBasedGeneratorKt {
public static final fun generateUUID (Lkotlinx/uuid/UUID$Companion;Lkotlinx/uuid/UUID;Ljava/lang/String;)Lkotlinx/uuid/UUID;
public static final fun generateUUID (Lkotlinx/uuid/UUID$Companion;[B)Lkotlinx/uuid/UUID;
}

public final class kotlinx/uuid/RandomGeneratorKt {
public static final fun generateUUID (Lkotlinx/uuid/UUID$Companion;Lkotlin/random/Random;)Lkotlinx/uuid/UUID;
public static synthetic fun generateUUID$default (Lkotlinx/uuid/UUID$Companion;Lkotlin/random/Random;ILjava/lang/Object;)Lkotlinx/uuid/UUID;
public static final fun nextUUID (Lkotlin/random/Random;)Lkotlinx/uuid/UUID;
}

public final class kotlinx/uuid/SecureRandom_androidKt {
public static final fun getSecureRandom ()Lkotlin/random/Random;
}

public abstract class kotlinx/uuid/Serializer : kotlinx/serialization/KSerializer {
public synthetic fun <init> (ZLkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/uuid/UUID;
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/uuid/UUID;)V
}

public final class kotlinx/uuid/Serializer$Default : kotlinx/uuid/Serializer {
public static final field INSTANCE Lkotlinx/uuid/Serializer$Default;
}

public final class kotlinx/uuid/Serializer$WrappedCurlyBrackets : kotlinx/uuid/Serializer {
public static final field INSTANCE Lkotlinx/uuid/Serializer$WrappedCurlyBrackets;
}

public final class kotlinx/uuid/UUID : kotlinx/uuid/internal/Parcelable, java/lang/Comparable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public static final field Companion Lkotlinx/uuid/UUID$Companion;
public fun <init> ()V
public fun <init> (IJIJI)V
public synthetic fun <init> (IJIJIILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;)V
public fun <init> (Lkotlinx/uuid/UUID$Version;JIJI)V
public synthetic fun <init> (Lkotlinx/uuid/UUID$Version;JIJIILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun compareTo (Ljava/lang/Object;)I
public fun compareTo (Lkotlinx/uuid/UUID;)I
public fun equals (Ljava/lang/Object;)Z
public final fun getClockSequence ()I
public final fun getNode ()J
public final fun getTimeStamp ()J
public final fun getVariant ()I
public final fun getVersion ()Lkotlinx/uuid/UUID$Version;
public final fun getVersionNumber ()I
public fun hashCode ()I
public final fun isRfcVariant ()Z
public fun toString ()Ljava/lang/String;
public final fun toString (Z)Ljava/lang/String;
}

public final class kotlinx/uuid/UUID$Companion {
public final fun getNIL ()Lkotlinx/uuid/UUID;
public final fun isValidUUIDString (Ljava/lang/String;)Z
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class kotlinx/uuid/UUID$Version : java/lang/Enum {
public static final field DCE_SECURITY Lkotlinx/uuid/UUID$Version;
public static final field NAME_BASED_MD5 Lkotlinx/uuid/UUID$Version;
public static final field NAME_BASED_SHA1 Lkotlinx/uuid/UUID$Version;
public static final field RANDOM_BASED Lkotlinx/uuid/UUID$Version;
public static final field TIME_BASED Lkotlinx/uuid/UUID$Version;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lkotlinx/uuid/UUID$Version;
public static fun values ()[Lkotlinx/uuid/UUID$Version;
}

public final class kotlinx/uuid/UUID7Kt {
public static final fun UUIDv7 (JLkotlin/random/Random;)Lkotlinx/uuid/UUID;
public static synthetic fun UUIDv7$default (JLkotlin/random/Random;ILjava/lang/Object;)Lkotlinx/uuid/UUID;
public static final fun getUnixTimeStamp (Lkotlinx/uuid/UUID;)J
}

public abstract interface annotation class kotlinx/uuid/UUIDExperimentalAPI : java/lang/annotation/Annotation {
public abstract fun plannedVersion ()Ljava/lang/String;
}

public final class kotlinx/uuid/UUIDKt {
public static final fun toUUID (Ljava/lang/String;)Lkotlinx/uuid/UUID;
public static final fun toUUIDOrNull (Ljava/lang/String;)Lkotlinx/uuid/UUID;
}

public abstract class kotlinx/uuid/internal/Parcelable : android/os/Parcelable {
public fun <init> (JJ)V
public fun describeContents ()I
public fun writeToParcel (Landroid/os/Parcel;I)V
}

public final class kotlinx/uuid/internal/Parcelable_androidKt {
public static final fun getCreator ()Landroid/os/Parcelable$Creator;
}

Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ public final class kotlinx/uuid/Serializer$WrappedCurlyBrackets : kotlinx/uuid/S
public static final field INSTANCE Lkotlinx/uuid/Serializer$WrappedCurlyBrackets;
}

public final class kotlinx/uuid/UUID : java/lang/Comparable {
public final class kotlinx/uuid/UUID : kotlinx/uuid/internal/Parcelable, java/lang/Comparable {
public static final field CREATOR Lkotlinx/uuid/internal/ParcelableCreator;
public static final field Companion Lkotlinx/uuid/UUID$Companion;
public fun <init> ()V
public fun <init> (IJIJI)V
public synthetic fun <init> (IJIJIILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (JJLkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;)V
public fun <init> (Lkotlinx/uuid/UUID$Version;JIJI)V
public synthetic fun <init> (Lkotlinx/uuid/UUID$Version;JIJIILkotlin/jvm/internal/DefaultConstructorMarker;)V
Expand Down Expand Up @@ -123,3 +123,10 @@ public final class kotlinx/uuid/UUIDKt {
public static final fun toUUIDOrNull (Ljava/lang/String;)Lkotlinx/uuid/UUID;
}

public abstract class kotlinx/uuid/internal/Parcelable {
public fun <init> (JJ)V
}

public abstract interface class kotlinx/uuid/internal/ParcelableCreator {
}

42 changes: 42 additions & 0 deletions kotlinx-uuid-core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.plugin.*

/*
* Copyright 2020-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2021 hfhbd and contributors. Use of this source code is governed by the Apache 2.0 license.
Expand All @@ -8,6 +10,7 @@ plugins {
id("publish")
id("dokkaLicensee")
id("kover")
id("com.android.library")
}

kotlin {
Expand All @@ -20,6 +23,10 @@ kotlin {
}
}

androidTarget {
instrumentedTestVariant.sourceSetTree.set(KotlinSourceSetTree.test)
}

sourceSets {
commonMain {
dependencies {
Expand All @@ -36,3 +43,38 @@ kotlin {
}
}
}

android {
namespace = "kotlinx.uuid"
compileSdk = 34

defaultConfig {
minSdk = 21
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
testOptions {
managedDevices {
localDevices {
register("pixel2api30") {
device = "Pixel 2"
apiLevel = 30
systemImageSource = "aosp"
}
}
}
}
}

kotlin.sourceSets {
named("androidInstrumentedTest") {
dependencies {
implementation("androidx.test:runner:1.5.2")
implementation("androidx.test.ext:junit-ktx:1.1.4")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package kotlinx.uuid.internal

import android.os.Parcel
import androidx.test.ext.junit.runners.*
import kotlinx.uuid.*
import org.junit.runner.*
import kotlin.test.*

@RunWith(AndroidJUnit4::class)
class ParcelableTest {
@Test
fun testParcelable() {
val parcel = Parcel.obtain()
val uuid = UUID(SOME_UUID_STRING)
uuid.writeToParcel(parcel, uuid.describeContents())
parcel.setDataPosition(0)
assertEquals(uuid, UUID.CREATOR.createFromParcel(parcel))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package kotlinx.uuid

import kotlin.random.*

/**
* Returns a platform dependent SecureRandom instance.
* - On JVM, it uses `java.util.SecureRandom`
* - On JS, it uses `window.crypto` or `nodejs.crypto`.
* - On darwin, it uses `SecRandomCopyBytes`.
* - On mingw, it uses `BCryptRandom`.
* - On Linux and Android native, it uses `DevUrandom`.
*/
public actual val SecureRandom: Random = java.security.SecureRandom().asKotlinRandom()
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")

package kotlinx.uuid.internal

import android.os.*
import kotlinx.uuid.*

public actual abstract class Parcelable actual constructor(
Fixed Show fixed Hide fixed
private val timeStampAndVersionRaw: Long,
private val clockSequenceVariantAndNodeRaw: Long
) : android.os.Parcelable {
override fun describeContents(): Int = 0
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeLong(timeStampAndVersionRaw)
parcel.writeLong(clockSequenceVariantAndNodeRaw)
}
}

internal actual typealias ParcelableCreator<UUID> = android.os.Parcelable.Creator<UUID>

public actual val creator: ParcelableCreator<UUID> = object : android.os.Parcelable.Creator<UUID> {
override fun createFromParcel(parcel: Parcel): UUID {
val timeStampAndVersionRaw = parcel.readLong()
val clockSequenceVariantAndNodeRaw = parcel.readLong()
return UUID(timeStampAndVersionRaw, clockSequenceVariantAndNodeRaw)
}

override fun newArray(size: Int): Array<UUID?> {
return arrayOfNulls(size)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package kotlinx.uuid.internal

import kotlinx.uuid.*

@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
public actual abstract class Parcelable actual constructor(
timeStampAndVersionRaw: Long,
clockSequenceVariantAndNodeRaw: Long
)

public actual interface ParcelableCreator<T : Any>

internal actual val creator: ParcelableCreator<UUID> = object : ParcelableCreator<UUID> {}
Loading
Loading