#![feature(async_stream)]
use bytes::Bytes;
use std::collections::HashSet;
use std::future::Future;
use std::marker::Unpin;
use std::stream::Stream;
use tokio::io::{self, AsyncBufRead, AsyncBufReadExt, BufReader};
enum Rule {
Match(String),
Branch(Vec<Vec<usize>>),
}
fn parse_rule(s: String) -> Option<Rule> {
let s = s.trim();
s.split_once(':').and_then(|(_ix, body)| {
let body = body.trim();
parse_match_rule(body).or_else(|| parse_branch_rule(body))
})
}
fn parse_match_rule(body: &str) -> Option<Rule> {
let oqi = body.find('\"')?;
let cqi = body.rfind('\"')?;
Some(Rule::Match(String::from(&body[oqi + 1 .. cqi])))
}
fn parse_branch_rule(body: &str) -> Option<Rule> {
use std::str::FromStr;
let mut result = Vec::new();
for a in body.split('|') {
let mut branch = Vec::new();
for b in a.split_whitespace() {
branch.push(usize::from_str(b).ok()?);
}
result.push(branch);
}
Some(Rule::Branch(result))
}
async fn read_rules<I: Unpin + AsyncBufRead>(source: &mut I) -> Vec<Rule> {
let mut result = Vec::new();
loop {
let mut buf = String::new();
match source.read_line(&mut buf).await {
Ok(0) => break,
Ok(_) => match parse_rule(buf) {
None => break,
Some(rule) => {
result.push(rule);
}
},
_ => break,
}
}
result
}
async fn check_match(rules: Vec<Rule>, rule_index: usize, text: String) -> Option<HashSet<String>> {
tokio::task::yield_now().await;
match &rules[rule_index] {
Rule::Match(lit) => text.strip_prefix(<String as AsRef<str>>::as_ref(lit)).map(|s| {
let mut r = HashSet::with_capacity(1);
r.insert(String::from(s));
r
}),
Rule::Branch(branches) => {
let jhs: Vec<_> = branches.iter().map(|branch| {
let branch = branch.clone();
let text = text.clone();
tokio::spawn(async {
tokio::task::yield_now().await;
let mut remainders = HashSet::with_capacity(1);
remainders.insert(text);
for child in branch {
let mut nr: HashSet<String> = HashSet::new();
for r in remainders {
let recursive = Box::new(check_match(rules, child, r)) as Box<dyn Future<Output=Option<HashSet<String>>> + Unpin + Send>;
for r2 in recursive.await.unwrap_or_else(|| HashSet::new()) {
}
}
}
Some(remainders)
})
}).collect();
todo!()
}
}
}
async fn write_str<S: io::AsyncWriteExt + Unpin>(sink: &mut S, text: String) -> io::Result<usize> {
sink.write_buf(&mut Bytes::from(text)).await
}
#[tokio::main(flavor = "multi_thread")]
async fn main() -> io::Result<()> {
let stdout = &mut io::stdout();
let args: Vec<_> = std::env::args().collect();
let mut input = BufReader::new(tokio::fs::File::open(args[1].clone()).await?);
let rules = read_rules(&mut input).await;
write_str(stdout, format!("rules.len() = {}\n", rules.len())).await?;
Ok(())
}