ehttpd_range/
requestext.rs1use crate::anyrange::AnyInclusiveRange;
4use ehttpd::{
5 bytes::DataParseExt,
6 error,
7 error::Error,
8 http::{Request, RequestExt},
9};
10use std::str;
11
12pub trait RequestRangeExt {
14 fn range(&self) -> Result<Option<AnyInclusiveRange<u64>>, Error>;
16}
17impl<'a, const HEADER_SIZE_MAX: usize> RequestRangeExt for Request<'a, HEADER_SIZE_MAX> {
18 fn range(&self) -> Result<Option<AnyInclusiveRange<u64>>, Error> {
19 let Some(range) = self.field("Range") else {
21 return Ok(None);
22 };
23
24 let mut range = range.clone();
26 let kind = range.split_off(b"=").ok_or_else(|| error!("Invalid range header field"))?;
27 if !kind.eq(b"bytes") {
28 return Err(error!("Invalid range kind"))?;
29 }
30
31 let start = range.split_off(b"-").ok_or_else(|| error!("Invalid range"))?;
33 let end = range;
34
35 let start = str::from_utf8(&start)?;
37 let end = str::from_utf8(&end)?;
38 let range = match (start, end) {
39 ("", "") => AnyInclusiveRange::Full,
40 (start, "") => AnyInclusiveRange::From { start: start.parse()? },
41 ("", end) => AnyInclusiveRange::To { end: end.parse()? },
42 (start, end) => AnyInclusiveRange::FromTo { start: start.parse()?, end: end.parse()? },
43 };
44 Ok(Some(range))
45 }
46}