All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.HalfOpenRange.kt Maven / Gradle / Ivy

package io.fluidsonic.stdlib

// TODO add all special cases for Char, Double, Float, Long, UInt, ULong


public interface HalfOpenRange> {

	public val start: Bound
	public val endExclusive: Bound


	public operator fun contains(value: Bound): Boolean =
		value >= start && value < endExclusive


	public fun isEmpty(): Boolean =
		start >= endExclusive


	public companion object
}


public fun > HalfOpenRange.contains(other: HalfOpenRange): Boolean =
	contains(other.start) && other.endExclusive <= endExclusive


public fun > HalfOpenRange.flipped(): HalfOpenRange =
	endExclusive rangeToExcluding start


public fun > HalfOpenRange.intersection(other: HalfOpenRange): HalfOpenRange? =
	overlaps(other).thenTake { maxOf(start, other.start) rangeToExcluding minOf(endExclusive, other.endExclusive) }


public fun > HalfOpenRange.overlaps(other: HalfOpenRange): Boolean =
	contains(other.start) || other.contains(start)


public inline fun > HalfOpenRange.mapBounds(transform: (Bound) -> Int): HalfOpenIntRange =
	transform(start) rangeToExcluding transform(endExclusive)


public inline fun , R : Comparable> HalfOpenRange.mapBounds(transform: (Bound) -> R): HalfOpenRange =
	transform(start) rangeToExcluding transform(endExclusive)


public fun > HalfOpenRange.subtracting(rangeToSubtract: HalfOpenRange): List> {
	if (rangeToSubtract.start >= endExclusive || rangeToSubtract.endExclusive <= start)
		return listOf(this)

	val result = mutableListOf>()
	if (rangeToSubtract.start > start)
		result.add(start rangeToExcluding rangeToSubtract.start)
	if (rangeToSubtract.endExclusive < endExclusive)
		result.add(rangeToSubtract.endExclusive rangeToExcluding endExclusive)

	return result
}


public fun > HalfOpenRange.toSequence(nextFunction: (Bound) -> Bound?): Sequence =
	when {
		isEmpty() -> emptySequence()
		else -> generateSequence(start) { start ->
			nextFunction(start)?.takeIf { value -> contains(value) }
		}
	}


private class HalfOpenComparableRange>(
	override val start: Bound,
	override val endExclusive: Bound
) : HalfOpenRange {

	operator fun component1() =
		start


	operator fun component2() =
		endExclusive


	override fun equals(other: Any?) =
		this === other || (other is HalfOpenRange<*> && start == other.start && endExclusive == other.endExclusive)


	override fun hashCode() =
		hash { start x endExclusive }


	override fun toString() =
		"$start ..< $endExclusive"
}


public infix fun > Bound.rangeToExcluding(that: Bound): HalfOpenRange =
	HalfOpenComparableRange(this, that)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy