I can check if R::class == List::class but I can not check if R::class == List<Int>::class

val byteArray = byteArrayOf(1, 2, 3, 4, 8, 7, 0, 1, 2, 3.......)

// Define a generic function that returns a R from the byteArray
inline fun <reified R> getValue(): R {
    // Create a ByteBuffer from the byteArray
    val buffer = ByteBuffer.wrap(byteArray)
    // Return the value of the buffer as the specified type R
    return when (R::class) {
        Int::class -> buffer.int as R
        Float::class -> buffer.float as R
        Double::class -> buffer.double as R
        List::class -> {  // I want to the if R is a List<Int>
            val size = buffer.getInt() // first 4 bytes define the size of items.
        }
        else -> throw IllegalArgumentException("Unsupported type")
    }
}

// Test the function with different types
fun main() {
    println(getValue<Int>()) // 16909060
    println(getValue<Float>()) // 2.3879393E-38
    println(getValue<Double>()) // 8.20788039913184E-317
    println(getValue<List<Int>>()) // [16909060] // this does not work
}

I don’t know if there is a better way, but we can use KType:

List::class -> {
  val t = typeOf<R>().arguments[0]
  if (t.type?.classifier == Int::class) {
    return listOf(1, 2, 3, 4) as R
  }
  throw IllegalArgumentException("Unsupported type")
}

Thanks :+1:

How about this one:

inline fun <reified R> getValue(): R {
	val buffer = ByteBuffer.wrap(byteArray)
	return when (typeOf<R>()) {
		typeOf<Int>() -> buffer.int as R
		typeOf<Float>() -> buffer.float as R
		typeOf<Double>() -> buffer.double as R
		typeOf<List<Int>>() -> {
			val size = buffer.int
			val array = IntArray(size)
			buffer.asIntBuffer()[array, 0, size]
			array.toList() as R
		}
		else -> throw IllegalArgumentException("Unsupported type")
	}
}

Not sure if the list implementation is totally correct, was written without testing, but you get the idea how you can case match with typeOf() :slight_smile:

1 Like

Oh wow, that looks sooo much better :slight_smile:

I would be a little concerned about the performance. My gut feeling is that acquiring KTypes and comparing them will be pretty slow, at least in relation to comparing classes.

Also, please be aware in this case we compare by both the type and its variance. In some cases we might expect such behavior, in others we might not. List is a special case, because it specifies variance at declaration site, but still getValue<List<out Int>> will fail with this solution.

BTW, this buffer.asIntBuffer()[array, 0, size] line is super confusing, it is one of the worst Kotlin code fragments I ever saw and initially I was surprised this is even possible :smiley: I assume you put it there as a funny “easter egg”.

2 Likes