use std::fs;
use std::path;
use anyhow::anyhow;
use crate::doc;
use crate::index;
pub trait Source {
fn find_crate(&self, name: &str) -> Option<doc::Crate>;
fn load_index(&self) -> anyhow::Result<Option<index::Index>>;
}
#[derive(Clone, Debug, PartialEq)]
pub struct DirSource {
path: path::PathBuf,
}
impl DirSource {
fn new(path: path::PathBuf) -> Self {
log::info!("Created directory source at '{}'", path.display());
Self { path }
}
}
impl Source for DirSource {
fn find_crate(&self, name: &str) -> Option<doc::Crate> {
log::info!(
"Searching crate '{}' in dir source '{}'",
name,
self.path.display()
);
let crate_path = self.path.join(name.replace('-', "_"));
if crate_path.join("all.html").is_file() {
log::info!("Found crate '{}': '{}'", name, crate_path.display());
Some(doc::Crate::new(name.to_owned(), crate_path))
} else {
log::info!("Did not find crate '{}' in '{}'", name, self.path.display());
None
}
}
fn load_index(&self) -> anyhow::Result<Option<index::Index>> {
log::info!("Searching search index for '{}'", self.path.display());
for entry in fs::read_dir(&self.path)? {
let entry = entry?;
if entry.file_type()?.is_file() {
if let Some(s) = entry.file_name().to_str() {
if s.starts_with("search-index") && s.ends_with(".js") {
log::info!("Found search index '{}'", &entry.path().display());
return index::Index::load(&entry.path());
}
}
}
}
log::info!("Could not find search index for '{}'", self.path.display());
Ok(None)
}
}
pub fn get_source<P: AsRef<path::Path>>(path: P) -> anyhow::Result<Box<dyn Source>> {
if path.as_ref().is_dir() {
Ok(Box::new(DirSource::new(path.as_ref().to_path_buf())))
} else {
Err(anyhow!(
"This source is not supported: {}",
path.as_ref().display()
))
}
}
#[cfg(test)]
mod tests {
use std::path;
use super::Source;
#[test]
fn dir_source_find_crate() {
fn assert_crate(source: &dyn super::Source, path: &path::PathBuf, name: &str) {
assert_eq!(
source.find_crate(name),
Some(super::doc::Crate::new(name.to_owned(), path.join(name)))
);
}
let doc = crate::tests::ensure_docs();
let source = super::DirSource::new(doc.clone());
assert_crate(&source, &doc, "clap");
assert_crate(&source, &doc, "lazy_static");
assert_eq!(source.find_crate("lazystatic"), None);
}
}