From 5448c2748bad2e92a1a31d6c61e1865f02ba32a9 Mon Sep 17 00:00:00 2001 From: Water-OR Date: Thu, 26 Jun 2025 20:33:25 +0800 Subject: [PATCH] feat: improve type-utils --- .../net/llvg/llvg_utils/type/Class-utils.kt | 181 ++++++++++++++++-- 1 file changed, 166 insertions(+), 15 deletions(-) diff --git a/lib/src/main/kotlin/net/llvg/llvg_utils/type/Class-utils.kt b/lib/src/main/kotlin/net/llvg/llvg_utils/type/Class-utils.kt index b23e3d2..4f9d3cc 100644 --- a/lib/src/main/kotlin/net/llvg/llvg_utils/type/Class-utils.kt +++ b/lib/src/main/kotlin/net/llvg/llvg_utils/type/Class-utils.kt @@ -2,6 +2,7 @@ package net.llvg.llvg_utils.type +import kotlin.contracts.contract import kotlin.internal.InlineOnly import kotlin.internal.NoInfer import kotlin.internal.PureReifiable @@ -25,45 +26,94 @@ public inline val T.jClass: Class get() = cast(cast().`class`) /** - * Check if the receiver [Class] is extended from type [T] + * Check if the receiver [Class] is extended from class [T] * * @receiver The [Class] being checked - * @param T The type to check against + * @param T The class to check against * - * @return `true` if the receiver [Class] is extended from type [T], otherwise `false` + * @return `true` if the receiver [Class] is extended from class [T], otherwise `false` * * @see asExtend */ @InlineOnly public inline fun <@PureReifiable reified T> Class<*>.isExtend(): Boolean = - T::class.java.isAssignableFrom(this) + jClass().isAssignableFrom(this) /** - * Casts the receiver [Class] to subclass of type [T] if possible, otherwise returns `null` + * Check if the receiver [Class] is extended from class [type] + * + * @receiver The [Class] being checked + * @param type The class to check against + * + * @return `true` if the receiver [Class] is extended from class [type], otherwise `false` + * + * @see asExtend + */ +@InlineOnly +public inline fun Class<*>.isExtend( + type: Class +): Boolean = + type.isAssignableFrom(this) + +/** + * Casts the receiver [Class] to subclass of class [T] if possible, otherwise returns `null` * * @receiver The [Class] to attempt casting on - * @param T The target type to cast to + * @param T The target class to cast to * - * @return The receiver [Class] being cast to subclass of type [T] if possible, otherwise `null` + * @return The receiver [Class] being cast to subclass of class [T] if possible, otherwise `null` * * @see isExtend */ @InlineOnly public inline fun <@PureReifiable reified T> Class<*>.asExtend(): Class? = - if (isExtend()) asSubclass(T::class.java) else null + if (isExtend()) asSubclass(jClass()) else null + +/** + * Casts the receiver [Class] to subclass of class [type] if possible, otherwise returns `null` + * + * @receiver The [Class] to attempt casting on + * @param type The target class to cast to + * + * @return The receiver [Class] being cast to subclass of class [type] if possible, otherwise `null` + * + * @see isExtend + */ +@InlineOnly +public inline fun Class<*>.asExtend( + type: Class +): Class? = + if (isExtend(type)) asSubclass(type) else null /** - * Casts the receiver [Class] to subclass of type [T] + * Casts the receiver [Class] to subclass of class [T] * * @receiver The [Class] to attempt casting on - * @param T the target type to cast to + * @param T the target class to cast to * - * @return The receiver [Class] being cast to subclass of type [T] - * @throws ClassCastException If the receiver [Class] can not be cast to subclass of type [T] + * @return The receiver [Class] being cast to subclass of class [T] + * @throws ClassCastException If the receiver [Class] can not be cast to subclass of class [T] */ @InlineOnly +@Deprecated("", ReplaceWith("asSubclass(jClass())", "net.llvg.llvg_utils.type.jClass")) public inline fun <@PureReifiable reified T> Class<*>.toExtend(): Class = - asSubclass(T::class.java) + asSubclass(jClass()) + +/** + * Casts the receiver [Class] to subclass of class [type] + * + * @receiver The [Class] to attempt casting on + * @param type the target class to cast to + * + * @return The receiver [Class] being cast to subclass of class [type] + * @throws ClassCastException If the receiver [Class] can not be cast to subclass of class [type] + */ +@InlineOnly +@Deprecated("", ReplaceWith("asSubclass(type)")) +public inline fun Class<*>.toExtend( + type: Class +): Class = + asSubclass(type) /** * Casts the receiver [Class] to subclass of type [T] if possible, otherwise returns `null` @@ -76,6 +126,107 @@ public inline fun <@PureReifiable reified T> Class<*>.toExtend(): Class()", "net.llvg.llvg_utils.asExtend")) +@Deprecated("", ReplaceWith("asExtend()", "net.llvg.llvg_utils.type.asExtend")) public inline fun <@PureReifiable reified T> Class<*>.tryExtend(): Class? = - if (isExtend()) asSubclass(T::class.java) else null \ No newline at end of file + if (isExtend()) asSubclass(T::class.java) else null + +/** + * Check if the receiver object is in class [T] + * + * @receiver The object being checked + * @param T The type to check against + * + * @return `true` if the receiver object is in class [T], otherwise `false` + * + * @see asExtend + */ +@InlineOnly +public inline fun <@PureReifiable reified T> Any.isInType(): Boolean { + contract { + returns(true) implies (this@isInType is T) + } + + return jClass().isInstance(this) +} + +/** +[ * Check if the receiver object is in class [type] +] * + * @receiver The object being checked + * @param T The type to check against + * + * @return `true` if the receiver object is in class [type], otherwise `false` + * + * @see asExtend + */ +@InlineOnly +public inline fun Any.isInType( + type: Class +): Boolean { + return type.isInstance(this) +} + +/** + * Casts the receiver object to instance of class [T] if possible, otherwise returns `null` + * + * @receiver The object to attempt casting on + * @param T The target class to cast to + * + * @return The receiver object being cast to instance of class [T] if possible, otherwise `null` + * + * @see isExtend + */ +@InlineOnly +public inline fun <@PureReifiable reified T> Any.asTyped(): @NoInfer T? { + contract { + returnsNotNull() implies (this@asTyped is T) + } + + return if (isInType()) jClass().cast(this) else null +} + +/** + * Casts the receiver object to instance of class [type] if possible, otherwise returns `null` + * + * @receiver The object to attempt casting on + * @param T The target class to cast to + * + * @return The receiver object being cast to instance of class [type] if possible, otherwise `null` + * + * @see isExtend + */ +@InlineOnly +public inline fun Any.asTyped( + type: Class +): @NoInfer T? = + if (isInType(type)) type.cast(this) else null + +/** + * Casts the receiver object to instance of class [T] + * + * @receiver The object to attempt casting on + * @param T The target class to cast to + * + * @return The receiver object being cast to instance of class [T] + * + * @see isExtend + */ +@InlineOnly +public inline fun <@PureReifiable reified T> Any.toTyped(): @NoInfer T = + jClass().cast(this) + +/** + * Casts the receiver object to instance of class [type] + * + * @receiver The object to attempt casting on + * @param T The target class to cast to + * + * @return The receiver object being cast to instance of class [type] + * + * @see isExtend + */ +@InlineOnly +public inline fun Any.toTyped( + type: Class +): @NoInfer T = + type.cast(this) \ No newline at end of file