KotlinRangeable

May 10, 2026 · View on GitHub

JitPack Kotlin JVM License

Reference Kotlin/JVM implementation of Rangeable<Element> — a generic, integer-coordinate, closed-interval set container with first-insert ordered active queries.

Installation

Add JitPack to your repositories and depend on the tagged release:

// settings.gradle.kts
dependencyResolutionManagement {
    repositories {
        mavenCentral()
        maven("https://jitpack.io")
    }
}

// build.gradle.kts
dependencies {
    implementation("com.github.ZhgChgLi:KotlinRangeable:v1.0.0")
}

Or in Groovy DSL:

repositories {
    maven { url 'https://jitpack.io' }
}
dependencies {
    implementation 'com.github.ZhgChgLi:KotlinRangeable:v1.0.0'
}

Usage

import io.github.zhgchgli.rangeable.Rangeable

data class Strong(val tag: String = "strong")
data class Italic(val tag: String = "italic")
data class Link(val url: String)

val r = Rangeable<Any>()
r.insert(Strong(), start = 2, end = 5)
r.insert(Strong(), start = 3, end = 7)        // merges with [2, 5] → [2, 7]
r.insert(Strong(), start = 9, end = 11)       // disjoint
r.insert(Italic(), start = 3, end = 8)

r.getRange(Strong())        // [Interval(2, 7), Interval(9, 11)]
r.getRange(Italic())        // [Interval(3, 8)]

r[4].objs                   // [Strong(...), Italic(...)]   first-insert order
r[8].objs                   // [Italic(...)]
r[10].objs                  // [Strong(...)]

Sweep iteration via transitions

for (event in r.transitions(from = 0, to = 15)) {
    println("${event.coordinate} ${event.kind} ${event.element}")
}

API

MemberReturnsNotes
Rangeable<E : Any>()constructorempty container
r.insert(e, start, end)Rangeable<E> (chainable)throws InvalidIntervalException on start > end
r[i]Slot<E>Slot.objs is the active-set list
r.getRange(e)List<Interval>merged disjoint ranges
r.transitions(from, to)List<TransitionEvent<E>>to = null means +∞
r.sizeIntdistinct elements
r.isEmptyBoolean
for (pair in r)Iterator<Pair<E, List<Interval>>>first-insert order
r.copy()Rangeable<E>deep copy
r.versionIntunchanged on idempotent insert

Element equality

Rangeable<E : Any> keys elements by equals / hashCode. Kotlin data class auto-generates these from primary-constructor properties, which is the easiest way to satisfy the contract:

data class Strong(val tag: String = "strong")  // Strong() == Strong()
data class Link(val url: String)               // Link("a") != Link("b")

For non-data classes, override equals and hashCode consistently per RFC §4.2 (E1–E5).

Semantics

  • End is inclusive: insert(e, start = a, end = b) covers a..b, both ends.
  • Same-element merging: equal elements merge on overlap or integer adjacency. [2, 4] ∪ [5, 7] = [2, 7].
  • Idempotent insert: re-inserting a contained interval does not bump version.
  • Out-of-order rejected: insert(e, 5, 2) throws InvalidIntervalException.
  • Active-set ordering: deterministic — first-insert order of the element.
  • Coordinate sentinel: a close event for an interval ending at the optional intMaxSentinel carries coordinate == null (null == +∞ per RFC §4.7).

See RangeableRFC § 4 for normative semantics and § 10 for the 23-case test contract.

Cross-language consistency

This Kotlin implementation joins the Ruby, Swift, Python, JS and Go implementations. All six share a 160-op / 86-probe JSON fixture and produce byte-identical outputs.

See also

Development

./gradlew test            # run JUnit5 suite
./gradlew jar             # produce build/libs/rangeable-1.0.0.jar
./gradlew publishToMavenLocal   # smoke-test publishing config

The suite covers the full RFC § 10 contract, the cross-language fixture replay (org.json-based parser), and a property test against a brute-force oracle.

License

MIT (c) ZhgChgLi

Buy me a beer ❤️❤️❤️

Buy Me A Beer

If this project has helped you, feel free to sponsor me a cup of coffee, thank you.