use std::{
fmt::{self, Display},
num::ParseIntError,
ops::RangeInclusive,
};
pub mod content_range;
pub mod if_range;
pub mod range;
#[cfg(test)]
mod tests;
const UNIT: &str = "bytes";
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum ParseHttpRangeOrContentRangeError {
#[error("The header value is malformed")]
Malformed,
#[error("Contains nonvisible ASCII")]
ContainsNonVisibleASCII,
#[error("Empty header value")]
Empty,
#[error("Invalid unit")]
InvalidUnit,
#[error("Invalid range value")]
MalformedRange,
#[error(transparent)]
UnorderedRange(#[from] InvalidOrderedRange),
#[error("Invalid range piece")]
InvalidRangePiece(#[source] InvalidHttpU64),
#[error("Invalid size value")]
InvalidSize(#[source] InvalidHttpU64),
}
#[cfg(feature = "axum")]
impl axum_core::response::IntoResponse for ParseHttpRangeOrContentRangeError {
fn into_response(self) -> axum_core::response::Response {
http::StatusCode::BAD_REQUEST.into_response()
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum InvalidHttpU64 {
#[error("{0} has a sign as prefix, so it can't be parsed as an unprefixed int")]
HasSignPrefix(String),
#[error(transparent)]
InvalidInt(#[from] ParseIntError),
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("The provided `start`: {start} is greater than `end`: {end}")]
pub struct InvalidOrderedRange {
start: u64,
end: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OrderedRange {
start: u64,
end: u64,
}
impl OrderedRange {
pub fn new(range: RangeInclusive<u64>) -> Result<Self, InvalidOrderedRange> {
let start = *range.start();
let end = *range.end();
if start > end {
return Err(InvalidOrderedRange { start, end });
}
Ok(Self { start, end })
}
pub fn start(&self) -> u64 {
self.start
}
pub fn end(&self) -> u64 {
self.end
}
}
impl Display for OrderedRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}-{}", self.start(), self.end())
}
}
pub(crate) fn u64_unprefixed_parse(s: &str) -> Result<u64, InvalidHttpU64> {
if s.starts_with("+") {
Err(InvalidHttpU64::HasSignPrefix(s.to_owned()))
} else {
Ok(s.parse::<u64>()?)
}
}