use crate::anyrange::AnyInclusiveRange;
use ehttpd::{
bytes::DataParseExt,
error,
error::Error,
http::{Request, RequestExt},
};
use std::str;
pub trait RequestRangeExt {
fn range(&self) -> Result<Option<AnyInclusiveRange<u64>>, Error>;
}
impl<'a, const HEADER_SIZE_MAX: usize> RequestRangeExt for Request<'a, HEADER_SIZE_MAX> {
fn range(&self) -> Result<Option<AnyInclusiveRange<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 = range;
let start = str::from_utf8(&start)?;
let end = str::from_utf8(&end)?;
let range = match (start, end) {
("", "") => AnyInclusiveRange::Full,
(start, "") => AnyInclusiveRange::From { start: start.parse()? },
("", end) => AnyInclusiveRange::To { end: end.parse()? },
(start, end) => AnyInclusiveRange::FromTo { start: start.parse()?, end: end.parse()? },
};
Ok(Some(range))
}
}