Skip to main content

cfn_guard/commands/
parse_tree.rs

1use crate::commands::{Executable, PRINT_JSON, PRINT_YAML, SUCCESS_STATUS_CODE};
2use crate::rules::Result;
3use crate::utils::reader::Reader;
4use crate::utils::writer::Writer;
5use clap::Args;
6use std::fs::File;
7
8const ABOUT: &str = "Prints out the parse tree for the rules defined in the file.";
9const OUTPUT_HELP: &str = "Write to output file";
10const PRINT_JSON_HELP: &str = "Print output in JSON format. Use -p as the short flag";
11const PRINT_YAML_HELP: &str = "Print output in YAML format";
12const RULES_HELP: &str = "Provide a rules file";
13
14#[derive(Debug, Clone, Eq, PartialEq, Args)]
15#[clap(about=ABOUT)]
16#[clap(arg_required_else_help = true)]
17/// .
18/// The ParseTree command prints out the parse tree for a given rule file
19pub struct ParseTree {
20    // the path to a rules file that a data file will have access to
21    // if set to false, will attempt to parse rules from stdin
22    // default None
23    #[arg(short, long, help=RULES_HELP)]
24    pub(crate) rules: Option<String>,
25    #[arg(short, long, help=OUTPUT_HELP)]
26    // the path to a file a user wants to print the output to
27    // default None
28    pub(crate) output: Option<String>,
29    // print output in json
30    // default false
31    #[arg(short=PRINT_JSON.1, long=PRINT_JSON.0, help=PRINT_JSON_HELP)]
32    pub(crate) print_json: bool,
33    // print output in yaml
34    // default true
35    #[arg(short=PRINT_YAML.1, long=PRINT_YAML.0, help=PRINT_YAML_HELP)]
36    pub(crate) print_yaml: bool,
37}
38
39impl Executable for ParseTree {
40    /// .
41    /// prints the parse tree for a given rule file
42    ///
43    /// This function will return an error if
44    /// - any of the specified paths do not exist
45    /// - parse errors occur in the rule file
46    fn execute(&self, writer: &mut Writer, reader: &mut Reader) -> Result<i32> {
47        let mut file: Box<dyn std::io::Read> = match &self.rules {
48            Some(file) => Box::new(std::io::BufReader::new(File::open(file)?)),
49            None => Box::new(reader),
50        };
51
52        let mut content = String::new();
53        file.read_to_string(&mut content)?;
54        let span = crate::rules::parser::Span::new_extra(&content, "");
55
56        let rules = crate::rules::parser::rules_file(span)?;
57
58        match self.print_json {
59            true => serde_json::to_writer_pretty(writer, &rules)?,
60            false => serde_yaml::to_writer(writer, &rules)?,
61        }
62
63        Ok(SUCCESS_STATUS_CODE)
64    }
65}