use super::{IncludeRef, PageRef};
use crate::span_wrap::SpanWrap;
use pest::iterators::Pairs;
use pest::Parser;
use std::borrow::Cow;
use std::collections::HashMap;
#[derive(Parser, Debug)]
#[grammar = "includes/grammar.pest"]
struct IncludeParser;
pub fn parse_include_block<'t>(
log: &slog::Logger,
text: &'t str,
start: usize,
) -> Option<(IncludeRef<'t>, usize)> {
match IncludeParser::parse(Rule::include, text) {
Ok(mut pairs) => {
let first = pairs.next().expect("No pairs returned on successful parse");
let span = first.as_span();
debug!(
log,
"Parsed include block";
"span" => SpanWrap::from(span.start()..span.end()),
"slice" => text,
);
let include = match process_pairs(log, first.into_inner()) {
Some(include) => include,
None => return None,
};
Some((include, start + span.end()))
}
Err(error) => {
debug!(
log,
"Include block was invalid";
"error" => str!(error),
"start" => start,
"slice" => text,
);
None
}
}
}
fn process_pairs<'t>(
log: &slog::Logger,
mut pairs: Pairs<'t, Rule>,
) -> Option<IncludeRef<'t>> {
let page_raw = match pairs.next() {
Some(pair) => pair.as_str(),
None => return None,
};
let page_ref = match PageRef::parse(page_raw) {
Some(page_ref) => page_ref,
None => return None,
};
trace!(
log,
"Got page for include";
"site" => page_ref.site(),
"page" => page_ref.page(),
);
let mut arguments = HashMap::new();
for pair in pairs {
debug_assert_eq!(pair.as_rule(), Rule::argument);
let (key, value) = {
let mut argument_pairs = pair.into_inner();
let key = argument_pairs
.next()
.expect("Argument pairs terminated early")
.as_str();
let value = argument_pairs
.next()
.expect("Argument pairs terminated early")
.as_str();
(key, value)
};
trace!(
log,
"Adding argument for include";
"key" => key,
"value" => value,
);
arguments.insert(Cow::Borrowed(key), Cow::Borrowed(value));
}
Some(IncludeRef::new(page_ref, arguments))
}