Skip to content

Commit

Permalink
update build.gradle and import remaining evaluation-core files
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Yiu authored and Tim Yiu committed Sep 21, 2023
1 parent 681edc3 commit 8bb7444
Show file tree
Hide file tree
Showing 8 changed files with 562 additions and 3 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ apply plugin: 'org.jetbrains.dokka'
apply plugin: 'org.jlleitschuh.gradle.ktlint'

buildscript {
ext.kotlin_version = '1.5.31'
ext.kotlin_version = '1.6.21'
ext.dokka_version = '1.4.32'

repositories {
Expand Down
5 changes: 3 additions & 2 deletions sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id 'com.android.library'
id 'kotlin-android'
id 'org.jetbrains.dokka'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.0'
}
ext {
PUBLISH_NAME = 'Experiment Android SDK'
Expand Down Expand Up @@ -41,8 +42,8 @@ dependencies {
implementation 'com.amplitude:analytics-connector:1.0.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'com.amplitude:android-sdk:2.26.1'
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.2.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.3.3")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3")

testImplementation 'junit:junit:4.13.2'
testImplementation 'org.json:json:20201115'
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
@file:UseSerializers(AnySerializer::class)

package com.amplitude.experiment.evaluation

import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers

@Serializable
data class EvaluationFlag(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
@file:UseSerializers(AnySerializer::class)

package com.amplitude.experiment.evaluation

import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers

@Serializable
data class EvaluationSegment(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.amplitude.experiment.evaluation

import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.booleanOrNull
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.doubleOrNull
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.longOrNull
import kotlin.jvm.JvmField
import kotlin.jvm.JvmSynthetic

@JvmSynthetic
@JvmField
internal val json = Json {
ignoreUnknownKeys = true
isLenient = true
coerceInputValues = true
explicitNulls = false
}

@JvmSynthetic
internal fun Any?.toJsonElement(): JsonElement = when (this) {
null -> JsonNull
is Map<*, *> -> toJsonObject()
is Collection<*> -> toJsonArray()
is Boolean -> JsonPrimitive(this)
is Number -> JsonPrimitive(this)
is String -> JsonPrimitive(this)
else -> JsonPrimitive(toString())
}

@JvmSynthetic
internal fun Collection<*>.toJsonArray(): JsonArray = JsonArray(map { it.toJsonElement() })

@JvmSynthetic
internal fun Map<*, *>.toJsonObject(): JsonObject = JsonObject(
mapNotNull {
(it.key as? String ?: return@mapNotNull null) to it.value.toJsonElement()
}.toMap(),
)

@JvmSynthetic
internal fun JsonElement.toAny(): Any? {
return when (this) {
is JsonPrimitive -> toAny()
is JsonArray -> toList()
is JsonObject -> toMap()
}
}

@JvmSynthetic
internal fun JsonPrimitive.toAny(): Any? {
return if (isString) {
contentOrNull
} else {
booleanOrNull ?: intOrNull ?: longOrNull ?: doubleOrNull
}
}

@JvmSynthetic
internal fun JsonArray.toList(): List<Any?> = map { it.toAny() }

@JvmSynthetic
internal fun JsonObject.toMap(): Map<String, Any?> = mapValues { it.value.toAny() }

internal object AnySerializer : KSerializer<Any?> {
private val delegate = JsonElement.serializer()
override val descriptor: SerialDescriptor
get() = SerialDescriptor("Any", delegate.descriptor)

override fun serialize(encoder: Encoder, value: Any?) {
val jsonElement = value.toJsonElement()
encoder.encodeSerializableValue(delegate, jsonElement)
}

override fun deserialize(decoder: Decoder): Any? {
val jsonElement = decoder.decodeSerializableValue(delegate)
return jsonElement.toAny()
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
@file:UseSerializers(AnySerializer::class)

package com.amplitude.experiment.evaluation

import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers

@Serializable
data class EvaluationVariant(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.amplitude.experiment.evaluation

internal object Murmur3 {

private const val C1_32 = -0x3361d2af
private const val C2_32 = 0x1b873593
private const val R1_32 = 15
private const val R2_32 = 13
private const val M_32 = 5
private const val N_32 = -0x19ab949c

internal fun hash32x86(data: ByteArray, length: Int, seed: Int): Int {
var hash = seed
val nblocks = length shr 2

// body
for (i in 0 until nblocks) {
val index = (i shl 2)
val k: Int = data.readIntLe(index)
hash = mix32(k, hash)
}

// tail
val index = (nblocks shl 2)
var k1 = 0

when (length - index) {
3 -> {
k1 = k1 xor ((data[index + 2].toInt() and 0xff) shl 16)
k1 = k1 xor ((data[index + 1].toInt() and 0xff) shl 8)
k1 = k1 xor ((data[index].toInt() and 0xff))

// mix functions
k1 *= C1_32
k1 = k1.rotateLeft(R1_32)
k1 *= C2_32
hash = hash xor k1
}
2 -> {
k1 = k1 xor ((data[index + 1].toInt() and 0xff) shl 8)
k1 = k1 xor ((data[index].toInt() and 0xff))
k1 *= C1_32
k1 = k1.rotateLeft(R1_32)
k1 *= C2_32
hash = hash xor k1
}
1 -> {
k1 = k1 xor ((data[index].toInt() and 0xff))
k1 *= C1_32
k1 = k1.rotateLeft(R1_32)
k1 *= C2_32
hash = hash xor k1
}
}
hash = hash xor length
return fmix32(hash)
}

private fun mix32(k: Int, hash: Int): Int {
var kResult = k
var hashResult = hash
kResult *= C1_32
kResult = kResult.rotateLeft(R1_32)
kResult *= C2_32
hashResult = hashResult xor kResult
return hashResult.rotateLeft(
R2_32
) * M_32 + N_32
}

private fun fmix32(hash: Int): Int {
var hashResult = hash
hashResult = hashResult xor (hashResult ushr 16)
hashResult *= -0x7a143595
hashResult = hashResult xor (hashResult ushr 13)
hashResult *= -0x3d4d51cb
hashResult = hashResult xor (hashResult ushr 16)
return hashResult
}

private fun Int.reverseBytes(): Int {
return (this and -0x1000000 ushr 24) or
(this and 0x00ff0000 ushr 8) or
(this and 0x0000ff00 shl 8) or
(this and 0x000000ff shl 24)
}

private fun ByteArray.readIntLe(index: Int = 0): Int {
return (
this[index].toInt() and 0xff shl 24
or (this[index + 1].toInt() and 0xff shl 16)
or (this[index + 2].toInt() and 0xff shl 8)
or (this[index + 3].toInt() and 0xff)
).reverseBytes()
}
}

0 comments on commit 8bb7444

Please sign in to comment.