Files

83 lines
2.3 KiB
Rust

extern crate pest;
#[macro_use]
extern crate pest_derive;
pub mod loader;
use anyhow::{bail, ensure, Context};
use smartstring::alias::CompactString;
#[cfg(test)]
mod test;
#[derive(Parser)]
#[grammar = "seed.pest"]
struct SeedParser;
use pest::Parser;
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct SeedBlock {
pub tags: Vec<CompactString>,
pub seeds: Vec<Seed>,
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Seed {
pub url: String,
pub extra_tags: Vec<CompactString>,
}
pub fn parse_seeds(input: &str) -> anyhow::Result<Vec<SeedBlock>> {
use pest::iterators::Pair;
pub fn parse_tag(pair: Pair<Rule>) -> anyhow::Result<CompactString> {
ensure!(matches!(pair.as_rule(), Rule::tagName));
Ok(CompactString::from(pair.as_str()))
}
pub fn parse_url(pair: Pair<Rule>) -> anyhow::Result<String> {
ensure!(matches!(pair.as_rule(), Rule::url));
Ok(String::from(pair.as_str()))
}
pub fn parse_seedblock_header(pair: Pair<Rule>) -> anyhow::Result<Vec<CompactString>> {
pair.into_inner().map(parse_tag).collect()
}
pub fn parse_seed(pair: Pair<Rule>) -> anyhow::Result<Seed> {
let mut children = pair.into_inner();
let url = parse_url(children.next().context("Expecting URL")?)?;
let extra_tags: anyhow::Result<Vec<CompactString>> = children.map(parse_tag).collect();
let extra_tags = extra_tags?;
Ok(Seed { url, extra_tags })
}
pub fn parse_seedblock(pair: Pair<Rule>) -> anyhow::Result<SeedBlock> {
match pair.as_rule() {
Rule::seedblock => {
let mut children = pair.into_inner();
let header = children.next().context("No seedblock header")?;
let tags = parse_seedblock_header(header)?;
let urls: anyhow::Result<Vec<Seed>> = children.map(parse_seed).collect();
let seeds = urls?;
Ok(SeedBlock { tags, seeds })
}
other => {
bail!("Looking for seedblock; unexpected {:#?}", other);
}
}
}
let pairs = SeedParser::parse(Rule::main, input)?;
pairs
.into_iter()
.filter(|pair| pair.as_rule() != Rule::EOI)
.map(parse_seedblock)
.collect()
}