#![cfg_attr(coverage_nightly, coverage(off))]
use super::{Complexity, DateTime, Priority, Roadmap, Sprint, Task, TaskStatus};
use anyhow::Result;
use chrono::{NaiveDate, Utc};
use regex::Regex;
use std::collections::HashMap;
use std::str::FromStr;
struct Parsers {
sprint_regex: Regex,
task_regex: Regex,
done_regex: Regex,
}
fn create_parsers() -> Result<Parsers> {
Ok(Parsers {
sprint_regex: Regex::new(r"## (?:Current |Previous |Next )?Sprint: (v[\d.]+) (.+)")?,
task_regex: Regex::new(r"\| (PMAT-\d{4}) \| ([^|]+) \| ([^|]+) \| ([^|]+) \| ([^|]+) \|")?,
done_regex: Regex::new(r"- \[([ x])\] (.+)")?,
})
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn parse_roadmap(content: &str) -> Result<Roadmap> {
let mut roadmap = Roadmap {
current_sprint: None,
sprints: HashMap::new(),
backlog: Vec::new(),
completed_sprints: Vec::new(),
};
let parsers = create_parsers()?;
let lines: Vec<&str> = content.lines().collect();
let mut i = 0;
while i < lines.len() {
let line = lines[i];
if let Some(captures) = parsers.sprint_regex.captures(line) {
let (sprint, version, advance) = parse_sprint_section(&lines, i, &captures, &parsers)?;
i += advance;
update_roadmap_state(&mut roadmap, line, &version);
roadmap.sprints.insert(version, sprint);
}
else if line.contains("### Backlog") {
let (tasks, advance) = parse_backlog_section(&lines, i, &parsers.task_regex)?;
i += advance;
roadmap.backlog = tasks;
} else {
i += 1;
}
}
Ok(roadmap)
}
fn update_roadmap_state(roadmap: &mut Roadmap, line: &str, version: &str) {
if line.contains("Current Sprint:")
|| (roadmap.current_sprint.is_none() && !line.contains("Previous"))
{
roadmap.current_sprint = Some(version.to_string());
}
if line.contains("\u{2705} COMPLETED") {
roadmap.completed_sprints.push(version.to_string());
}
}
include!("parser_helpers.rs");
include!("parser_sprint.rs");
include!("parser_serialize.rs");
include!("parser_tests.rs");