use std::fs;
use std::sync::Arc;
use corpora_core::subscriber::ek;
use corpora_core::{Context, DocPath, Event, Interest, ParseError, Record, Subscriber};
use crate::toml_format::TomlFormat;
pub trait FrontMatterFormat {
fn parse(&self, path: &DocPath, text: &str) -> Result<Record, ParseError>;
}
pub struct Parser {
fmt: Box<dyn FrontMatterFormat>,
}
impl Parser {
pub fn new(fmt: Box<dyn FrontMatterFormat>) -> Self {
Parser { fmt }
}
pub fn toml() -> Self {
Parser {
fmt: Box::new(TomlFormat),
}
}
}
impl Subscriber for Parser {
fn name(&self) -> &'static str {
"parser"
}
fn interest(&self) -> Interest {
Interest::only(ek::DISCOVERED | ek::CHANGED)
}
fn handle(&mut self, ev: &Event, cx: &mut Context<'_>) {
let path = match ev {
Event::Discovered(p) | Event::Changed(p) => p,
_ => return,
};
let text = match fs::read_to_string(&path.0) {
Ok(t) => t,
Err(e) => {
cx.emit(Event::ParseFailed {
path: path.clone(),
error: ParseError(e.to_string()),
});
return;
}
};
match self.fmt.parse(path, &text) {
Ok(r) => cx.emit(Event::Parsed(Arc::new(r))),
Err(e) => cx.emit(Event::ParseFailed {
path: path.clone(),
error: e,
}),
}
}
}