« Stardust 6 | Fail-Safety »


Key Features of Stardust 6

Primitive Conclude Types

Using results for error handling has become widely established and also Stardust makes heavy use of it. In Stardust, results are of the Conclude type. Since the JVM makes a difference between reference types and primitive types, Stardust 6 now provides additional result types, such as ConcludeInt, as well as corresponding utilities especially for primitive types to avoid unnecessary boxing and unboxing. This includes all primitive types of the JVM, such as Boolean or Int, and also the unsigned integer types introduced by Kotlin, such as UInt.

Examples

The following subsections contains some examples for the Int type.

Creating Primitive Concludes

We can create a ConcludeInt using the following functions:

fun successIntOf(value: Int): SuccessInt

fun <Error> failureIntOf(reason: Error): FailureInt<Error>

With these functions, we can create SuccessInt and FailureInt instances of ConcludeInt:

fun nonNegative(value: Int): ConcludeInt<String> =
    if(value < 0) failureIntOf("Invalid value!")
    else successIntOf(value)

val value: Int = nonNegative(4711).orThrow()

Parsing a Number

Stardust provides the String.parseInt function that parses the given string into an integer and returns a ConcludeInt:

// Returns `ConcludeInt` of the primitive `Int` type
fun String.parseInt(radix: Int = 10): ConcludeInt<NumberFormatFault>

Let's use this function to parse an integer value. The API of ConcludeInt is identical to the generic Conclude type.

// Parse an integer into the primitive Conclude type `ConcludeInt<*>`
val parsingResult: ConcludeInt<NumberFormatFault> = "4711".parseInt()

// Retrieve the parsed value from the parsing result
val parsedValue: Int = parsingResult.orThrow()

Collection Utils for Primitive Concludes

There are lots of utils available to map and filter collections and sequences containing primitive Concludes.

// Create a list of parsing results
val parsingResults: List<ConcludeInt<NumberFormatFault>> =
    listOf("4711".parseInt(), "foo".parseInt(), "815".parseInt())

// Filter all `SuccessInt` results
val parsedValues: List<Int> = parsingResults.filterSuccessInt() // Yields: [4711, 815]

Boxing and Unboxing

If it is required to convert between generic and primitive Conclude types, you can use the box() and unbox() functions:


// Converts a `ConcludeInt<*>` into a `Conclude<Int, *>` val boxedParsingResult: Conclude<Int, NumberFormatFault> = parsingResult.box() // Converts a `Conclude<Int, *>` into a `ConcludeInt<*>` val unboxedParsingResult1: ConcludeInt<NumberFormatFault> = boxedParsingResult.unbox() // If the compiler for whatever reason cannot infer the primitive type correctly, // you can use the explicit named variant: `unboxInt` val unboxedParsingResult2: ConcludeInt<NumberFormatFault> = boxedParsingResult.unboxInt()

Test Utils

There are also test utils for primitive Concludes available in the stardustx-test module:

fun assertIsSuccess(result: ConcludeInt<*>, message: String? = null): Int

fun <Error> assertIsFailure(result: ConcludeInt<Error>, message: String? = null): Error

« Stardust 6 | Fail-Safety »