use indexmap::IndexMap;
use serde_json::Value;
use super::ScanAction;
#[cfg(test)]
pub(crate) fn scan_file<F>(path: &std::path::Path, visitor: F) -> anyhow::Result<()>
where
F: FnMut(&str, usize) -> ScanAction,
{
use anyhow::Context as _;
use std::fs::File;
use std::io::BufReader;
let file = File::open(path).with_context(|| format!("failed to open {}", path.display()))?;
let reader = BufReader::new(file);
scan_reader(reader, visitor)
}
#[cfg(test)]
pub(crate) fn scan_reader<R: std::io::BufRead, F>(reader: R, visitor: F) -> anyhow::Result<()>
where
F: FnMut(&str, usize) -> ScanAction,
{
let mut wrapper = ClosureVisitor { visitor };
super::scan_reader_multi(reader, &mut [&mut wrapper])
}
#[cfg(test)]
struct ClosureVisitor<F: FnMut(&str, usize) -> ScanAction> {
visitor: F,
}
#[cfg(test)]
impl<F: FnMut(&str, usize) -> ScanAction> FileVisitor for ClosureVisitor<F> {
fn on_body_line(&mut self, _raw: &str, cleaned: &str, line_num: usize) -> ScanAction {
(self.visitor)(cleaned, line_num)
}
}
pub trait FileVisitor {
fn on_frontmatter(&mut self, _props: IndexMap<String, Value>) -> ScanAction {
ScanAction::Continue
}
fn on_body_line(&mut self, _raw: &str, _cleaned: &str, _line_num: usize) -> ScanAction {
ScanAction::Continue
}
fn on_code_fence_open(&mut self, _raw: &str, _language: &str, _line_num: usize) -> ScanAction {
ScanAction::Continue
}
fn on_code_fence_close(&mut self, _line_num: usize) -> ScanAction {
ScanAction::Continue
}
fn on_code_block_line(&mut self, _raw: &str, _line_num: usize) -> ScanAction {
ScanAction::Continue
}
fn needs_body(&self) -> bool {
true
}
fn needs_frontmatter(&self) -> bool {
true
}
}