///|
/// Return a copy sorted by inclusive first position, then last position.
pub fn sort_ranges(input : Array[ConcreteRange]) -> Array[ConcreteRange] {
let ranges = input.copy()
ranges.sort_by(fn(a, b) {
if a.first() < b.first() {
-1
} else if a.first() > b.first() {
1
} else if a.last() < b.last() {
-1
} else if a.last() > b.last() {
1
} else {
0
}
})
ranges
}
///|
/// Merge overlapping ranges, preserving gaps and not merging adjacency.
pub fn merge_overlapping_ranges(
input : Array[ConcreteRange],
) -> Array[ConcreteRange] {
merge_sorted(input, false)
}
///|
/// Merge ranges that overlap or touch at one byte boundary.
pub fn merge_adjacent_ranges(
input : Array[ConcreteRange],
) -> Array[ConcreteRange] {
merge_sorted(input, true)
}
///|
/// Server-side planning helper: sort, then merge overlap and adjacency.
pub fn coalesce_ranges(input : Array[ConcreteRange]) -> Array[ConcreteRange] {
merge_sorted(input, true)
}
///|
fn merge_sorted(
input : Array[ConcreteRange],
include_adjacent : Bool,
) -> Array[ConcreteRange] {
let sorted = sort_ranges(input)
let output : Array[ConcreteRange] = []
for current in sorted {
if output.is_empty() {
output.push(current)
continue
}
let previous = output[output.length() - 1]
let overlap = current.first() <= previous.last()
let adjacent = include_adjacent &&
previous.last() != @int64.MAX_VALUE &&
current.first() == previous.last() + 1L
if overlap || adjacent {
let last = if current.last() > previous.last() {
current.last()
} else {
previous.last()
}
output[output.length() - 1] = concrete_range(previous.first(), last)
} else {
output.push(current)
}
}
output
}