diff --git a/src/dircheck.rs b/src/dircheck.rs index 1b78926..9171363 100644 --- a/src/dircheck.rs +++ b/src/dircheck.rs @@ -17,15 +17,16 @@ pub struct DirCheck { pub fn dir_check(dir: &Path, root: &NavFolder) -> Result { trace!(target: "dir_check", "dir={dir:?}"); - let nav_paths = root - .into_iter() // recursive iterator over all pages in the folder - .map(|p| &p.path) - .collect::>(); + let mut nav_paths = HashSet::new(); + + root.for_each_page(|p| { + nav_paths.insert(&p.path); + }); let mut unused = Vec::new(); let mut extra = Vec::new(); - walk_dir_recursive(dir, &mut |path| { + walk_dir_recursive(dir, |path| { if path.extension() != Some("md".as_ref()) { // if it's not an .md file, it's extra extra.push(path); @@ -40,12 +41,12 @@ pub fn dir_check(dir: &Path, root: &NavFolder) -> Result { Ok(DirCheck { unused, extra }) } -fn walk_dir_recursive(dir: &Path, cb: &mut impl FnMut(Path)) -> Result<()> { +fn walk_dir_recursive(dir: &Path, mut cb: impl FnMut(Path)) -> Result<()> { let read_dir = unwrap!(fs::read_dir(dir), "couldn't read dir {dir}"); for entry in read_dir { let entry = entry.unwrap(); - let path = Path::new(entry.path()); + let path = Path::new_owned(entry.path()); let metadata = entry.metadata().unwrap(); trace!( target: "walk_dir_recursive", @@ -54,7 +55,7 @@ fn walk_dir_recursive(dir: &Path, cb: &mut impl FnMut(Path)) -> Result<()> { ); if metadata.is_dir() { - walk_dir_recursive(&path, cb)?; + walk_dir_recursive(&path, &mut cb)?; } else { cb(path); } diff --git a/src/modes.rs b/src/modes.rs index 980302b..55e5366 100644 --- a/src/modes.rs +++ b/src/modes.rs @@ -3,7 +3,6 @@ use crate::nav::NavFolder; use crate::path::Path; use anyhow::{anyhow, Result}; use log::{debug, error, info}; -use std::convert::Infallible; use std::fs::File; use std::io::Write; @@ -22,8 +21,7 @@ pub fn mode_check(root: &NavFolder) -> Result<()> { let mut total = 0; let mut fails = 0; - // Result<(), !> - let _ = root.into_iter().try_for_each(|page| { + root.for_each_page(|page| { total += 1; // TODO rich diff? @@ -33,8 +31,6 @@ pub fn mode_check(root: &NavFolder) -> Result<()> { } else { debug!(target: "mode_check", "pass {}", page.path); } - - Ok::<(), Infallible>(()) }); if fails == 0 { @@ -51,7 +47,7 @@ pub fn mode_fix(root: &NavFolder) -> Result<()> { let mut fixed = 0; let mut total = 0; - root.into_iter().try_for_each(|page| { + root.try_for_each_page(|page| { total += 1; if page.fixed_content == page.raw_content { diff --git a/src/nav.rs b/src/nav.rs index 9e37841..e6dc447 100644 --- a/src/nav.rs +++ b/src/nav.rs @@ -1,6 +1,6 @@ use crate::front_matter::FrontMatter; use crate::path::Path; -use std::iter::{once, Chain, Once}; +use anyhow::Result; /// a regular page, eg. `example.md` #[derive(Debug)] @@ -15,11 +15,9 @@ pub struct NavPage { pub fixed_content: String, } -type NavPageIter<'a> = Once<&'a NavPage>; - /// A folder with an index /// -/// name is index.page.name (ignored for root) +/// name is index.page.name #[derive(Debug)] pub struct NavFolder { // this may not be an index.md (if it was tagged in nav: `!index abc.md`) @@ -27,8 +25,6 @@ pub struct NavFolder { pub children: Vec, } -type NavFolderIter<'a> = Chain, NavChildrenIter<'a>>; - /// a category /// /// no index page @@ -39,13 +35,6 @@ pub struct NavCategory { pub children: Vec, } -// without indirection rustc cant resolve the type layout -type NavChildrenIter<'a> = Box + 'a>; - -fn nav_children_iter<'a>(data: &'a [NavItem]) -> NavChildrenIter<'a> { - Box::new(data.iter().flat_map(<&'a NavItem>::into_iter)) -} - #[derive(Debug)] pub enum NavItem { Page(NavPage), @@ -53,74 +42,39 @@ pub enum NavItem { Category(NavCategory), } -pub enum NavItemIter<'a> { - Page(NavPageIter<'a>), - Folder(NavFolderIter<'a>), - Category(NavChildrenIter<'a>), -} - -// - -impl<'a> IntoIterator for &'a NavPage { - type Item = &'a NavPage; - type IntoIter = NavPageIter<'a>; - - fn into_iter(self) -> Self::IntoIter { - once(self) - } -} - -impl<'a> IntoIterator for &'a NavFolder { - type Item = &'a NavPage; - type IntoIter = NavFolderIter<'a>; - - fn into_iter(self) -> Self::IntoIter { - self.index - .into_iter() - .chain(nav_children_iter(&self.children)) - } -} - -impl<'a> IntoIterator for &'a NavCategory { - type Item = &'a NavPage; - type IntoIter = NavChildrenIter<'a>; - - fn into_iter(self) -> Self::IntoIter { - nav_children_iter(&self.children) +impl NavItem { + #[allow(clippy::needless_lifetimes)] // ??? + pub fn for_each_page<'s>(&'s self, mut f: impl FnMut(&'s NavPage)) { + match self { + NavItem::Page(x) => f(x), + NavItem::Folder(x) => x.for_each_page(f), + NavItem::Category(x) => x.children.iter().for_each(|i| i.for_each_page(&mut f)), + } } -} - -impl<'a> IntoIterator for &'a NavItem { - type Item = &'a NavPage; - type IntoIter = NavItemIter<'a>; - fn into_iter(self) -> Self::IntoIter { + pub fn try_for_each_page(&self, mut f: impl FnMut(&NavPage) -> Result<()>) -> Result<()> { match self { - NavItem::Page(p) => NavItemIter::Page(p.into_iter()), - NavItem::Folder(f) => NavItemIter::Folder(f.into_iter()), - NavItem::Category(c) => NavItemIter::Category(c.into_iter()), + NavItem::Page(x) => f(x), + NavItem::Folder(x) => x.try_for_each_page(f), + NavItem::Category(x) => x + .children + .iter() + .try_for_each(|i| i.try_for_each_page(&mut f)), } } } -// - -impl<'a> Iterator for NavItemIter<'a> { - type Item = &'a NavPage; - - fn next(&mut self) -> Option { - match self { - NavItemIter::Page(i) => i.next(), - NavItemIter::Folder(i) => i.next(), - NavItemIter::Category(i) => i.next(), - } +impl NavFolder { + #[allow(clippy::needless_lifetimes)] // ??? + pub fn for_each_page<'s>(&'s self, mut f: impl FnMut(&'s NavPage)) { + f(&self.index); + self.children.iter().for_each(|i| i.for_each_page(&mut f)); } - fn size_hint(&self) -> (usize, Option) { - match self { - NavItemIter::Page(i) => i.size_hint(), - NavItemIter::Folder(i) => i.size_hint(), - NavItemIter::Category(i) => i.size_hint(), - } + pub fn try_for_each_page(&self, mut f: impl FnMut(&NavPage) -> Result<()>) -> Result<()> { + f(&self.index)?; + self.children + .iter() + .try_for_each(|i| i.try_for_each_page(&mut f)) } } diff --git a/src/path.rs b/src/path.rs index df3a259..4f4b714 100644 --- a/src/path.rs +++ b/src/path.rs @@ -14,13 +14,15 @@ pub struct Path { } impl Path { - pub fn new>(path: T) -> Self { - Path { - inner: path.as_ref().to_path_buf(), - } + pub fn new(path: impl AsRef) -> Self { + Path::new_owned(path.as_ref().to_path_buf()) } - pub fn join>(&self, path: T) -> Self { + pub fn new_owned(buf: PathBuf) -> Self { + Path { inner: buf } + } + + pub fn join(&self, path: impl AsRef) -> Self { let mut p = self.clone(); p.inner.push(path); p diff --git a/src/process.rs b/src/process.rs index e65a3a9..bb25cdb 100644 --- a/src/process.rs +++ b/src/process.rs @@ -107,7 +107,7 @@ pub fn process_include(dir: &Path, name: String) -> Result { for entry in read_dir { let entry = entry.unwrap(); - let path = Path::new(entry.path()); + let path = Path::new_owned(entry.path()); let metadata = entry.metadata().unwrap(); if metadata.is_dir() {