Skip to content
Merged
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
181 changes: 166 additions & 15 deletions lib/src/main/kotlin/net/llvg/llvg_utils/type/Class-utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -25,45 +26,94 @@ public inline val <T : Any> T.jClass: Class<out T>
get() = cast(cast<Object>().`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<T>().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 <T> Class<*>.isExtend(
type: Class<T>
): 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<out @NoInfer T>? =
if (isExtend<T>()) asSubclass(T::class.java) else null
if (isExtend<T>()) asSubclass(jClass<T>()) 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 <T> Class<*>.asExtend(
type: Class<T>
): Class<out @NoInfer T>? =
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<T>())", "net.llvg.llvg_utils.type.jClass"))
public inline fun <@PureReifiable reified T> Class<*>.toExtend(): Class<out @NoInfer T> =
asSubclass(T::class.java)
asSubclass(jClass<T>())

/**
* 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 <T> Class<*>.toExtend(
type: Class<T>
): Class<out @NoInfer T> =
asSubclass(type)

/**
* Casts the receiver [Class] to subclass of type [T] if possible, otherwise returns `null`
Expand All @@ -76,6 +126,107 @@ public inline fun <@PureReifiable reified T> Class<*>.toExtend(): Class<out @NoI
* @see isExtend
*/
@InlineOnly
@Deprecated("", ReplaceWith("asExtend<T>()", "net.llvg.llvg_utils.asExtend"))
@Deprecated("", ReplaceWith("asExtend<T>()", "net.llvg.llvg_utils.type.asExtend"))
public inline fun <@PureReifiable reified T> Class<*>.tryExtend(): Class<out @NoInfer T>? =
if (isExtend<T>()) asSubclass(T::class.java) else null
if (isExtend<T>()) 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<T>().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 <T> Any.isInType(
type: Class<T>
): 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<Int>()) jClass<T>().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 <T> Any.asTyped(
type: Class<T>
): @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<T>().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 <T> Any.toTyped(
type: Class<T>
): @NoInfer T =
type.cast(this)