use http::StatusCode;
use std::fs::Metadata;
use std::path::{Path, PathBuf};
use crate::Result;
use crate::headers_ext::ContentCoding;
pub(crate) struct FileMetadata<'a> {
pub file_path: &'a PathBuf,
pub metadata: Metadata,
pub is_dir: bool,
pub precompressed_variant: Option<(PathBuf, ContentCoding)>,
}
pub(crate) fn try_metadata(file_path: &Path) -> Result<(Metadata, bool), StatusCode> {
match std::fs::metadata(file_path) {
Ok(meta) => {
let is_dir = meta.is_dir();
tracing::trace!("file found: {:?}; is_dir: {is_dir}", file_path);
Ok((meta, is_dir))
}
Err(err) => {
tracing::debug!("file not found: {:?} {:?}", file_path, err);
Err(StatusCode::NOT_FOUND)
}
}
}
pub(crate) fn try_metadata_with_html_suffix(
file_path: &mut PathBuf,
) -> (&mut PathBuf, Option<Metadata>) {
tracing::debug!("file: appending .html suffix to the path");
if let Some(filename) = file_path.file_name() {
let owned_filename = filename.to_os_string();
let mut owned_filename_with_html = owned_filename.clone();
owned_filename_with_html.push(".html");
file_path.set_file_name(owned_filename_with_html);
if let Ok(meta_res) = try_metadata(file_path) {
let (meta, _) = meta_res;
return (file_path, Some(meta));
}
tracing::debug!(
"file: the .html suffixed path doesn't exist, falling back to the original"
);
file_path.set_file_name(owned_filename);
}
(file_path, None)
}
pub(crate) fn try_markdown_variant(file_path: &Path) -> Option<PathBuf> {
let try_path = |path: PathBuf| -> Option<PathBuf> {
match try_metadata(&path) {
Ok((_, false)) => Some(path),
_ => None,
}
};
if let Some(filename) = file_path.file_name() {
for suffix in [".md", ".html.md"] {
let mut path = file_path.to_path_buf();
let mut owned_filename = filename.to_os_string();
owned_filename.push(suffix);
path.set_file_name(owned_filename);
if let Some(found) = try_path(path) {
return Some(found);
}
}
}
let mut path = file_path.to_path_buf();
path.push("index.html.md");
try_path(path)
}