|
| 1 | +@file:OptIn(ExperimentalUnsignedTypes::class) |
| 2 | + |
| 3 | +package org.jetbrains.kotlinx.dataframe.impl.columns |
| 4 | + |
| 5 | +import org.jetbrains.kotlinx.dataframe.ColumnDataHolder |
| 6 | +import org.jetbrains.kotlinx.dataframe.impl.asList |
| 7 | +import org.jetbrains.kotlinx.dataframe.impl.isPrimitiveArray |
| 8 | +import kotlin.reflect.KType |
| 9 | +import kotlin.reflect.typeOf |
| 10 | + |
| 11 | +internal class ColumnDataHolderImpl<T> private constructor( |
| 12 | + private val list: List<T>, |
| 13 | + distinct: Lazy<Set<T>>?, |
| 14 | +) : ColumnDataHolder<T> { |
| 15 | + |
| 16 | + override val distinct = distinct ?: lazy { list.toSet() } |
| 17 | + override val size: Int get() = list.size |
| 18 | + |
| 19 | + override fun toSet(): Set<T> = distinct.value |
| 20 | + override fun toList(): List<T> = list |
| 21 | + override fun get(index: Int): T = list[index] |
| 22 | + override fun get(range: IntRange): List<T> = list.subList(range.first, range.last + 1) |
| 23 | + override fun contains(value: T): Boolean = list.contains(value) |
| 24 | + override fun iterator(): Iterator<T> = list.iterator() |
| 25 | + |
| 26 | + companion object { |
| 27 | + |
| 28 | + /** |
| 29 | + * Constructs [ColumnDataHolderImpl] using an [asList] wrapper around the [list]. |
| 30 | + */ |
| 31 | + @Suppress("UNCHECKED_CAST") |
| 32 | + internal fun <T> of(list: Collection<T>, type: KType, distinct: Lazy<Set<T>>? = null): ColumnDataHolder<T> { |
| 33 | + if (list is ColumnDataHolder<*>) return list as ColumnDataHolder<T> |
| 34 | + |
| 35 | + try { |
| 36 | + val newList = when (type) { |
| 37 | + BOOLEAN -> (list as Collection<Boolean>).toBooleanArray().asList() |
| 38 | + BYTE -> (list as Collection<Byte>).toByteArray().asList() |
| 39 | + SHORT -> (list as Collection<Short>).toShortArray().asList() |
| 40 | + INT -> (list as Collection<Int>).toIntArray().asList() |
| 41 | + LONG -> (list as Collection<Long>).toLongArray().asList() |
| 42 | + FLOAT -> (list as Collection<Float>).toFloatArray().asList() |
| 43 | + DOUBLE -> (list as Collection<Double>).toDoubleArray().asList() |
| 44 | + CHAR -> (list as Collection<Char>).toCharArray().asList() |
| 45 | + UBYTE -> (list as Collection<UByte>).toUByteArray().asList() |
| 46 | + USHORT -> (list as Collection<UShort>).toUShortArray().asList() |
| 47 | + UINT -> (list as Collection<UInt>).toUIntArray().asList() |
| 48 | + ULONG -> (list as Collection<ULong>).toULongArray().asList() |
| 49 | + else -> list.asList() |
| 50 | + } as List<T> |
| 51 | + |
| 52 | + return ColumnDataHolderImpl(newList, distinct) |
| 53 | + } catch (e: Exception) { |
| 54 | + throw IllegalArgumentException("Can't create ColumnDataHolder from $list and type $type", e) |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + /** |
| 59 | + * Constructs [ColumnDataHolderImpl] using an [asList] wrapper around the [array]. |
| 60 | + * If [array] is an array of primitives, it will be converted to a primitive array first before being |
| 61 | + * wrapped with [asList]. |
| 62 | + */ |
| 63 | + @Suppress("UNCHECKED_CAST") |
| 64 | + internal fun <T> of(array: Array<T>, type: KType, distinct: Lazy<Set<T>>? = null): ColumnDataHolder<T> { |
| 65 | + try { |
| 66 | + val list = when (type) { |
| 67 | + BOOLEAN -> (array as Array<Boolean>).toBooleanArray().asList() |
| 68 | + BYTE -> (array as Array<Byte>).toByteArray().asList() |
| 69 | + SHORT -> (array as Array<Short>).toShortArray().asList() |
| 70 | + INT -> (array as Array<Int>).toIntArray().asList() |
| 71 | + LONG -> (array as Array<Long>).toLongArray().asList() |
| 72 | + FLOAT -> (array as Array<Float>).toFloatArray().asList() |
| 73 | + DOUBLE -> (array as Array<Double>).toDoubleArray().asList() |
| 74 | + CHAR -> (array as Array<Char>).toCharArray().asList() |
| 75 | + UBYTE -> (array as Array<UByte>).toUByteArray().asList() |
| 76 | + USHORT -> (array as Array<UShort>).toUShortArray().asList() |
| 77 | + UINT -> (array as Array<UInt>).toUIntArray().asList() |
| 78 | + ULONG -> (array as Array<ULong>).toULongArray().asList() |
| 79 | + else -> array.asList() |
| 80 | + } as List<T> |
| 81 | + |
| 82 | + return ColumnDataHolderImpl(list, distinct) |
| 83 | + } catch (e: Exception) { |
| 84 | + throw IllegalArgumentException( |
| 85 | + "Can't create ColumnDataHolder from $array and mismatching type $type", |
| 86 | + e |
| 87 | + ) |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + /** |
| 92 | + * Constructs [ColumnDataHolderImpl] using an [asList] wrapper around the [primitiveArray]. |
| 93 | + * [primitiveArray] must be an array of primitives, returns `null` if something goes wrong. |
| 94 | + */ |
| 95 | + @Suppress("UNCHECKED_CAST") |
| 96 | + internal fun <T> of(primitiveArray: Any, type: KType, distinct: Lazy<Set<T>>? = null): ColumnDataHolder<T> { |
| 97 | + val newList = when { |
| 98 | + type == BOOLEAN && primitiveArray is BooleanArray -> primitiveArray.asList() |
| 99 | + type == BYTE && primitiveArray is ByteArray -> primitiveArray.asList() |
| 100 | + type == SHORT && primitiveArray is ShortArray -> primitiveArray.asList() |
| 101 | + type == INT && primitiveArray is IntArray -> primitiveArray.asList() |
| 102 | + type == LONG && primitiveArray is LongArray -> primitiveArray.asList() |
| 103 | + type == FLOAT && primitiveArray is FloatArray -> primitiveArray.asList() |
| 104 | + type == DOUBLE && primitiveArray is DoubleArray -> primitiveArray.asList() |
| 105 | + type == CHAR && primitiveArray is CharArray -> primitiveArray.asList() |
| 106 | + type == UBYTE && primitiveArray is UByteArray -> primitiveArray.asList() |
| 107 | + type == USHORT && primitiveArray is UShortArray -> primitiveArray.asList() |
| 108 | + type == UINT && primitiveArray is UIntArray -> primitiveArray.asList() |
| 109 | + type == ULONG && primitiveArray is ULongArray -> primitiveArray.asList() |
| 110 | + !primitiveArray.isPrimitiveArray -> throw IllegalArgumentException( |
| 111 | + "Can't create ColumnDataHolder from non primitive array $primitiveArray and type $type" |
| 112 | + ) |
| 113 | + |
| 114 | + else -> throw IllegalArgumentException( |
| 115 | + "Can't create ColumnDataHolder from primitive array $primitiveArray and type $type" |
| 116 | + ) |
| 117 | + } as List<T> |
| 118 | + |
| 119 | + return ColumnDataHolderImpl(newList, distinct) |
| 120 | + } |
| 121 | + } |
| 122 | +} |
| 123 | + |
| 124 | +private val BOOLEAN = typeOf<Boolean>() |
| 125 | +private val BYTE = typeOf<Byte>() |
| 126 | +private val SHORT = typeOf<Short>() |
| 127 | +private val INT = typeOf<Int>() |
| 128 | +private val LONG = typeOf<Long>() |
| 129 | +private val FLOAT = typeOf<Float>() |
| 130 | +private val DOUBLE = typeOf<Double>() |
| 131 | +private val CHAR = typeOf<Char>() |
| 132 | +private val UBYTE = typeOf<UByte>() |
| 133 | +private val USHORT = typeOf<UShort>() |
| 134 | +private val UINT = typeOf<UInt>() |
| 135 | +private val ULONG = typeOf<ULong>() |
0 commit comments