package ru.dbotthepony.kstarbound.util import ru.dbotthepony.kstarbound.io.json.EitherTypeAdapter /** * Представляет собой контейнер с "или тот или другой" значениями * * JSON адаптер реализуется через [EitherTypeAdapter] */ class Either private constructor(val left: KOptional, val right: KOptional) { val isLeft: Boolean get() = left.isPresent val isRight: Boolean get() = right.isPresent inline fun map(left: (L) -> T, right: (R) -> T): T { this.left.ifPresent { return left.invoke(it) } return right.invoke(this.right.value) } inline fun flatMap(left: (L) -> NL, right: (R) -> NR): Either { 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 left(value: L): Either { return Either(KOptional.of(value), KOptional.empty()) } @JvmStatic fun right(value: R): Either { return Either(KOptional.empty(), KOptional.of(value)) } } }