|
| 1 | +use std::error::Error; |
| 2 | + |
| 3 | +use crate::fail; |
| 4 | +use crate::options::ChiselFlags; |
| 5 | +use serde_yaml::Value; |
| 6 | + |
| 7 | +pub fn parse_config(flags: &ChiselFlags, buf: &String) { |
| 8 | + let yaml = serde_yaml::from_str::<Value>(buf).unwrap_or_else(|e| { |
| 9 | + fail( |
| 10 | + 1, |
| 11 | + &format!("Failed to parse YAML configuration: {}", e.description()), |
| 12 | + ) |
| 13 | + }); |
| 14 | +} |
| 15 | + |
| 16 | +pub fn validate_config(flags: &ChiselFlags, yaml: &Value) -> Result<(), String> { |
| 17 | + if flags.debug_enabled() { |
| 18 | + println!("Validating YAML configuration..."); |
| 19 | + } |
| 20 | + |
| 21 | + // rules |
| 22 | + // - top-level value must always be a mapping of string to mapping |
| 23 | + // - each child mapping must have a string field: file |
| 24 | + // - each child mapping must contain at least one string to mapping map (represents a module) |
| 25 | + match yaml { |
| 26 | + Value::Mapping(m) => { |
| 27 | + // Iterate over rulesets |
| 28 | + for (idx, (key, value)) in m.iter().enumerate() { |
| 29 | + // Rule 1 |
| 30 | + match (key, value) { |
| 31 | + (Value::String(name), Value::Mapping(ruleset)) => { |
| 32 | + // Rule 2 |
| 33 | + match ruleset.get(&Value::String("file".to_string())) { |
| 34 | + Some(Value::String(path)) => (), |
| 35 | + Some(_) => { |
| 36 | + return Err(format!( |
| 37 | + "Ruleset {}: field 'file' has invalid type", |
| 38 | + name |
| 39 | + )) |
| 40 | + } |
| 41 | + _ => { |
| 42 | + return Err(format!( |
| 43 | + "Ruleset {}: Missing required field 'file'", |
| 44 | + name |
| 45 | + )) |
| 46 | + } |
| 47 | + } |
| 48 | + // Rule 3 |
| 49 | + if ruleset |
| 50 | + .iter() |
| 51 | + .filter(|(lhs, rhs)| match (lhs, rhs) { |
| 52 | + (Value::String(module_name), Value::Mapping(module_opts)) => true, |
| 53 | + _ => false, |
| 54 | + }) |
| 55 | + .collect::<Vec<(&Value, &Value)>>() |
| 56 | + .len() |
| 57 | + == 0 |
| 58 | + { |
| 59 | + return Err(format!("Ruleset {}: Missing module declarations", name)); |
| 60 | + } |
| 61 | + } |
| 62 | + (Value::String(name), _) => { |
| 63 | + return Err(format!("Ruleset '{}': invalid value type", name)) |
| 64 | + } |
| 65 | + (_, Value::Mapping(m)) => { |
| 66 | + return Err(format!("Ruleset {}: invalid key type", idx)) |
| 67 | + } |
| 68 | + (_, _) => return Err(format!("Ruleset {}: invalid key and value type", idx)), |
| 69 | + } |
| 70 | + } |
| 71 | + return Ok(()); |
| 72 | + } |
| 73 | + _ => Err("Top-level YAML value is not a mapping".to_string()), |
| 74 | + } |
| 75 | +} |
0 commit comments