ByteRange

reads, resolves and writes Range header values in the bytes range unit (RFC 9110 §14.1). A server answers a satisfiable range with a 206 carrying a ContentRange header, and an unsatisfiable one with a 416.

(match (ByteRange.parse "bytes=0-499, -200")
  (Result.Success specs)
    (let [rs (ByteRange.resolve &specs 1000l)]
      (if (Array.empty? &rs) (println* "416") (println* &rs)))
  (Result.Error e) (IO.errorln &e))

parse

defn

(Fn [(Ref String a)] (Result (Array ByteRangeSpec) String))

                        (parse s)
                    

parses a Range header value into its range-specs, in header order, as (Result (Array ByteRangeSpec) String).

Only the bytes range unit is understood; unit names are compared case-insensitively. Whitespace around the commas of the range-set is ignored, as are empty list elements (RFC 9110 §5.6.1.2). An unknown unit, an empty range-set, and a spec that is syntactically invalid — including a last-pos below its first-pos — all fail, which for a server means serving the whole representation, since RFC 9110 §14.2 has it ignore the header field then.

resolve

defn

(Fn [(Ref (Array ByteRangeSpec) a), Long] (Array (Pair Long Long)))

                        (resolve specs len)
                    

maps specs and the length len of the representation to the byte positions they select, as inclusive [first last] Pairs in spec order (RFC 9110 §14.1.1).

A last-pos past the end clamps to len - 1, and a suffix-length of len or more selects the whole representation. Specs that select nothing — a first-pos at or past the end, a suffix-length of 0, anything at all when len is 0 — are dropped, so an empty result for a non-empty specs is the 416 Range Not Satisfiable case.

str

defn

(Fn [(Ref (Array ByteRangeSpec) a)] String)

                        (str specs)
                    

serializes specs into a Range header value, e.g. bytes=0-499, -200, which parse reads back into an equal array. specs should hold at least one spec: RFC 9110 §14.1.1 has no empty range-set.