添加delegate和observe

This commit is contained in:
tursom 2021-02-28 17:43:13 +08:00
parent c44e9fca3e
commit 530b0b8602
53 changed files with 1520 additions and 344 deletions

View File

@ -1,7 +1,9 @@
dependencies {
compile project(":")
compile project(":log")
// kotlin
compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
compile project(":log")
testRuntime group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-debug', version: '1.3.9'
}

View File

@ -1,10 +1,9 @@
package cn.tursom.niothread.loophandler
import cn.tursom.core.randomInt
import cn.tursom.niothread.NioThread
import cn.tursom.core.Utils
import cn.tursom.niothread.NioProtocol
import cn.tursom.niothread.NioThread
import java.nio.channels.SelectionKey
import java.nio.channels.ServerSocketChannel
class MultithreadingBossLoopHandler(
protocol: NioProtocol,
@ -14,7 +13,7 @@ class MultithreadingBossLoopHandler(
val workerThread: NioThread = if (workerThread.isEmpty()) {
nioThread
} else {
workerThread[randomInt(0, workerThread.size - 1)]
workerThread[Utils.random.nextInt(0, workerThread.size - 1)]
}
handle(nioThread, key, workerThread)
}

View File

@ -1,17 +1,19 @@
package cn.tursom.datagram.server
import cn.tursom.channel.BufferedAsyncChannel
import cn.tursom.core.log
import cn.tursom.core.pool.DirectMemoryPool
import cn.tursom.datagram.AsyncDatagramClient
import cn.tursom.log.impl.Slf4jImpl
import cn.tursom.socket.NioClient
import cn.tursom.socket.server.BuffedNioServer
import kotlinx.coroutines.runBlocking
val logger = Slf4jImpl.getLogger()
val echoHandler: suspend BufferedAsyncChannel.() -> Unit = {
while (true) {
val buffer = read()
log("$this recv from client $remoteAddress: ${buffer.toString(buffer.readable)}")
logger.debug("$this recv from client $remoteAddress: ${buffer.toString(buffer.readable)}")
Throwable().printStackTrace()
write(buffer)
}
@ -52,7 +54,7 @@ fun main() {
client.write(line)
client.read(3000)
}
log("recv from server: ${read.getString()}")
logger.debug("recv from server: ${read.getString()}")
read.close()
} catch (e: Exception) {
Exception(e).printStackTrace()

View File

@ -1,5 +1,5 @@
buildscript {
ext.kotlinVersion = '1.4.0'
ext.kotlinVersion = '1.4.31'
repositories {
mavenLocal()
@ -28,14 +28,18 @@ allprojects {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
api "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
api "com.google.code.gson:gson:2.8.2"
testImplementation group: 'junit', name: 'junit', version: '4.12'
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.useIR = true
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.useIR = true
}
//
@ -66,4 +70,11 @@ allprojects {
}
}
}
sourceSets {
all {
languageSettings {
useExperimentalAnnotation('-Xopt-in=kotlin.RequiresOptIn')
}
}
}
}

View File

@ -1,5 +1,8 @@
package cn.tursom.log
import org.slf4j.Logger
import org.slf4j.event.Level
inline fun lazyLog(crossinline toString: () -> String) = object {
override fun toString(): String = toString()
}
@ -26,4 +29,46 @@ inline fun lazyPrettyMap(map: Map<out CharSequence, Any>) = if (map.isNotEmpty()
lazyPrettyMap(map.iterator())
} else {
"{}"
}
fun Logger.isEnabled(level: Level) = when (level) {
Level.ERROR -> isErrorEnabled
Level.WARN -> isWarnEnabled
Level.INFO -> isInfoEnabled
Level.DEBUG -> isDebugEnabled
Level.TRACE -> isTraceEnabled
}
fun Logger.log(level: Level, msg: String, args: Array<*>) = when (level) {
Level.ERROR -> error(msg, *args)
Level.WARN -> warn(msg, *args)
Level.INFO -> info(msg, *args)
Level.DEBUG -> debug(msg, *args)
Level.TRACE -> trace(msg, *args)
}
@JvmName("friendlyLog")
fun Logger.log(level: Level, msg: String, vararg args: Any?) = when (level) {
Level.ERROR -> error(msg, *args)
Level.WARN -> warn(msg, *args)
Level.INFO -> info(msg, *args)
Level.DEBUG -> debug(msg, *args)
Level.TRACE -> trace(msg, *args)
}
fun Logger.logCaller() = logCaller(Level.DEBUG)
fun Logger.logCaller(level: Level) {
if (isEnabled(level)) {
val e = Throwable()
val stackTraceElement = e.stackTrace[1]
log(
level,
"calling {}.{}({}:{})",
stackTraceElement.className,
stackTraceElement.methodName,
stackTraceElement.fileName,
stackTraceElement.lineNumber
)
}
}

View File

@ -3,21 +3,60 @@ package cn.tursom.log.impl
import cn.tursom.log.Slf4j
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import sun.reflect.Reflection
import kotlin.reflect.KClass
import kotlin.reflect.jvm.jvmName
open class Slf4jImpl(name: String? = null) : Slf4j {
constructor(clazz: Class<*>?) : this(clazz?.name)
constructor(clazz: KClass<*>?) : this(clazz?.jvmName?.let {
if (clazz.isCompanion) it.dropLast(10) else it
open class Slf4jImpl(
override val log: Logger,
) : Slf4j, Logger by log {
constructor(name: String? = null) : this(LoggerFactory.getLogger(name ?: loggerName))
constructor(target: Class<*>?) : this(target?.canonicalName)
constructor(target: Any?) : this(target?.let { it::class })
constructor(target: KClass<*>?) : this(target?.let { clazz ->
clazz.jvmName.let {
if (clazz.isCompanion) {
it.dropLast(10)
} else {
it
}
}
})
override val log: Logger = LoggerFactory.getLogger(name ?: if (this.javaClass != Slf4jImpl::class.java) {
val clazz = this.javaClass.kotlin
clazz.jvmName.let {
if (clazz.isCompanion) it.dropLast(10) else it
@Suppress("MemberVisibilityCanBePrivate", "NOTHING_TO_INLINE")
companion object {
private val thisClassName = listOf(this::class.java.name.dropLast(10), this::class.java.name)
private val loggerName: String
get() = getCallerClassName() ?: throw UnsupportedOperationException()
private fun getCallerClassName(): String? {
var clazz: Class<*>?
var callStackDepth = 1
do {
@Suppress("DEPRECATION")
clazz = Reflection.getCallerClass(callStackDepth++)
if (clazz?.name !in thisClassName) {
break
}
} while (clazz != null)
return clazz?.name
}
} else {
throw NotImplementedError("")
})
inline fun getLogger(name: String): Logger = LoggerFactory.getLogger(name)
fun getLogger(): Logger = LoggerFactory.getLogger(loggerName)
inline fun getLogger(target: Any): Logger = getLogger(if (target::class != Slf4jImpl::class) {
val kClass = target::class
kClass.jvmName.let {
if (kClass.isCompanion) {
it.dropLast(10)
} else {
it
}
}
} else {
throw NotImplementedError("there is no default logger name")
})
}
}

View File

@ -14,5 +14,7 @@ include 'database:redis'
include 'utils:ws-client'
include 'utils:mail'
include 'utils:csv'
include 'utils:delegation'
include 'utils:observer'
include 'utils:TrafficForward'
include 'utils:performance-test'

View File

@ -1,3 +1,4 @@
dependencies {
compile project(":")
compile project(":log")
}

View File

@ -1,7 +1,5 @@
package cn.tursom.socket.server
import cn.tursom.core.log
import cn.tursom.core.logE
import cn.tursom.socket.INioProtocol
import cn.tursom.socket.niothread.INioThread
import cn.tursom.socket.niothread.WorkerLoopNioThread

View File

@ -1,6 +1,6 @@
package cn.tursom.socket.server
import cn.tursom.core.getTAG
import cn.tursom.log.impl.Slf4jImpl
import cn.tursom.socket.BaseSocket
import java.io.IOException
import java.net.ServerSocket
@ -41,22 +41,22 @@ class ThreadPoolSocketServer
* @param timeUnit timeout的单位默认毫秒
* @param handler 对套接字处理的业务逻辑
*/(
override val port: Int,
threads: Int = 1,
queueSize: Int = 1,
keepAliveTime: Long = 60_000L,
timeUnit: TimeUnit = TimeUnit.MILLISECONDS,
override val handler: BaseSocket.() -> Unit
override val port: Int,
threads: Int = 1,
queueSize: Int = 1,
keepAliveTime: Long = 60_000L,
timeUnit: TimeUnit = TimeUnit.MILLISECONDS,
override val handler: BaseSocket.() -> Unit
) : ISimpleSocketServer {
constructor(
port: Int,
handler: BaseSocket.() -> Unit
port: Int,
handler: BaseSocket.() -> Unit
) : this(port, 1, 1, 60_000L, TimeUnit.MILLISECONDS, handler)
var socket = Socket()
private val pool: ThreadPoolExecutor =
ThreadPoolExecutor(threads, threads, keepAliveTime, timeUnit, LinkedBlockingQueue(queueSize))
ThreadPoolExecutor(threads, threads, keepAliveTime, timeUnit, LinkedBlockingQueue(queueSize))
private var serverSocket: ServerSocket = ServerSocket(port)
/**
@ -70,7 +70,7 @@ class ThreadPoolSocketServer
while (!serverSocket.isClosed) {
try {
socket = serverSocket.accept()
println("$TAG: run(): get connect: $socket")
debug("run(): get connect: {}", socket)
pool.execute {
socket.use {
BaseSocket(it).handler()
@ -128,8 +128,7 @@ class ThreadPoolSocketServer
closeServer()
}
companion object {
val TAG = getTAG(this::class.java)
companion object : Slf4jImpl() {
/**
* 线程池满时返回给客户端的信息
*/

View File

@ -0,0 +1,79 @@
package cn.tursom.core
import com.google.gson.Gson
import com.google.gson.TypeAdapter
import com.google.gson.TypeAdapterFactory
import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
object EnumTypeAdapterFactory : TypeAdapterFactory {
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
annotation class EnumValue
override fun <T : Any> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
if (!type.rawType.isEnum) {
return null
}
val valueOf = type.rawType.getDeclaredMethod("valueOf", String::class.java)
val enumValueMap = type.rawType.enumConstants.asList().associateWith {
val enum: T = it.cast()
enum.javaClass.getField(it.toString()).getAnnotation(SerializedName::class.java)?.let { serializedName ->
return@associateWith serializedName.value
}
val field = enum.javaClass.declaredFields.firstOrNull { it2 ->
it2.getAnnotation(EnumValue::class.java) != null
}
if (field != null) {
field.isAccessible = true
val value: Any = field.get(enum)
value
} else {
enum
}
}
return object : TypeAdapter<T>() {
override fun write(out: JsonWriter, value: T?) {
if (value == null) {
out.nullValue()
} else {
when (val enumValue = enumValueMap[value]) {
null -> out.nullValue()
is Boolean -> out.value(enumValue)
is Char -> out.value(enumValue.toString())
is Byte -> out.value(enumValue)
is Short -> out.value(enumValue)
is Int -> out.value(enumValue)
is Long -> out.value(enumValue)
is Float -> out.value(enumValue)
is Double -> out.value(enumValue)
is Enum<*> -> out.value(enumValue.toString())
else -> out.jsonValue(Utils.gson.toJson(enumValue))
}
}
}
override fun read(reader: JsonReader): T? {
if (reader.peek() == JsonToken.NULL) {
reader.nextNull()
return null
} else {
val source = reader.nextString()
enumValueMap.forEach { (value, type) ->
if (type.toString() == source) {
return value.cast()
}
}
return valueOf(null, source).cast()
}
}
}
}
}

View File

@ -0,0 +1,81 @@
package cn.tursom.core
import com.google.gson.Gson
import com.google.gson.TypeAdapter
import com.google.gson.TypeAdapterFactory
import com.google.gson.internal.LinkedTreeMap
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
class GsonDataTypeAdaptor internal constructor(private val gson: Gson) : TypeAdapter<Map<String, Any>?>() {
override fun write(out: JsonWriter, value: Map<String, Any>?) {
if (value == null) {
out.nullValue()
return
}
out.beginObject()
value.forEach { (t, u) ->
out.name(t)
System.err.println(u)
gson.getAdapter(Any::class.java).write(out, u)
}
out.endObject()
}
override fun read(`in`: JsonReader): Map<String, Any> = readInternal(`in`).cast()
private fun readInternal(`in`: JsonReader): Any? {
return when (`in`.peek()) {
JsonToken.BEGIN_ARRAY -> {
val list: MutableList<Any?> = ArrayList()
`in`.beginArray()
while (`in`.hasNext()) {
list.add(readInternal(`in`))
}
`in`.endArray()
list
}
JsonToken.BEGIN_OBJECT -> {
val map: MutableMap<String, Any?> = LinkedTreeMap()
`in`.beginObject()
while (`in`.hasNext()) {
map[`in`.nextName()] = readInternal(`in`)
}
`in`.endObject()
map
}
JsonToken.STRING -> `in`.nextString()
JsonToken.NUMBER -> {
//将其作为一个字符串读取出来
val numberStr: String = `in`.nextString()
//返回的numberStr不会为null
if (numberStr.contains(".") || numberStr.contains("e")
|| numberStr.contains("E")
) {
numberStr.toDouble()
} else numberStr.toLong()
}
JsonToken.BOOLEAN -> `in`.nextBoolean()
JsonToken.NULL -> {
`in`.nextNull()
null
}
else -> throw IllegalStateException()
}
}
companion object {
val FACTORY: TypeAdapterFactory = object : TypeAdapterFactory {
override fun <T : Any> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
return if (type.rawType == Map::class.java) {
GsonDataTypeAdaptor(gson).cast()
} else {
null
}
}
}
}
}

View File

@ -1,5 +1,6 @@
package cn.tursom.core
import cn.tursom.core.Unsafe.unsafe
import java.lang.reflect.Array
import java.lang.reflect.Field
import java.lang.reflect.Modifier

View File

@ -2,229 +2,229 @@
package cn.tursom.core
import sun.misc.Unsafe
import java.io.ByteArrayInputStream
import cn.tursom.core.datastruct.ReversedList
import cn.tursom.core.datastruct.StepList
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import sun.reflect.Reflection
import java.io.ByteArrayOutputStream
import java.io.ObjectOutputStream
import java.io.Serializable
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.lang.reflect.Proxy
import java.net.URLDecoder
import java.net.URLEncoder
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.util.*
import java.util.concurrent.Executor
import java.util.jar.JarFile
import java.util.zip.Deflater
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import java.util.zip.Inflater
import kotlin.collections.ArrayList
import kotlin.collections.HashSet
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import kotlin.experimental.and
import kotlin.jvm.internal.PropertyReference
import kotlin.random.Random
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty1
import kotlin.reflect.full.companionObjectInstance
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.superclasses
object Utils {
const val dollar = '$'
val random = Random(System.currentTimeMillis())
inline fun <reified T> Array<out T?>.excludeNull(): List<T> {
val list = ArrayList<T>()
forEach { if (it != null) list.add(it) }
return list
}
fun printNonDaemonThread() {
val currentGroup = Thread.currentThread().threadGroup
val noThreads = currentGroup.activeCount()
val lstThreads = arrayOfNulls<Thread>(noThreads)
currentGroup.enumerate(lstThreads)
lstThreads.excludeNull().forEach { t ->
if (!t.isDaemon) {
log(t.name)
}
@Suppress("unused", "SpellCheckingInspection")
val gson: Gson by lazy {
GsonBuilder()
.registerTypeAdapterFactory(GsonDataTypeAdaptor.FACTORY)
.registerTypeAdapterFactory(EnumTypeAdapterFactory)
.create()
}
println()
}
fun log(log: String) = println("${ThreadLocalSimpleDateFormat.standard.format(System.currentTimeMillis())}: $log")
fun logE(log: String) =
System.err.println("${ThreadLocalSimpleDateFormat.standard.format(System.currentTimeMillis())}: $log")
val String.urlDecode: String get() = URLDecoder.decode(this, "utf-8")
val String.urlEncode: String get() = URLEncoder.encode(this, "utf-8")
inline fun <T> usingTime(action: () -> T): Long {
val t1 = System.currentTimeMillis()
action()
val t2 = System.currentTimeMillis()
return t2 - t1
}
inline fun <T> usingNanoTime(action: () -> T): Long {
val t1 = System.nanoTime()
action()
val t2 = System.nanoTime()
return t2 - t1
}
inline fun <T> Collection<T>.toString(action: (T) -> Any): String {
val iterator = iterator()
if (!iterator.hasNext()) return "[]"
val sb = StringBuilder("[${action(iterator.next())}")
iterator.forEach {
sb.append(", ")
sb.append(action(it))
@Suppress("unused", "SpellCheckingInspection")
val prettyGson: Gson by lazy {
GsonBuilder()
.registerTypeAdapterFactory(GsonDataTypeAdaptor.FACTORY)
.registerTypeAdapterFactory(EnumTypeAdapterFactory)
.setPrettyPrinting()
.create()
}
internal val UPPER_HEX_ARRAY = "0123456789ABCDEF".toCharArray()
internal val LOWER_HEX_ARRAY = "0123456789abcdef".toCharArray()
val md5 by lazy { MessageDigest.getInstance("MD5")!! }
val sha256 by lazy { MessageDigest.getInstance("SHA-256")!! }
val sha by lazy { MessageDigest.getInstance("SHA")!! }
val sha1 by lazy { MessageDigest.getInstance("SHA-1")!! }
val sha384 by lazy { MessageDigest.getInstance("SHA-384")!! }
val sha512 by lazy { MessageDigest.getInstance("SHA-512")!! }
internal val DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray()
val receiverField: Field by lazy {
kotlin.jvm.internal.CallableReference::class.java.getDeclaredField("receiver").apply { isAccessible = true }
}
val ownerField: Field by lazy {
kotlin.jvm.internal.CallableReference::class.java.getDeclaredField("owner").apply { isAccessible = true }
}
sb.append("]")
return sb.toString()
}
val unsafe by lazy {
val field = Unsafe::class.java.getDeclaredField("theUnsafe")
field.isAccessible = true
field.get(null) as Unsafe
fun String.hexStringToByteArray(): ByteArray {
val len = length
val data = ByteArray(len / 2)
var i = 0
while (i < len) {
data[i / 2] = (Character.digit(this[i], 16) shl 4 or Character.digit(this[i + 1], 16)).toByte()
i += 2
}
return data
}
@Suppress("UNCHECKED_CAST")
fun <T> Class<T>.unsafeInstance() = unsafe.allocateInstance(this) as T
val Class<*>.actualTypeArguments: Array<out Type>
get() = (genericSuperclass as ParameterizedType).actualTypeArguments
fun ByteArray.toHexString(upper: Boolean = true): String = if (upper) toUpperHexString() else toLowerHexString()
fun ByteArray.toUpperHexString(): String {
val hexChars = CharArray(size * 2)
for (i in indices) {
val b = this[i]
hexChars[i shl 1] = Utils.UPPER_HEX_ARRAY[b.toInt() ushr 4 and 0x0F]
hexChars[(i shl 1) + 1] = Utils.UPPER_HEX_ARRAY[(b and 0x0F).toInt()]
}
return String(hexChars)
}
fun ByteArray.toLowerHexString(): String {
val hexChars = CharArray(size * 2)
for (i in indices) {
val b = this[i]
hexChars[i shl 1] = Utils.LOWER_HEX_ARRAY[b.toInt() ushr 4 and 0x0F]
hexChars[(i shl 1) + 1] = Utils.LOWER_HEX_ARRAY[(b and 0x0F).toInt()]
}
return String(hexChars)
}
inline fun <T, R : Any> Iterable<T>.toSetNotNull(transform: (T) -> R?): Set<R> {
return HashSet<R>().apply { this@toSetNotNull.forEach { add(transform(it) ?: return@forEach) } }
}
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
inline fun <T> Any?.cast() = this as T
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
inline fun <reified T> Any?.castOrNull() = if (this is T) this else null
inline fun <T> T?.checkNull(ifNull: () -> Exception): T {
if (this == null) {
throw ifNull()
} else {
return this
}
}
fun String.emptyToNull() = if (isEmpty()) null else this
inline fun <reified T> getClazz() = T::class.java
fun Class<*>.isInheritanceFrom(parent: Class<*>) = parent.isAssignableFrom(this)
fun getClassName(jarPath: String): List<String> {
val myClassName = ArrayList<String>()
for (entry in JarFile(jarPath).entries()) {
val entryName = entry.name
if (entryName.endsWith(".class")) {
myClassName.add(entryName.replace("/", ".").substring(0, entryName.lastIndexOf(".")))
}
}
return myClassName
operator fun <T> (() -> T).unaryPlus() = object : () -> T {
override operator fun invoke() = this@unaryPlus()
override fun toString(): String = this@unaryPlus().toString()
}
fun <T> List<T>.binarySearch(comparison: (T) -> Int): T? {
val index = binarySearch(0, size, comparison)
return if (index < 0) null
else get(index)
fun String.toLowerCase(vararg indexes: Int): String {
val charArray = toCharArray()
indexes.forEach { index ->
charArray[index] = charArray[index].toLowerCase()
}
return String(charArray)
}
val cpuNumber = Runtime.getRuntime().availableProcessors()
fun String.simplifyPath(): String {
if (isEmpty()) {
return "."
fun String.toUpperCase(vararg indexes: Int): String {
val charArray = toCharArray()
indexes.forEach { index ->
charArray[index] = charArray[index].toUpperCase()
}
val pathList = split(java.io.File.separator).dropLastWhile { it.isEmpty() }
val list = LinkedList<String>()
for (path in pathList) {
if (path.isEmpty() || "." == path) {
continue
}
if (".." == path) {
list.pollLast()
continue
}
list.addLast(path)
}
var result = ""
while (list.size > 0) {
result += java.io.File.separator + list.pollFirst()!!
}
return if (result.isNotEmpty()) result else "."
return String(charArray)
}
//获取md5加密对象
val md5 by lazy { MessageDigest.getInstance("MD5")!! }
fun String.toLowerCase(indexes: IntRange): String {
val charArray = toCharArray()
indexes.forEach { index ->
charArray[index] = charArray[index].toLowerCase()
}
return String(charArray)
}
fun String.toUpperCase(indexes: IntRange): String {
val charArray = toCharArray()
indexes.forEach { index ->
charArray[index] = charArray[index].toUpperCase()
}
return String(charArray)
}
fun ByteArray.md5(): ByteArray {
//加密,返回字节数组
return md5.digest(this)
return Utils.md5.digest(this)
}
fun String.md5(): String = toByteArray().md5().toHexString()
//获取md5加密对象
val sha256 by lazy { MessageDigest.getInstance("SHA-256")!! }
fun ByteArray.sha256(): ByteArray {
//加密,返回字节数组
return sha256.digest(this)
return Utils.sha256.digest(this)
}
fun String.sha256(): String = toByteArray().sha256().toHexString()
//获取sha加密对象
val sha by lazy { MessageDigest.getInstance("SHA")!! }
fun ByteArray.sha(): ByteArray = sha.digest(this)
fun ByteArray.sha(): ByteArray = Utils.sha.digest(this)
fun String.sha(): String = toByteArray().sha().toHexString()
//获取sha1加密对象
val sha1 by lazy { MessageDigest.getInstance("SHA-1")!! }
fun ByteArray.sha1(): ByteArray = sha1.digest(this)
fun ByteArray.sha1(): ByteArray = Utils.sha1.digest(this)
fun String.sha1(): String = toByteArray().sha1().toHexString()
//获取sha384加密对象
val sha384 by lazy { MessageDigest.getInstance("SHA-384")!! }
fun ByteArray.sha384(): ByteArray = sha384.digest(this)
fun ByteArray.sha384(): ByteArray = Utils.sha384.digest(this)
fun String.sha384(): String = toByteArray().sha384().toHexString()
//获取 sha-512 加密对象
val sha512 by lazy { MessageDigest.getInstance("SHA-512")!! }
fun ByteArray.sha512(): ByteArray = sha512.digest(this)
fun ByteArray.sha512(): ByteArray = Utils.sha512.digest(this)
fun String.sha512(): String = toByteArray().sha512().toHexString()
fun ByteArray.toHexString(upper: Boolean = true): String = if (upper) toUpperHexString() else toLowerHexString()
private val UPPER_HEX_ARRAY = "0123456789ABCDEF".toCharArray()
fun ByteArray.toUpperHexString(): String {
val hexChars = CharArray(size * 2)
for (i in indices) {
val b = this[i]
hexChars[i shl 1] = UPPER_HEX_ARRAY[b.toInt() ushr 4 and 0x0F]
hexChars[(i shl 1) + 1] = UPPER_HEX_ARRAY[(b and 0x0F).toInt()]
}
return String(hexChars)
}
private val LOWER_HEX_ARRAY = "0123456789abcdef".toCharArray()
fun ByteArray.toLowerHexString(): String {
val hexChars = CharArray(size * 2)
for (i in indices) {
val b = this[i]
hexChars[i shl 1] = LOWER_HEX_ARRAY[b.toInt() ushr 4 and 0x0F]
hexChars[(i shl 1) + 1] = LOWER_HEX_ARRAY[(b and 0x0F).toInt()]
}
return String(hexChars)
}
fun String.fromHexString(): ByteArray {
val source = toLowerCase()
val data = ByteArray(length / 2)
for (i in 0 until length / 2) {
data[i] = ((LOWER_HEX_ARRAY.indexOf(source[i * 2]) shl 4) + LOWER_HEX_ARRAY.indexOf(source[i * 2 + 1])).toByte()
data[i] =
((Utils.UPPER_HEX_ARRAY.indexOf(source[i * 2]) shl 4) + Utils.UPPER_HEX_ARRAY.indexOf(source[i * 2 + 1])).toByte()
}
return data
}
fun ByteArray.toUTF8String() = String(this, Charsets.UTF_8)
fun String.base64(): String = this.toByteArray().base64().toUTF8String()
fun String.base64() = this.toByteArray().base64().toUTF8String()
fun ByteArray.base64(): ByteArray = Base64.getEncoder().encode(this)
fun String.base64Url(): String = this.toByteArray().base64Url().toUTF8String()
fun ByteArray.base64Url(): ByteArray = Base64.getUrlEncoder().encode(this)
fun String.base64Mime(): String = this.toByteArray().base64Mime().toUTF8String()
fun ByteArray.base64Mime(): ByteArray = Base64.getMimeEncoder().encode(this)
fun String.base64decode(): String = Base64.getDecoder().decode(this).toUTF8String()
fun String.base64decode() = Base64.getDecoder().decode(this).toUTF8String()
fun ByteArray.base64decode(): ByteArray = Base64.getDecoder().decode(this)
fun String.base64UrlDecode(): String = Base64.getUrlDecoder().decode(this).toUTF8String()
fun ByteArray.base64UrlDecode(): ByteArray = Base64.getUrlDecoder().decode(this)
@ -234,163 +234,56 @@ fun ByteArray.base64MimeDecode(): ByteArray = Base64.getMimeDecoder().decode(thi
fun String.digest(type: String) = toByteArray().digest(type)?.toHexString()
fun ByteArray.digest(type: String) = try {
//获取加密对象
val instance = MessageDigest.getInstance(type)
//加密,返回字节数组
instance.digest(this)
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
null
}
val random = Random()
fun randomInt() = random.nextInt()
fun randomInt(min: Int, max: Int): Int =
if (min > max) randomInt(max, min) else (random.nextInt() and Int.MAX_VALUE) % (max - min + 1) + min
fun randomLong() = random.nextLong()
fun randomLong(min: Long, max: Long) = (random.nextLong() and Long.MAX_VALUE) % (max - min + 1) + min
fun randomBoolean() = random.nextBoolean()
fun randomFloat() = random.nextFloat()
fun randomDouble() = random.nextDouble()
fun randomGaussian() = random.nextGaussian()
fun randomBytes(bytes: ByteArray) = random.nextBytes(bytes)
fun getTAG(cls: Class<*>): String {
return cls.name.split(".").last().dropLast(10)
}
operator fun <T> (() -> T).unaryPlus() = object : () -> T {
override fun invoke(): T = this@unaryPlus()
override fun toString() = this@unaryPlus().toString()
}
operator fun Executor.invoke(action: () -> Unit) {
execute(action)
}
operator fun Executor.invoke(action: Runnable) = this(action::run)
inline fun <reified T : Annotation> Field.getAnnotation(): T? = getAnnotation(T::class.java)
inline fun <reified T : Annotation> Class<*>.getAnnotation(): T? = getAnnotation(T::class.java)
fun process(size: Int, vararg actions: () -> Unit) {
actions.forEachIndexed { index, function ->
if (actions.size - index <= size) function()
}
}
fun <T> process(value: T, vararg actions: Pair<T, () -> Unit>) {
var checked = false
actions.forEach { (v, function) ->
if (checked || value == v) {
checked = true
function()
}
}
}
fun <T> T.println(): T {
println(this)
return this
}
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
inline fun <T> Any?.cast(): T = this as T
inline fun loop(`continue`: () -> Boolean = { true }, action: () -> Unit) {
while (`continue`()) action()
}
inline fun <reified T> getClazz() = T::class.java
@Suppress("NOTHING_TO_INLINE")
inline fun <R, T : Function<R>> lambda(lambda: T) = lambda
fun ByteArray.gz(): ByteArray {
val os = ByteArrayOutputStream()
GZIPOutputStream(os).use {
it.write(this)
}
return os.toByteArray()
}
fun ByteArray.ungz(): ByteArray {
return GZIPInputStream(ByteArrayInputStream(this)).readBytes()
}
fun ByteArray.undeflate(): ByteArray {
val infl = Inflater()
infl.setInput(this)
val bos = ByteArrayOutputStream()
val outByte = ByteArray(1024)
bos.use {
while (!infl.finished()) {
// 解压缩并将解压缩后的内容输出到字节输出流bos中
val len = infl.inflate(outByte)
if (len == 0) {
break
}
bos.write(outByte, 0, len)
}
infl.end()
}
return bos.toByteArray()
}
fun ByteArray.deflate(): ByteArray {
val defl = Deflater()
defl.setInput(this)
defl.finish()
val bos = ByteArrayOutputStream()
val outputByte = ByteArray(1024)
bos.use {
while (!defl.finished()) {
// 压缩并将压缩后的内容输出到字节输出流bos中
val len = defl.deflate(outputByte)
bos.write(outputByte, 0, len)
}
defl.end()
}
return bos.toByteArray()
}
//fun ByteArray.deflate(): ByteArray {
// val os = ByteArrayOutputStream()
// DeflaterOutputStream(os).use {
// it.write(this)
// }
// return os.toByteArray()
//}
//
//fun ByteArray.undeflate(): ByteArray {
// return DeflaterInputStream(ByteArrayInputStream(this)).readBytes()
//}
inline fun <reified T : Any?> Any.assert(action: T.() -> Unit): Boolean {
return if (this is T) {
action()
fun <A : Annotation, V : Any> A.changeAnnotationValue(field: KProperty1<A, V>, value: V): Boolean {
return try {
val h = Proxy.getInvocationHandler(this)
val memberValuesField = h.javaClass.getDeclaredField("memberValues")
memberValuesField.isAccessible = true
val memberValues = memberValuesField[h].cast<MutableMap<String, Any>>()
memberValues[field.name] = value
true
} else {
} catch (e: Exception) {
false
}
}
val Class<*>.allFields: List<Field>
get() {
var clazz = this
val list = ArrayList<Field>()
while (clazz != Any::class.java) {
list.addAll(clazz.declaredFields)
clazz = clazz.superclass
/**
* 向数据库提交一项任务并获取返回值
*/
suspend fun <T> Executor.runWith(action: () -> T): T = suspendCoroutine { cont ->
execute {
try {
cont.resume(action())
} catch (e: Exception) {
cont.resumeWithException(e)
}
list.addAll(clazz.declaredFields)
return list
}
}
fun Class<*>.forAllFields(action: (Field) -> Unit) {
inline fun <reified T : Any> Gson.fromJson(json: String): T = fromJson(json, T::class.java)
inline fun usingTime(action: () -> Unit): Long {
val t1 = System.currentTimeMillis()
action()
val t2 = System.currentTimeMillis()
return t2 - t1
}
inline fun usingNanoTime(action: () -> Unit): Long {
val t1 = System.nanoTime()
action()
val t2 = System.nanoTime()
return t2 - t1
}
inline fun Class<*>.forAllFields(action: (Field) -> Unit) {
var clazz = this
while (clazz != Any::class.java) {
clazz.declaredFields.forEach(action)
@ -399,14 +292,21 @@ fun Class<*>.forAllFields(action: (Field) -> Unit) {
clazz.declaredFields.forEach(action)
}
fun <T, R> Iterable<T>.firstNotNull(selector: (T) -> R): R? {
forEach {
return selector(it) ?: return@forEach
val Class<*>.allFields: List<Field>
get() {
val fieldList = ArrayList<Field>()
forAllFields(fieldList::add)
return fieldList
}
fun Class<*>.getFieldForAll(name: String): Field? {
forAllFields {
if (it.name == name) return it
}
return null
}
fun Class<*>.forAllMethods(action: (Method) -> Unit) {
inline fun Class<*>.forAllMethods(action: (Method) -> Unit) {
var clazz = this
while (clazz != Any::class.java) {
clazz.declaredMethods.forEach(action)
@ -415,14 +315,51 @@ fun Class<*>.forAllMethods(action: (Method) -> Unit) {
clazz.declaredMethods.forEach(action)
}
private val BASE62_DIGITS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray()
fun Class<*>.getMethodForAll(name: String, vararg parameterTypes: Class<*>?): Method? {
forAllMethods {
if (it.name == name && parameterTypes.contentEquals(it.parameterTypes)) return it
}
return null
}
val Class<*>.allMethods: List<Method>
get() {
val fieldList = ArrayList<Method>()
forAllMethods(fieldList::add)
return fieldList
}
/**
* 获取一个 KProperty<*> 对应的对象
*/
val KProperty<*>.receiver: Any?
get() = if (this is PropertyReference) {
boundReceiver
} else try {
Utils.receiverField.get(this)
} catch (e: Exception) {
null
} ?: javaClass.getFieldForAll("receiver")?.let {
it.isAccessible = true
it.get(this)
}
val KProperty<*>.owner: Class<*>?
get() = try {
Utils.ownerField.get(this)?.cast<Class<*>>()
} catch (e: Exception) {
null
} ?: javaClass.getFieldForAll("owner")?.let {
it.isAccessible = true
it.get(this)?.castOrNull()
}
tailrec fun Long.base62(sBuilder: StringBuilder = StringBuilder()): String {
return if (this == 0L) {
sBuilder.reverse().toString()
} else {
val remainder = (this % 62).toInt()
sBuilder.append(BASE62_DIGITS[remainder])
sBuilder.append(Utils.DIGITS[remainder])
(this / 62).base62(sBuilder)
}
}
@ -430,10 +367,208 @@ tailrec fun Long.base62(sBuilder: StringBuilder = StringBuilder()): String {
fun String.base62Decode(): Long {
var sum: Long = 0
val len = length
var base = 62L
var base = 1L
for (i in 0 until len) {
sum += BASE62_DIGITS.indexOf(this[len - i - 1]) * base
sum += Utils.DIGITS.indexOf(this[len - i - 1]) * base
base *= 62
}
return sum
}
fun Any.toJson(): String = Utils.gson.toJson(this)
fun Any.toPrettyJson(): String = Utils.prettyGson.toJson(this)
inline fun <reified T : Any> String.fromJson(): T = Utils.gson.fromJson(this, T::class.java)
fun Any.serialize(): ByteArray {
val outputStream = ByteArrayOutputStream()
ObjectOutputStream(outputStream).writeObject(this)
return outputStream.toByteArray()
}
operator fun <E> List<E>.get(startIndex: Int = 0, endIndex: Int = size, step: Int = 1): List<E> {
if (step <= 0) throw IllegalArgumentException("step($step) is negative or zero")
val fromIndex = when {
startIndex < 0 -> size + startIndex
startIndex >= size -> size
else -> startIndex
}
val toIndex = when {
endIndex < 0 -> size + endIndex + 1
endIndex >= size -> size
else -> endIndex
}
var targetList = if (fromIndex > toIndex) ReversedList(subList(toIndex, fromIndex)) else subList(fromIndex, toIndex)
if (step != 1) targetList = targetList step step
return targetList
}
operator fun <E> List<E>.get(intProgression: IntProgression): List<E> {
val first = intProgression.first
val last = intProgression.last
val step = intProgression.step
return when {
step == 0 -> get(first, last + if (last < 0) 0 else 1, 1)
step < 0 -> get(first + if (last > 0 && first >= 0) 1 else 0, last, -step)
else -> get(first, last + if (last < 0) 0 else 1, step)
}
}
infix fun <E> List<E>.step(step: Int): List<E> = StepList(this, step)
inline infix fun String.ifEmpty(ifEmpty: () -> String) = if (isNotEmpty()) this else ifEmpty()
inline infix fun String.ifBlank(ifBlank: () -> String) = if (isNotBlank()) this else ifBlank()
@JvmName("ifEmptyNullable")
inline fun String.ifEmpty(ifEmpty: () -> String?) = if (isNotEmpty()) this else ifEmpty()
@JvmName("ifBlankNullable")
inline fun String.ifBlank(ifBlank: () -> String?) = if (isNotBlank()) this else ifBlank()
/**
* 使用 condition 做条件判断如果返回 true 则使用 then 生成结果否则范湖自身
*/
inline fun <T> T.ifThen(condition: T.() -> Boolean, then: () -> T) = if (condition()) then() else this
@JvmName("ifThenNullable")
inline fun <T> T.ifThen(condition: T.() -> Boolean, then: () -> T?) = if (condition()) then() else this
inline fun <T> Any.wait(action: () -> T) = synchronized(this) {
val t = action()
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
(this as Object).wait()
t
}
inline fun <T> Any.notify(action: () -> T) = synchronized(this) {
val t = action()
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
(this as Object).notify()
t
}
inline fun <T> Any.notifyAll(action: () -> T) = synchronized(this) {
val t = action()
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
(this as Object).notifyAll()
t
}
inline val KClass<*>.companionObjectInstanceOrNull: Any?
get() = try {
companionObjectInstance
} catch (e: Exception) {
null
}
inline val <K : Any, V> Map<K?, V>.notNullKey get() = cast<Map<K, V>>()
inline val <K, V : Any> Map<K, V?>.notNullValue get() = cast<Map<K, V>>()
inline val <K : Any, V : Any> Map<K?, V?>.notNullEntry get() = cast<Map<K, V>>()
inline val <K : Any, V> Map<K?, V>.filterNullKey get() = filter { it.key != null }.notNullKey
inline val <K, V : Any> Map<K, V?>.filterNullValue get() = filter { it.value != null }.notNullValue
val <T : Any> KClass<T>.allMemberProperties: List<KProperty1<T, *>>
get() {
val propertiesList = memberProperties.toMutableList()
var superClass = superclasses.firstOrNull {
!it.java.isInterface
}
while (superClass != null) {
propertiesList.addAll(superClass.memberProperties.cast())
superClass = superClass.superclasses.firstOrNull {
!it.java.isInterface
}
}
return propertiesList
}
fun String.toStartWith(prefix: String) = if (startsWith(prefix)) this else prefix + this
fun String.toStartWith(prefix: Char) = if (startsWith(prefix)) this else prefix + this
fun mongoLegal(value: Any?) = when {
value == null -> true
value is Number -> true
value is Boolean -> true
value is Char -> true
value is String -> true
value is Serializable -> true
value.javaClass.kotlin.isData -> true
value.javaClass.name.endsWith("DTO") -> true
value.javaClass.name.endsWith("VO") -> true
else -> false
}
fun getCallerClass(thisClassName: List<String>): Class<*>? {
var clazz: Class<*>?
var callStackDepth = 1
do {
clazz = getCallerClass(callStackDepth++)
if (clazz?.name !in thisClassName) {
break
}
} while (clazz != null)
return clazz
}
fun getCallerClassName(thisClassName: List<String>): String? {
return getCallerClass(thisClassName)?.name
}
fun getCallerClass(callStackDepth: Int): Class<*>? {
@Suppress("DEPRECATION")
return Reflection.getCallerClass(callStackDepth)
}
fun getCallerClassName(callStackDepth: Int): String? {
return getCallerClass(callStackDepth)?.name
}
@OptIn(ExperimentalContracts::class)
fun CharSequence?.isNotNullOrEmpty(): Boolean {
contract {
returns(true) implies (this@isNotNullOrEmpty != null)
}
return this != null && this.isNotEmpty()
}
@OptIn(ExperimentalContracts::class)
fun Collection<*>?.isNotNullOrEmpty(): Boolean {
contract {
returns(true) implies (this@isNotNullOrEmpty != null)
}
return this != null && this.isNotEmpty()
}
//@OptIn(ExperimentalContracts::class)
//fun main() {
// val s: String? = ""
// if (s.isNotNullAndEmpty()) {
// println(s.length)
// }
//}
inline fun <reified T> Any?.assert(ifMatch: T.() -> Unit) = if (this is T) {
ifMatch()
true
} else {
false
}
val cpuNumber get() = Runtime.getRuntime().availableProcessors()
@Suppress("NOTHING_TO_INLINE")
inline fun <R, T : Function<R>> lambda(lambda: T) = lambda
val String.urlDecode: String get() = URLDecoder.decode(this, "utf-8")
val String.urlEncode: String get() = URLEncoder.encode(this, "utf-8")
fun <T> List<T>.binarySearch(comparison: (T) -> Int): T? {
val index = binarySearch(0, size, comparison)
return if (index < 0) null
else get(index)
}

View File

@ -0,0 +1,14 @@
package cn.tursom.core.datastruct
open class AbstractListIterator<E>(
val list: List<E>,
private var index: Int = 0
) : ListIterator<E> {
override fun hasNext(): Boolean = list.size > index
override fun next(): E = list[index++]
override fun nextIndex(): Int = index
override fun hasPrevious(): Boolean = index > 0
override fun previous(): E = list[--index]
override fun previousIndex(): Int = index - 1
}

View File

@ -0,0 +1,48 @@
package cn.tursom.core.datastruct
class ReversedList<E>(
val list: List<E>
) : List<E> by list {
override fun get(index: Int): E = list[size - index - 1]
override fun indexOf(element: E): Int {
val lastIndexOf = list.lastIndexOf(element)
return if (lastIndexOf >= 0) size - lastIndexOf else -1
}
override fun lastIndexOf(element: E): Int {
val indexOf = list.indexOf(element)
return if (indexOf >= 0) size - indexOf else -1
}
override fun iterator(): Iterator<E> = listIterator()
override fun listIterator(): ListIterator<E> = listIterator(0)
override fun listIterator(index: Int): ListIterator<E> = ReverseListIterator(list.listIterator(size - index))
override fun subList(fromIndex: Int, toIndex: Int): List<E> {
return ReversedList(list.subList(size - toIndex, size - fromIndex))
}
override fun toString(): String {
val iterator = iterator()
return buildString {
append('[')
iterator.forEach {
append(it)
if (iterator.hasNext()) append(", ")
}
append(']')
}
}
private class ReverseListIterator<E>(val listIterator: ListIterator<E>) : ListIterator<E> {
override fun hasNext(): Boolean = listIterator.hasPrevious()
override fun next(): E = listIterator.previous()
override fun nextIndex(): Int = listIterator.previousIndex()
override fun hasPrevious(): Boolean = listIterator.hasNext()
override fun previous(): E = listIterator.next()
override fun previousIndex(): Int = listIterator.nextIndex()
}
}

View File

@ -0,0 +1,49 @@
package cn.tursom.core.datastruct
class StepList<E>(
val list: List<E>,
val step: Int = 1,
) : List<E> by list {
init {
if (step <= 0) throw IllegalArgumentException("step is negative or zero")
}
override val size: Int
get() = when {
step == 1 -> list.size
list.isEmpty() -> 0
else -> list.size / step + if (list.size % step == 0) 0 else 1
}
override fun get(index: Int): E = list[index * step]
override fun indexOf(element: E): Int {
val indexOf = list.indexOf(element)
return if (indexOf >= 0) indexOf * step else -1
}
override fun lastIndexOf(element: E): Int {
val indexOf = list.lastIndexOf(element)
return if (indexOf >= 0) indexOf * step else -1
}
override fun iterator(): Iterator<E> = listIterator()
override fun listIterator(): ListIterator<E> = listIterator(0)
override fun listIterator(index: Int): ListIterator<E> =
if (step == 1) list.listIterator(index) else AbstractListIterator(this, index)
override fun subList(fromIndex: Int, toIndex: Int): List<E> =
StepList(list.subList(fromIndex * step, toIndex * step), step)
override fun toString(): String {
val iterator = iterator()
return buildString {
append('[')
iterator.forEach {
append(it)
if (iterator.hasNext()) append(", ")
}
append(']')
}
}
}

View File

@ -1,8 +1,8 @@
package cn.tursom.core.encrypt
import cn.tursom.core.Utils
import cn.tursom.core.datastruct.concurrent.BlockingArrayList
import cn.tursom.core.pool.Pool
import cn.tursom.core.randomInt
open class EncryptPool<T : Encrypt>(
initSize: Int = 0,
@ -20,5 +20,5 @@ open class EncryptPool<T : Encrypt>(
return aesPool.add(cache)
}
override fun get(): T = aesPool[randomInt(0, aesPool.size - 1)]
override fun get(): T = aesPool[Utils.random.nextInt(0, aesPool.size - 1)]
}

View File

@ -0,0 +1,4 @@
dependencies {
compile project(":")
api "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
}

View File

@ -0,0 +1,9 @@
package cn.tursom.delegation
import kotlin.reflect.KProperty
interface DecoratorDelegateProvider<in T, out V> :
DelegateProvider<T, DelegatedField<T, V>>,
DecoratorDelegatedField<T, V> {
override operator fun provideDelegate(thisRef: T, prop: KProperty<*>): DelegatedField<T, V> = delegatedField
}

View File

@ -0,0 +1,5 @@
package cn.tursom.delegation
interface DecoratorDelegatedField<in T, out V> {
val delegatedField: DelegatedField<T, V>
}

View File

@ -0,0 +1,11 @@
package cn.tursom.delegation
import kotlin.reflect.KProperty
interface DecoratorMutableDelegateProvider<in T, V> :
DelegateProvider<T, MutableDelegatedField<T, V>>,
//DecoratorProvideDelegate<T, V>,
DecoratorMutableDelegatedField<T, V> {
override operator fun provideDelegate(thisRef: T, prop: KProperty<*>): MutableDelegatedField<T, V> =
mutableDelegatedField
}

View File

@ -0,0 +1,6 @@
package cn.tursom.delegation
interface DecoratorMutableDelegatedField<in T, V> : DecoratorDelegatedField<T, V> {
val mutableDelegatedField: MutableDelegatedField<T, V>
override val delegatedField: DelegatedField<T, V> get() = mutableDelegatedField
}

View File

@ -0,0 +1,7 @@
package cn.tursom.delegation
import kotlin.reflect.KProperty
interface DelegateProvider<in T, out R> {
operator fun provideDelegate(thisRef: T, prop: KProperty<*>): R
}

View File

@ -0,0 +1,44 @@
package cn.tursom.delegation
import kotlin.reflect.KProperty
/**
* 这是用来规范kotlin委托属性的一个接口你可以用这个接口来针对属性进行硬编码级别的动态代理
* 比如如果你需要监控属性的变化可以使用 FieldChangeListener.listened 来定义属性
* 如果你还需要对这个属性进行加锁你就可以在后方加一个 .locked 即可
* 如果还需要用指定的锁在后面再加一个 (lock) 就玩成了
* 使用例
* class XXXImpl: XXX, FieldChangeListener by FieldChangeListenerImpl() {
* val lock = ReentrantLock()
* val field by listened(0).locker(lock)
* }
*/
interface DelegatedField<in T, out V> {
/**
* 用来获取值不会发生附加调用
*/
fun getValue(): V
operator fun getValue(thisRef: T, property: KProperty<*>): V = getValue()
operator fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? =
if (this is DecoratorDelegatedField<*, *>) {
delegatedField[key]
} else {
null
}
operator fun <V> set(key: DelegatedFieldAttachmentKey<V>, value: V): Boolean =
if (this is DecoratorDelegatedField<*, *>) {
delegatedField.set(key, value)
} else {
false
}
fun <V> removeAttachment(key: DelegatedFieldAttachmentKey<V>): Boolean =
if (this is DecoratorDelegatedField<*, *>) {
delegatedField.removeAttachment(key)
} else {
false
}
}

View File

@ -0,0 +1,3 @@
package cn.tursom.delegation
interface DelegatedFieldAttachmentKey<V>

View File

@ -0,0 +1,20 @@
package cn.tursom.delegation
import java.util.concurrent.Executor
import kotlin.reflect.KProperty
class ExecutorMutableDelegatedField<in T, V>(
override val mutableDelegatedField: MutableDelegatedField<T, V>,
private val executor: Executor,
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
executor.execute {
mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue)
}
}
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
valueOnSet(thisRef, property, value, getValue())
mutableDelegatedField.setValue(value)
}
}

View File

@ -0,0 +1,33 @@
package cn.tursom.delegation
import cn.tursom.core.cast
import kotlin.reflect.KProperty
class FilterDelegatedField<in T, V>(
override val mutableDelegatedField: MutableDelegatedField<T, V>,
private val filter: T.(old: V, new: V) -> Boolean,
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
companion object Key : DelegatedFieldAttachmentKey<Boolean>
private var filterResult = false
override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? {
return if (key == Key) filterResult.cast() else super.get(key)
}
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
filterResult = thisRef.filter(getValue(), value)
if (!filterResult) {
return
}
mutableDelegatedField.setValue(thisRef, property, value)
}
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
filterResult = thisRef.filter(getValue(), value)
if (!filterResult) {
return
}
mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue)
}
}

View File

@ -0,0 +1,10 @@
package cn.tursom.delegation
import kotlin.reflect.KProperty
class GetterDelegatedField<in T, out V>(
override val delegatedField: DelegatedField<T, V>,
private val getter: DelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V,
) : DelegatedField<T, V> by delegatedField, DecoratorDelegatedField<T, V> {
override fun getValue(thisRef: T, property: KProperty<*>): V = delegatedField.getter(thisRef, property)
}

View File

@ -0,0 +1,10 @@
package cn.tursom.delegation
import kotlin.reflect.KProperty
class GetterMutableDelegatedField<in T, V>(
override val mutableDelegatedField: MutableDelegatedField<T, V>,
private val getter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V,
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
override fun getValue(thisRef: T, property: KProperty<*>): V = mutableDelegatedField.getter(thisRef, property)
}

View File

@ -0,0 +1,9 @@
package cn.tursom.delegation
import kotlin.reflect.KProperty0
class KPropertyDelegatedField<in T, out V>(
val delegation: KProperty0<V>,
) : DelegatedField<T, V> {
override fun getValue(): V = delegation.get()
}

View File

@ -0,0 +1,10 @@
package cn.tursom.delegation
import kotlin.reflect.KMutableProperty0
class KPropertyMutableDelegatedField<in T, V>(
val delegation: KMutableProperty0<V>,
) : MutableDelegatedField<T, V> {
override fun getValue(): V = delegation.get()
override fun setValue(value: V) = delegation.set(value)
}

View File

@ -0,0 +1,28 @@
package cn.tursom.delegation
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
import kotlin.reflect.KProperty
class LockMutableDelegatedField<in T, V>(
override val mutableDelegatedField: MutableDelegatedField<T, V>,
private val lock: Lock = ReentrantLock(),
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
constructor(
initValue: V,
lock: Lock = ReentrantLock(),
) : this(MutableDelegatedFieldValue(initValue), lock)
override fun getValue(thisRef: T, property: KProperty<*>): V = lock.withLock {
mutableDelegatedField.getValue(thisRef, property)
}
override fun setValue(thisRef: T, property: KProperty<*>, value: V) = lock.withLock {
mutableDelegatedField.setValue(thisRef, property, value)
}
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) = lock.withLock {
mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue)
}
}

View File

@ -0,0 +1,25 @@
package cn.tursom.delegation
import kotlin.reflect.KProperty
interface MutableDelegatedField<in T, V> : DelegatedField<T, V> {
/**
* 用来设置值不会发生 valueOnSet调用
*/
fun setValue(value: V)
/**
* setter委托定义与其默认实现
*/
operator fun setValue(thisRef: T, property: KProperty<*>, value: V) {
valueOnSet(thisRef, property, value, getValue())
setValue(value)
}
/**
* 当值发生设置时应当被调用
* 流水线式调用
*/
fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {}
}

View File

@ -0,0 +1,17 @@
package cn.tursom.delegation
import kotlin.reflect.KProperty
open class MutableDelegatedFieldValue<in T, V>(
private var initValue: V
) : MutableDelegatedField<T, V> {
override fun getValue(): V = initValue
override fun getValue(thisRef: T, property: KProperty<*>): V = initValue
override fun setValue(value: V) {
initValue = value
}
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
initValue = value
}
}

View File

@ -0,0 +1,7 @@
package cn.tursom.delegation
import cn.tursom.core.cast
class NotNullDelegatedField<in T, out V : Any>(
override val delegatedField: DelegatedField<T, V?>,
) : DelegatedField<T, V> by delegatedField.cast(), DecoratorDelegatedField<T, V?>

View File

@ -0,0 +1,8 @@
package cn.tursom.delegation
import cn.tursom.core.cast
class NotNullMutableDelegatedField<in T, V : Any>(
override val mutableDelegatedField: MutableDelegatedField<T, V?>,
) : MutableDelegatedField<T, V> by mutableDelegatedField.cast(), DecoratorMutableDelegatedField<T, V?>

View File

@ -0,0 +1,43 @@
package cn.tursom.delegation
import java.util.concurrent.locks.ReadWriteLock
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.withLock
import kotlin.concurrent.write
import kotlin.reflect.KProperty
class ReadWriteLockMutableDelegatedField<in T, V>(
override val mutableDelegatedField: MutableDelegatedField<T, V>,
private val readWriteLock: ReadWriteLock = ReentrantReadWriteLock(),
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
constructor(
initValue: V,
readWriteLock: ReadWriteLock = ReentrantReadWriteLock(),
) : this(MutableDelegatedFieldValue(initValue), readWriteLock)
override fun getValue(thisRef: T, property: KProperty<*>): V {
val rl = readWriteLock.readLock()
rl.lock()
try {
return mutableDelegatedField.getValue(thisRef, property)
} finally {
rl.unlock()
}
}
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
if (readWriteLock is ReentrantReadWriteLock) readWriteLock.write {
mutableDelegatedField.setValue(thisRef, property, value)
} else readWriteLock.writeLock().withLock {
mutableDelegatedField.setValue(thisRef, property, value)
}
}
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
if (readWriteLock is ReentrantReadWriteLock) readWriteLock.write {
mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue)
} else readWriteLock.writeLock().withLock {
mutableDelegatedField.setValue(thisRef, property, value)
}
}
}

View File

@ -0,0 +1,8 @@
package cn.tursom.delegation
class SetterDelegatedField<T, V>(
override val delegatedField: DelegatedField<T, V>,
val setter: DelegatedField<T, V>.(value: V) -> Unit,
) : MutableDelegatedField<T, V>, DelegatedField<T, V> by delegatedField, DecoratorDelegatedField<T, V> {
override fun setValue(value: V) = delegatedField.setter(value)
}

View File

@ -0,0 +1,12 @@
package cn.tursom.delegation
import kotlin.reflect.KProperty
class SetterMutableDelegatedField<T, V>(
override val mutableDelegatedField: MutableDelegatedField<T, V>,
val setter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>, value: V) -> Unit,
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
mutableDelegatedField.setter(thisRef, property, value)
}
}

View File

@ -0,0 +1,14 @@
package cn.tursom.delegation
import cn.tursom.core.SimpThreadLocal
class SimpThreadLocalMutableDelegatedField<in T, V>(
private val threadLocal: SimpThreadLocal<V>,
val new: () -> V
) : MutableDelegatedField<T, V> {
constructor(new: () -> V) : this(SimpThreadLocal(new = new), new)
override fun setValue(value: V) = threadLocal.set(value)
override fun getValue(): V = threadLocal.get()
}

View File

@ -0,0 +1,8 @@
package cn.tursom.delegation
class ThreadLocalMutableDelegatedField<in T, V>(
private val threadLocal: ThreadLocal<V?> = ThreadLocal()
) : MutableDelegatedField<T, V?> {
override fun setValue(value: V?) = threadLocal.set(value)
override fun getValue(): V? = threadLocal.get()
}

View File

@ -0,0 +1,95 @@
@file:Suppress("unused")
package cn.tursom.delegation
import cn.tursom.core.SimpThreadLocal
import cn.tursom.core.cast
import cn.tursom.core.castOrNull
import cn.tursom.core.receiver
import java.util.concurrent.Executor
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReadWriteLock
import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty0
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty0
import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.isAccessible
fun getDelegate(obj: Any?, field: String): DelegatedField<*, *>? {
obj ?: return null
val kProperty1 = obj.javaClass.kotlin.memberProperties.firstOrNull { it.name == field }
kProperty1?.isAccessible = true
val delegate = kProperty1?.getDelegate(obj)
return delegate.castOrNull()
}
val <V> KProperty0<V>.getOwnerDelegated: DelegatedField<*, V>?
get() = getDelegate(receiver, name).castOrNull()
val <V> KProperty0<V>.getDelegatedValue: V?
get() {
val delegate = getDelegate() ?: getOwnerDelegated
return delegate?.castOrNull<DelegatedField<*, V>>()?.getValue()
}
fun <V> KProperty0<V>.setDelegatedValue(value: V): Boolean {
val delegate = getDelegate() ?: getOwnerDelegated
delegate.castOrNull<MutableDelegatedField<*, V>>()?.setValue(value) ?: return false
return true
}
/**
* 将可空属性委托为不可空属性
*/
fun <T, V> T.delegated(value: V): MutableDelegatedField<T, V> = MutableDelegatedFieldValue(value)
fun <T, V> T.delegated(@Suppress("UNUSED_PARAMETER") target: T, value: V): MutableDelegatedField<T, V> =
MutableDelegatedFieldValue(value)
val <V> KProperty0<V>.delegated: DelegatedField<Any, V> get() = KPropertyDelegatedField(this)
val <V> KMutableProperty0<V>.delegated: MutableDelegatedField<Any, V> get() = KPropertyMutableDelegatedField(this)
val <V : Any> KProperty0<V?>.delegatedNotNull get() = delegated.notNull
val <V : Any> KMutableProperty0<out V?>.delegatedNotNull: MutableDelegatedField<Any, V> get() = delegated.notNull
val <T, V : Any> DelegatedField<T, V?>.notNull: DelegatedField<T, V> get() = NotNullDelegatedField(this)
val <T, V : Any> MutableDelegatedField<T, out V?>.notNull: MutableDelegatedField<T, V>
get() = NotNullMutableDelegatedField(cast())
val <T, V> MutableDelegatedField<T, V>.locked: MutableDelegatedField<T, V> get() = LockMutableDelegatedField(this)
fun <T, V> MutableDelegatedField<T, V>.locked(lock: Lock = ReentrantLock()): MutableDelegatedField<T, V> =
LockMutableDelegatedField(this, lock)
val <T, V> MutableDelegatedField<T, V>.readWriteLocked: MutableDelegatedField<T, V>
get() = ReadWriteLockMutableDelegatedField(this)
fun <T, V> MutableDelegatedField<T, V>.readWriteLocked(readWriteLock: ReadWriteLock = ReentrantReadWriteLock()): MutableDelegatedField<T, V> =
ReadWriteLockMutableDelegatedField(this, readWriteLock)
fun <T, V> T.threadLocalDelegated(): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField()
fun <T, V> T.threadLocalDelegated(type: Class<V>): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField()
fun <T, V : Any> T.threadLocalDelegated(type: KClass<V>): MutableDelegatedField<T, V?> =
ThreadLocalMutableDelegatedField()
fun <T, V> T.threadLocalDelegated(new: () -> V): MutableDelegatedField<T, V> = SimpThreadLocalMutableDelegatedField(new)
fun <T, V> T.threadLocalDelegated(simpThreadLocal: SimpThreadLocal<V>, new: () -> V): MutableDelegatedField<T, V> =
SimpThreadLocalMutableDelegatedField(simpThreadLocal, new)
fun <T, V> MutableDelegatedField<T, V>.filter(filter: T.(old: V, new: V) -> Boolean): MutableDelegatedField<T, V> =
FilterDelegatedField(this, filter)
fun <T, V> DelegatedField<T, V>.setter(setter: DelegatedField<T, V>.(value: V) -> Unit): DelegatedField<T, V> =
SetterDelegatedField(this, setter)
fun <T, V> MutableDelegatedField<T, V>.setter(setter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>, value: V) -> Unit): MutableDelegatedField<T, V> =
SetterMutableDelegatedField(this, setter)
fun <T, V> DelegatedField<T, V>.getter(getter: DelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V): DelegatedField<T, V> =
GetterDelegatedField(this, getter)
fun <T, V> MutableDelegatedField<T, V>.getter(getter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V): MutableDelegatedField<T, V> =
GetterMutableDelegatedField(this, getter)
fun <T, V> MutableDelegatedField<T, V>.withExecutor(executor: Executor): MutableDelegatedField<T, V> =
ExecutorMutableDelegatedField(this, executor)

View File

@ -0,0 +1,4 @@
dependencies {
compile project(":")
compile project(":utils:delegation")
}

View File

@ -0,0 +1,10 @@
package cn.tursom.observer
/**
* 标识一个属性可以被指定的 FieldChangeListener 监听
* 属性的实现者应该实现相应的逻辑
*/
@RequiresOptIn
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
annotation class Observable

View File

@ -0,0 +1,64 @@
package cn.tursom.observer
import cn.tursom.core.cast
import cn.tursom.delegation.DecoratorMutableDelegatedField
import cn.tursom.delegation.DelegatedFieldAttachmentKey
import cn.tursom.delegation.MutableDelegatedField
import java.util.concurrent.ConcurrentLinkedDeque
import kotlin.reflect.KProperty
@Observable
class ObservableMutableDelegatedField<T, V>(
override val mutableDelegatedField: MutableDelegatedField<T, V>,
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
companion object : DelegatedFieldAttachmentKey<Boolean>
override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? {
return if (key == Companion) true.cast() else super.get(key)
}
private val listenerList = ConcurrentLinkedDeque<T.(old: V, new: V) -> Unit>()
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
val oldValue = getValue()
listenerList.forEach {
thisRef.it(oldValue, value)
}
mutableDelegatedField.setValue(thisRef, property, value)
}
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
listenerList.forEach {
thisRef.it(oldValue, value)
}
mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue)
}
fun addListener(listener: T.(old: V, new: V) -> Unit): Observer<T, V> {
var catch: (T.(old: V, new: V, e: Throwable) -> Unit)? = null
var finally: (T.(old: V, new: V) -> Unit)? = null
listenerList.add { old, new ->
try {
listener(old, new)
} catch (e: Throwable) {
catch?.invoke(this, old, new, e)
} finally {
finally?.invoke(this, old, new)
}
}
return object : Observer<T, V> {
override fun cancel() = listenerList.remove(listener)
override fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): Observer<T, V> {
catch = handler
return this
}
override fun finally(handler: T.(old: V, new: V) -> Unit): Observer<T, V> {
finally = handler
return this
}
}
}
}

View File

@ -0,0 +1,6 @@
package cn.tursom.observer
interface ObservableObserver<out T, V> : Observer<T, V> {
infix fun addListener(listener: T.(old: V, new: V) -> Unit): Observer<T, V>
override fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): ObservableObserver<T, V>
}

View File

@ -0,0 +1,7 @@
package cn.tursom.observer
interface Observer<out T, V> {
fun cancel(): Boolean
infix fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): Observer<T, V>
infix fun finally(handler: T.(old: V, new: V) -> Unit): Observer<T, V>
}

View File

@ -0,0 +1,14 @@
package cn.tursom.observer
class UnmonitoredFieldException : Exception {
constructor() : super()
constructor(message: String?) : super(message)
constructor(message: String?, cause: Throwable?) : super(message, cause)
constructor(cause: Throwable?) : super(cause)
constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super(
message,
cause,
enableSuppression,
writableStackTrace
)
}

View File

@ -0,0 +1,120 @@
package cn.tursom.observer
import cn.tursom.core.cast
import cn.tursom.core.receiver
import cn.tursom.delegation.*
import java.util.concurrent.ConcurrentLinkedQueue
import kotlin.reflect.KMutableProperty0
import kotlin.reflect.KProperty0
import kotlin.reflect.jvm.isAccessible
@Observable
fun <V> KMutableProperty0<V>.listenable(): MutableDelegatedField<Any, V> {
isAccessible = true
val delegate = getDelegate()
return if (delegate is MutableDelegatedField<*, *> && delegate[ObservableMutableDelegatedField] == true) {
delegate.cast()
} else {
ObservableMutableDelegatedField(KPropertyMutableDelegatedField(cast()))
}
}
@Observable
fun <V> listenable(initValue: V): MutableDelegatedField<Any, V> = ObservableMutableDelegatedField(
MutableDelegatedFieldValue(initValue)
)
@Observable
fun <T, V> MutableDelegatedField<T, V>.listenable(): MutableDelegatedField<T, V> =
ObservableMutableDelegatedField(this)
@OptIn(Observable::class)
fun <V> KProperty0<V>.getListenableMutableDelegatedField(): ObservableMutableDelegatedField<Any, V>? {
isAccessible = true
var delegate = getDelegate() ?: getDelegate(receiver, name)
if (delegate is DelegatedField<*, *>) {
while (true) {
if (delegate is ObservableMutableDelegatedField<*, *>) {
return delegate.cast()
}
if (delegate is DecoratorDelegatedField<*, *>) {
delegate = delegate.delegatedField
} else {
break
}
}
} else if (delegate is KProperty0<*>) {
return delegate.cast<KProperty0<V>>().getListenableMutableDelegatedField()
}
return null
}
inline fun <T, V> T.addChangeListener(
property: T.() -> KProperty0<V>,
): ObservableObserver<T, V> {
val kProperty0 = property()
@OptIn(Observable::class)
val delegatedField = kProperty0
.getListenableMutableDelegatedField()
.cast<ObservableMutableDelegatedField<T, V>?>()
?: throw UnmonitoredFieldException(kProperty0.toString())
return object : ObservableObserver<T, V> {
private val selfList = ConcurrentLinkedQueue<Observer<T, V>>()
override fun addListener(listener: T.(old: V, new: V) -> Unit): Observer<T, V> {
@OptIn(Observable::class)
val listener1 = delegatedField.addListener(listener)
selfList.add(listener1)
return listener1
}
override fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): ObservableObserver<T, V> {
selfList.forEach {
it.catch(handler)
}
return this
}
override fun cancel(): Boolean {
selfList.forEach {
it.cancel()
}
return true
}
override fun finally(handler: T.(old: V, new: V) -> Unit): Observer<T, V> {
selfList.forEach {
it.finally(handler)
}
return this
}
}
}
infix operator fun <T, V> ObservableObserver<T, V>.invoke(listener: T.(old: V, new: V) -> Unit): Observer<T, V> =
addListener(listener)
infix fun <T, V> ObservableObserver<T, V>.with(listener: T.(old: V, new: V) -> Unit): Observer<T, V> =
addListener(listener)
infix fun <T, V> ObservableObserver<T, V>.and(listener: T.(old: V, new: V) -> Unit): Observer<T, V> =
addListener(listener)
infix operator fun <T, V> ObservableObserver<T, V>.plus(listener: T.(old: V, new: V) -> Unit): Observer<T, V> =
addListener(listener)
infix fun <V> KProperty0<V>.listen(listener: Any.(old: V, new: V) -> Unit): Observer<Any, V> {
@OptIn(Observable::class)
return getListenableMutableDelegatedField()
?.addListener(listener)
?: throw UnmonitoredFieldException(toString())
}
fun <T, V> T.listen(property: KProperty0<V>, listener: T.(old: V, new: V) -> Unit): Observer<Any, V> {
@OptIn(Observable::class)
return property.getListenableMutableDelegatedField()
?.addListener(listener.cast())
?: throw UnmonitoredFieldException(toString())
}

View File

@ -1,6 +1,6 @@
package cn.tursom.utils.asynclock
import cn.tursom.core.unsafe
import cn.tursom.core.Unsafe.unsafe
import java.io.Closeable
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume

View File

@ -9,9 +9,9 @@ package cn.tursom.utils.bytebuffer
* will support
*/
import cn.tursom.core.Unsafe.unsafe
import cn.tursom.core.buffer.ByteBuffer
import cn.tursom.core.isStatic
import cn.tursom.core.unsafe
class UnsupportedException : Exception()

View File

@ -1,7 +1,7 @@
package cn.tursom.web.router.impl
import cn.tursom.core.binarySearch
import cn.tursom.web.router.*
import cn.tursom.web.router.Router
import cn.tursom.web.router.impl.colonnode.AnyColonNode
import cn.tursom.web.router.impl.colonnode.ColonNode
import cn.tursom.web.router.impl.colonnode.IColonNode
@ -29,31 +29,31 @@ class ColonRouter<T> : Router<T> {
routeNode = when {
r.isEmpty() -> routeNode
r == "*" -> routeNode.wildSubRouter ?: {
r == "*" -> routeNode.wildSubRouter ?: run {
val node = AnyColonNode<T>(routeList, index)
routeNode.wildSubRouter = node
index = routeList.size - 1
node
}()
}
r[0] == ':' -> run {
val node = synchronized(routeNode.placeholderRouterList!!) {
val matchLength = PlaceholderColonNode.matchLength(routeList, index)
routeNode.placeholderRouterList!!.binarySearch { it.size - matchLength } ?: {
routeNode.placeholderRouterList!!.binarySearch { it.size - matchLength } ?: run {
routeNode.addNode(routeList, index, null)
routeNode.placeholderRouterList!!.binarySearch { it.size - matchLength }!!
}()
}
}
index += node.size - 1
node
}
else -> synchronized(routeNode.subRouterMap) {
routeNode.subRouterMap[r] ?: {
routeNode.subRouterMap[r] ?: run {
val node = ColonNode<T>(routeList, index)
routeNode.subRouterMap[r] = node
node
}()
}
}
}
index++