diff options
author | Lars Wirzenius <liw@liw.fi> | 2019-09-25 11:47:42 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2019-09-25 11:47:42 +0300 |
commit | f21e1e0dde83229b024d4960e2e6871bc7727845 (patch) | |
tree | 7e2e8ad59ff843e14a895058bc16bc3c472b54fa /src/lib.rs | |
parent | 9bd8b8dfa1b898146458bf94c6ec43e27b792b50 (diff) | |
download | roadmap-f21e1e0dde83229b024d4960e2e6871bc7727845.tar.gz |
Change: check for non-existent dependencies
Also, rework how errors are defined
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 39 |
1 files changed, 36 insertions, 3 deletions
@@ -33,6 +33,8 @@ use serde_yaml; use serde_yaml::Value; use std::collections::HashMap; use textwrap::fill; +use std::fmt; +use std::error::Error; /// A step in a roadmap. #[derive(Clone,Debug,PartialEq)] @@ -95,6 +97,17 @@ pub struct Roadmap { steps: Vec<Step>, } +#[derive(Debug)] +struct ParseError(String); + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "ERROR: {}", self.0) + } +} + +impl Error for ParseError {} + impl Roadmap { /// Create a new, empty roadmap. pub fn new() -> Roadmap { @@ -102,7 +115,7 @@ impl Roadmap { } /// Create a new roadmap from a YAML representation. - pub fn from_yaml(yaml: &str) -> Result<Roadmap, Box<dyn std::error::Error>> { + pub fn from_yaml(yaml: &str) -> Result<Roadmap, Box<dyn Error>> { let mut roadmap = Roadmap::new(); let map: HashMap<String, serde_yaml::Value> = serde_yaml::from_str(yaml)?; @@ -111,6 +124,7 @@ impl Roadmap { roadmap.add_step(&step)?; } + roadmap.validate()?; Ok(roadmap) } @@ -170,6 +184,25 @@ impl Roadmap { } } + // Validate that the parsed, constructed roadmap is valid. + fn validate(&self) -> Result<(), Box<dyn std::error::Error>> { + // Does every dependency exist? + for step in self.steps.iter() { + for depname in step.dependencies() { + match self.get_step(depname) { + None => { + let msg = format!("step {} depends on missing {}", + step.name(), depname); + return Result::Err(Box::new(ParseError(msg.into()))); + } + Some(_) => (), + } + } + } + + Ok(()) + } + /// Return list of step names. pub fn step_names<'a>(&'a self) -> Vec<&'a str> { let mut names = vec![]; @@ -397,8 +430,8 @@ mod tests { } #[test] - fn parse_yaml_map_entries_not_maps() { - let r = Roadmap::from_yaml("foo: []"); + fn parse_yaml_unknown_dep() { + let r = Roadmap::from_yaml("foo: {depends: [bar]}"); match r { Ok(_) => panic!("expected a parse error"), _ => (), |