///|
/// Resolve byte specs against the selected representation length.
pub fn resolve_byte_ranges(
request : RangeRequest,
representation_length : Int64,
) -> Result[ResolvedRangeSet, RangeError] {
if representation_length < 0L {
return Err(
range_error(
Resolve,
InvalidRepresentationLength,
0,
"representation length cannot be negative",
),
)
}
if !request.unit().is_bytes() {
return Err(
range_error(
Resolve,
UnsupportedRangeUnit,
0,
"only bytes ranges have defined resolution semantics",
),
)
}
let resolved : Array[ConcreteRange] = []
let mut unsatisfiable = 0
let specs = request.specs()
for spec in specs {
match resolve_one(spec, representation_length) {
Some(range) => resolved.push(range)
None => unsatisfiable = unsatisfiable + 1
}
}
Ok(resolved_range_set(resolved, unsatisfiable, specs.length()))
}
///|
fn resolve_one(spec : ByteRangeSpec, length : Int64) -> ConcreteRange? {
if length <= 0L {
return None
}
match spec {
Closed(first, requested_last) => {
if first >= length {
return None
}
let last = if requested_last >= length {
length - 1L
} else {
requested_last
}
Some(concrete_range(first, last))
}
OpenEnded(first) =>
if first >= length {
None
} else {
Some(concrete_range(first, length - 1L))
}
Suffix(suffix_length) => {
if suffix_length <= 0L {
return None
}
let selected = if suffix_length >= length {
length
} else {
suffix_length
}
Some(concrete_range(length - selected, length - 1L))
}
}
}