(** Range request parsing and Content-Range response writing per RFC 7233. *) (** {1 Types} *) (** A single byte range specification. Use query functions ([is_range], [is_suffix], [is_open]) to inspect the kind. *) type byte_range = { kind : int ; start : int64 ; end_ : int64 } (** Maximum number of ranges that can be parsed. *) val max_ranges : int (** Empty byte_range for array initialization. *) val empty : byte_range (** {2 Range Queries} *) (** Returns true if this is a standard range with explicit start and end. *) val is_range : byte_range -> bool (** Returns true if this is a suffix range (last N bytes). *) val is_suffix : byte_range -> bool (** Returns true if this is an open-ended range (start to EOF). *) val is_open : byte_range -> bool (** Parse status. *) type parse_status = | Valid | Invalid (** A resolved byte range with concrete start/end positions. *) type resolved = { start : int64 (** First byte position (0-indexed) *) ; end_ : int64 (** Last byte position (inclusive) *) ; length : int64 (** Number of bytes: end_ - start + 1 *) } (** Empty resolved range for array initialization. *) val empty_resolved : resolved (** Range evaluation result. *) type eval_result = | Full_content (** Serve full content *) | Single_range (** Single range - use first resolved *) | Multiple_ranges (** Multiple ranges - use resolved array *) | Not_satisfiable (** 416 error *) (** {1 Parsing} *) (** Parse Range header value into array of byte_ranges. Returns (status, count) where count is number of ranges parsed. Only supports "bytes" unit. *) val parse : Base_bigstring.t -> Span.t -> byte_range array -> parse_status * int (** Parse Range header from a string. Creates a local buffer internally. *) val parse_string : string -> byte_range array -> parse_status * int (** {1 Range Resolution} *) (** Evaluate ranges and determine result. Returns (result, resolved_count). Resolved ranges are written to the output array. *) val evaluate : byte_range array -> count:int -> resource_length:int64 -> resolved array -> eval_result * int (** Resolve a single byte_range against resource length. Returns (valid, resolved) where valid indicates if range is satisfiable. *) val resolve_range : byte_range -> resource_length:int64 -> bool * resolved (** {1 Response Writing} *) (** Write [Accept-Ranges: bytes\r\n] header. Returns new offset. *) val write_accept_ranges : Base_bigstring.t -> off:int -> int (** Write [Accept-Ranges: none\r\n] header. Returns new offset. *) val write_accept_ranges_none : Base_bigstring.t -> off:int -> int (** Write [Content-Range: bytes start-end/total\r\n] header. *) val write_content_range : Base_bigstring.t -> off:int -> start:int64 -> end_:int64 -> total:int64 -> int (** Write Content-Range header from resolved range. *) val write_content_range_resolved : Base_bigstring.t -> off:int -> resolved -> total:int64 -> int (** Write [Content-Range: bytes * /total\r\n] header for 416 responses. *) val write_content_range_unsatisfiable : Base_bigstring.t -> off:int -> total:int64 -> int (** {1 Multipart Helpers} *) (** Write multipart boundary line: [--boundary\r\n]. *) val write_multipart_boundary : Base_bigstring.t -> off:int -> boundary:string -> int (** Write final multipart boundary: [--boundary--\r\n]. *) val write_multipart_final : Base_bigstring.t -> off:int -> boundary:string -> int (** Generate a random boundary string suitable for multipart responses. *) val generate_boundary : unit -> string