83 lines
2.3 KiB
Rust
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()
|
|
}
|