diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/parse.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/parse.kt index 04fb4d4ea0..0999f76337 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/parse.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/parse.kt @@ -56,6 +56,8 @@ import kotlin.reflect.full.withNullability import kotlin.reflect.jvm.jvmErasure import kotlin.reflect.typeOf import kotlin.time.Duration +import kotlin.uuid.ExperimentalUuidApi +import kotlin.uuid.Uuid import java.time.Duration as JavaDuration import java.time.Instant as JavaInstant import java.time.LocalDate as JavaLocalDate @@ -426,6 +428,7 @@ internal object Parsers : GlobalParserOptions { } } + @OptIn(ExperimentalUuidApi::class) internal val parsersOrder = listOf( // Int stringParser { it.toIntOrNull() }, @@ -491,6 +494,21 @@ internal object Parsers : GlobalParserOptions { posixParserToDoubleWithOptions, // Boolean stringParser { it.toBooleanOrNull() }, + // UUID + stringParser { str -> + + val uuidRegex = Regex("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}") + + if (uuidRegex.matches(str)) { + try { + Uuid.parse(str) + } catch (e: IllegalArgumentException) { + null + } + } else { + null + } + }, // BigInteger stringParser { it.toBigIntegerOrNull() }, // BigDecimal diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/parse.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/parse.kt index 081e28d078..dc2d2bc495 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/parse.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/parse.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlinx.dataframe.api import io.kotest.matchers.should import io.kotest.matchers.shouldBe +import io.kotest.matchers.shouldNotBe import kotlinx.datetime.DateTimeUnit import kotlinx.datetime.Instant import kotlinx.datetime.LocalDate @@ -28,6 +29,8 @@ import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.nanoseconds import kotlin.time.Duration.Companion.seconds +import kotlin.uuid.ExperimentalUuidApi +import kotlin.uuid.Uuid import java.time.Duration as JavaDuration import java.time.Instant as JavaInstant @@ -481,6 +484,28 @@ class ParseTests { df.parse() } + @OptIn(ExperimentalUuidApi::class) + @Test + fun `parse valid Uuid`() { + val validUUID = "550e8400-e29b-41d4-a716-446655440000" + val column by columnOf(validUUID) + val parsed = column.parse() + + parsed.type() shouldBe typeOf() + (parsed[0] as Uuid).toString() shouldBe validUUID // Change UUID to Uuid + } + + @OptIn(ExperimentalUuidApi::class) + @Test + fun `parse invalid Uuid`() { + val invalidUUID = "this is not a UUID" + val column = columnOf(invalidUUID) + val parsed = column.tryParse() // tryParse as string is not formatted. + + parsed.type() shouldNotBe typeOf() + parsed.type() shouldBe typeOf() + } + /** * Asserts that all elements of the iterable are equal to each other */