82 lines
1.8 KiB
Kotlin
82 lines
1.8 KiB
Kotlin
package ru.dbotthepony.kstarbound.util
|
||
|
||
import ru.dbotthepony.kstarbound.io.json.EitherTypeAdapter
|
||
|
||
/**
|
||
* Представляет собой контейнер с "или тот или другой" значениями
|
||
*
|
||
* JSON адаптер реализуется через [EitherTypeAdapter]
|
||
*/
|
||
class Either<L, R> private constructor(val left: KOptional<L>, val right: KOptional<R>) {
|
||
val isLeft: Boolean get() = left.isPresent
|
||
val isRight: Boolean get() = right.isPresent
|
||
|
||
inline fun <T> map(left: (L) -> T, right: (R) -> T): T {
|
||
this.left.ifPresent {
|
||
return left.invoke(it)
|
||
}
|
||
|
||
return right.invoke(this.right.value)
|
||
}
|
||
|
||
inline fun <NL, NR> flatMap(left: (L) -> NL, right: (R) -> NR): Either<NL, NR> {
|
||
this.left.ifPresent {
|
||
return left(left.invoke(it))
|
||
}
|
||
|
||
return right(right.invoke(this.right.value))
|
||
}
|
||
|
||
/**
|
||
* @throws NoSuchElementException
|
||
*/
|
||
fun left(): L = left.value
|
||
|
||
/**
|
||
* @throws NoSuchElementException
|
||
*/
|
||
fun right(): R = right.value
|
||
|
||
inline fun leftOrElse(orElse: () -> L): L {
|
||
if (isLeft)
|
||
return left()
|
||
else
|
||
return orElse.invoke()
|
||
}
|
||
|
||
inline fun rightOrElse(orElse: () -> R): R {
|
||
if (isRight)
|
||
return right()
|
||
else
|
||
return orElse.invoke()
|
||
}
|
||
|
||
override fun equals(other: Any?): Boolean {
|
||
return other === this || other is Either<*, *> && other.left == left && other.right == right
|
||
}
|
||
|
||
override fun hashCode(): Int {
|
||
return left.hashCode() * 31 + right.hashCode()
|
||
}
|
||
|
||
override fun toString(): String {
|
||
if (isLeft) {
|
||
return "Either.left[${left.value}]"
|
||
} else {
|
||
return "Either.right[${right.value}]"
|
||
}
|
||
}
|
||
|
||
companion object {
|
||
@JvmStatic
|
||
fun <L, R> left(value: L): Either<L, R> {
|
||
return Either(KOptional.of(value), KOptional.empty())
|
||
}
|
||
|
||
@JvmStatic
|
||
fun <L, R> right(value: R): Either<L, R> {
|
||
return Either(KOptional.empty(), KOptional.of(value))
|
||
}
|
||
}
|
||
}
|