use {
anyhow::Result,
std::path::{Path, PathBuf},
};
use crate::book::toc::{Toc, TocItem, TocItemContent};
pub trait BookVisitor: Clone + Send + Sync {
fn visit_file(&mut self, file: &Path) -> Result<()>;
}
pub fn flatten_toc_items(toc: &Toc, items: &mut Vec<TocItem>) {
for item in &toc.items {
match item.content {
TocItemContent::File(_) => {
items.push(item.clone());
}
TocItemContent::SubToc(ref toc) => {
self::flatten_toc_items(toc, items);
}
};
}
}
pub fn pull_files_rec(toc: &Toc, files: &mut Vec<PathBuf>) {
for item in &toc.items {
match item.content {
TocItemContent::File(ref file) => {
files.push(file.clone());
}
TocItemContent::SubToc(ref toc) => {
self::pull_files_rec(toc, files);
}
};
}
}
pub fn walk_book(v: &mut impl BookVisitor, root_toc: &Toc) {
let mut files = Vec::with_capacity(80);
self::pull_files_rec(root_toc, &mut files);
let results = files.iter().map(|file| v.visit_file(file));
let errors: Vec<_> = results
.into_iter()
.filter(|x| x.is_err())
.map(|x| x.unwrap_err())
.collect();
crate::utils::print_errors(&errors, "while building the book");
}
pub async fn walk_book_async<V: BookVisitor + 'static>(v: &mut V, root_toc: &Toc) {
let mut files = Vec::with_capacity(80);
self::pull_files_rec(root_toc, &mut files);
let xs = files.into_iter().map(|file| {
let mut v = v.clone();
async_std::task::spawn(async move { v.visit_file(&file) })
});
let results = futures::future::join_all(xs).await;
let errors: Vec<_> = results
.into_iter()
.filter(|x| x.is_err())
.map(|x| x.unwrap_err())
.collect();
crate::utils::print_errors(&errors, "while building the book");
}