use crate::header::HeaderValue;
use crate::headers::ETag;
use httpdate::HttpDate;
use std::time::SystemTime;
pub(super) fn etag_from_metadata(size: u64, modified: SystemTime) -> Option<ETag> {
let duration = modified.duration_since(SystemTime::UNIX_EPOCH).ok()?;
let value = format!(
"\"{:x}.{:08x}-{:x}\"",
duration.as_secs(),
duration.subsec_nanos(),
size
);
value.parse().ok()
}
#[derive(Clone)]
pub(super) struct LastModified(pub(super) HttpDate);
impl From<SystemTime> for LastModified {
fn from(time: SystemTime) -> Self {
Self(time.into())
}
}
pub(super) struct IfModifiedSince(HttpDate);
impl IfModifiedSince {
pub(super) fn is_modified(&self, last_modified: &LastModified) -> bool {
self.0 < last_modified.0
}
pub(super) fn from_header_value(value: &HeaderValue) -> Option<Self> {
std::str::from_utf8(value.as_bytes())
.ok()
.and_then(|value| httpdate::parse_http_date(value).ok())
.map(|time| Self(time.into()))
}
}
pub(super) struct IfUnmodifiedSince(HttpDate);
impl IfUnmodifiedSince {
pub(super) fn precondition_passes(&self, last_modified: &LastModified) -> bool {
self.0 >= last_modified.0
}
pub(super) fn from_header_value(value: &HeaderValue) -> Option<Self> {
std::str::from_utf8(value.as_bytes())
.ok()
.and_then(|value| httpdate::parse_http_date(value).ok())
.map(|time| Self(time.into()))
}
}