1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use ehttpd::{
bytes::DataParseExt,
error,
error::Error,
http::{Request, RequestExt},
};
use std::{ops::RangeInclusive, str};
pub trait RequestRangeExt {
fn range(&self) -> Result<Option<RangeInclusive<u64>>, Error>;
}
impl<'a, const HEADER_SIZE_MAX: usize> RequestRangeExt for Request<'a, HEADER_SIZE_MAX> {
fn range(&self) -> Result<Option<RangeInclusive<u64>>, Error> {
let Some(range) = self.field("Range") else {
return Ok(None);
};
let mut range = range.clone();
let kind = range.split_off(b"=").ok_or_else(|| error!("Invalid range header field"))?;
if !kind.eq(b"bytes") {
return Err(error!("Invalid range kind"))?;
}
let start = range.split_off(b"-").ok_or_else(|| error!("Invalid range"))?;
let end_incl = range;
let start: u64 = {
let start_str = str::from_utf8(&start)?;
start_str.parse()?
};
let end_incl: u64 = {
let end_incl_str = str::from_utf8(&end_incl)?;
end_incl_str.parse()?
};
Ok(Some(start..=end_incl))
}
}