Skip to main content

parse_range

Function parse_range 

Source
pub fn parse_range(range: &str, size: u64) -> Result<(u64, u64), ()>
Expand description

Parses an HTTP Range header into absolute byte offsets.

Implements a subset of HTTP range request syntax (RFC 7233), supporting only simple byte ranges without multi-part or suffix ranges.

§Supported Syntax

  • Bounded range: bytes=<start>-<end> (both offsets specified)
    • Example: bytes=0-1023 → Returns (0, 1023)
  • Unbounded range: bytes=<start>- (from start to EOF)
    • Example: bytes=1024- → Returns (1024, size-1)

§Unsupported Syntax

  • Suffix range: bytes=-<length> (last N bytes)
    • Example: bytes=-1024 → Returns Err(())
  • Multi-part range: bytes=0-100,200-300
    • Example: bytes=0-100,200-300 → Returns Err(())

These are rejected because:

  1. They are rarely used in practice (<1% of range requests)
  2. They add significant parsing and response generation complexity
  3. The HTTP 416 error response is acceptable for clients that need them

§Arguments

  • range: The value of the Range header (e.g., "bytes=0-1023")
  • size: The total size of the stream in bytes (used to validate offsets)

§Returns

  • Ok((start, end)): Valid range with absolute byte offsets (both inclusive)
  • Err(()): Invalid syntax or out-of-bounds range

§Error Conditions

Returns Err(()) if:

  1. Missing prefix: Header does not start with "bytes="
    • Example: "items=0-100" → Error
  2. Invalid integer: Start or end cannot be parsed as u64
    • Example: "bytes=abc-def" → Error
  3. Inverted range: Start offset is greater than end offset
    • Example: "bytes=1000-500" → Error
  4. Out of bounds: End offset is beyond the stream size
    • Example: "bytes=0-999999" when size is 1000 → Error

§Parsing Algorithm

1. Check for "bytes=" prefix (RANGE_PREFIX_LEN = 6)
2. Split remaining string on '-' delimiter
3. Parse start offset (parts[0])
4. Parse end offset (parts[1] if present and non-empty, else size-1)
5. Validate: start <= end && end < size
6. Return (start, end)

§Edge Cases

§Empty String After Prefix

Range: bytes=

Returns Err(()) because there is no start offset.

§Single Byte Range

Range: bytes=0-0

Returns Ok((0, 0)) (valid, requests exactly 1 byte).

§Range at EOF

Range: bytes=0-999 (size = 1000)

Returns Ok((0, 999)) (valid, end is inclusive and equals size - 1).

§Range Beyond EOF

Range: bytes=0-1000 (size = 1000)

Returns Err(()) because offset 1000 does not exist (valid range is 0-999).

§Examples

parse_range("bytes=0-1023", 10000)  -> Ok((0, 1023))
parse_range("bytes=1024-", 10000)   -> Ok((1024, 9999))
parse_range("0-1023", 10000)        -> Err(())   // missing "bytes=" prefix
parse_range("bytes=0-10000", 10000) -> Err(())   // out of bounds
parse_range("bytes=1000-500", 10000)-> Err(())   // inverted range

§Performance

  • Time complexity: O(n) where n is the length of the range string (typically <20 chars)
  • Allocation: One heap allocation for the split('-') iterator’s internal state
  • Typical latency: <1 μs (negligible compared to snapshot read latency)

§Security

This function is resilient to malicious input:

  • Integer overflow: u64::parse rejects values >2^64-1
  • Unbounded length: The Range header is bounded by HTTP header size limits (typically 8 KB, enforced by the HTTP server)
  • No allocation attacks: Uses only one small allocation for splitting