1use fslite_core::ByteRange;
6
7#[derive(Debug, Eq, PartialEq)]
9pub enum RangeError {
10 Malformed,
12 MultiRangeUnsupported,
14 Unsatisfiable,
16}
17
18pub fn resolve_range(header: &str, logical_size: u64) -> Result<ByteRange, RangeError> {
23 let spec = header.strip_prefix("bytes=").ok_or(RangeError::Malformed)?;
24 if spec.contains(',') {
25 return Err(RangeError::MultiRangeUnsupported);
26 }
27
28 let (start_str, end_str) = spec.split_once('-').ok_or(RangeError::Malformed)?;
29
30 if start_str.is_empty() {
31 let suffix_len: u64 = end_str.parse().map_err(|_| RangeError::Malformed)?;
33 if suffix_len == 0 {
34 return Err(RangeError::Malformed);
35 }
36 let start = logical_size.saturating_sub(suffix_len);
37 return Ok(ByteRange::new(start, logical_size));
38 }
39
40 let start: u64 = start_str.parse().map_err(|_| RangeError::Malformed)?;
41 if start >= logical_size {
42 return Err(RangeError::Unsatisfiable);
43 }
44
45 let end = if end_str.is_empty() {
46 logical_size
47 } else {
48 let inclusive_end: u64 = end_str.parse().map_err(|_| RangeError::Malformed)?;
49 if inclusive_end < start {
52 return Err(RangeError::Malformed);
53 }
54 inclusive_end.saturating_add(1).min(logical_size)
55 };
56
57 Ok(ByteRange::new(start, end))
58}