use include_dir::Dir;
#[derive(Debug, Clone, Copy)]
pub struct Shelf {
pub dir: &'static Dir<'static>,
pub strip: Option<&'static str>,
}
pub const METHOD: Shelf = Shelf {
dir: &crate::embedded::METHOD,
strip: None,
};
pub const SPECS: Shelf = Shelf {
dir: &crate::embedded::SPECS,
strip: Some("SPEC-"),
};
pub const TEMPLATES: Shelf = Shelf {
dir: &crate::embedded::TEMPLATES,
strip: Some("TEMPLATE-"),
};
fn short_name<'a>(shelf: &Shelf, file_name: &'a str) -> Option<&'a str> {
let stem = file_name.strip_suffix(".md")?;
shelf
.strip
.map_or(Some(stem), |prefix| stem.strip_prefix(prefix))
}
#[must_use]
pub fn list(shelf: &Shelf) -> Vec<String> {
let mut names: Vec<String> = shelf
.dir
.files()
.filter_map(|file| {
let name = file.path().as_os_str().to_str()?;
short_name(shelf, name).map(String::from)
})
.collect();
names.sort();
names
}
#[must_use]
pub fn get(shelf: &Shelf, name: &str) -> Option<&'static str> {
let wanted = name.strip_suffix(".md").unwrap_or(name);
shelf.dir.files().find_map(|file| {
let file_name = file.path().as_os_str().to_str()?;
let stem = file_name.strip_suffix(".md")?;
let matches = stem == wanted || short_name(shelf, file_name) == Some(wanted);
if matches { file.contents_utf8() } else { None }
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn shelves_list_their_short_names() {
assert!(list(&METHOD).contains(&"glossary".to_string()));
assert!(list(&SPECS).contains(&"distribution".to_string()));
assert!(list(&TEMPLATES).contains(&"adr".to_string()));
}
#[test]
fn documents_resolve_by_short_and_full_names() {
let by_short = get(&SPECS, "distribution").unwrap();
assert_eq!(get(&SPECS, "SPEC-distribution").unwrap(), by_short);
assert_eq!(get(&SPECS, "SPEC-distribution.md").unwrap(), by_short);
assert!(by_short.contains("distribution:instances-operate-offline"));
assert!(get(&SPECS, "nonexistent").is_none());
}
}