use std::io::{self, Read};
use std::path::PathBuf;
use std::process;
use clap::Args;
use rsigma_parser::{parse_sigma_file, parse_sigma_yaml};
use crate::output::{OutputCtx, OutputFormat, render_json};
#[derive(Args, Debug)]
pub(crate) struct ParseArgs {
pub path: PathBuf,
#[arg(short, long, default_value_t = true)]
pub pretty: bool,
}
#[derive(Args, Debug)]
pub(crate) struct ConditionArgs {
pub expr: String,
}
#[derive(Args, Debug)]
pub(crate) struct StdinArgs {
#[arg(short, long, default_value_t = true)]
pub pretty: bool,
}
pub(crate) fn cmd_parse(args: ParseArgs, ctx: OutputCtx) {
let ParseArgs { path, pretty } = args;
match parse_sigma_file(&path) {
Ok(collection) => {
crate::print_warnings(&collection.errors);
emit_ast("rule parse", &ctx, &collection, pretty);
}
Err(e) => {
eprintln!("Error parsing {}: {e}", path.display());
process::exit(crate::exit_code::RULE_ERROR);
}
}
}
pub(crate) fn cmd_condition(args: ConditionArgs, ctx: OutputCtx) {
let ConditionArgs { expr } = args;
match rsigma_parser::parse_condition(&expr) {
Ok(ast) => emit_ast("rule condition", &ctx, &ast, true),
Err(e) => {
eprintln!("Condition parse error: {e}");
process::exit(crate::exit_code::RULE_ERROR);
}
}
}
pub(crate) fn cmd_stdin(args: StdinArgs, ctx: OutputCtx) {
let StdinArgs { pretty } = args;
let mut input = String::new();
if let Err(e) = io::stdin().read_to_string(&mut input) {
eprintln!("Error reading stdin: {e}");
process::exit(crate::exit_code::RULE_ERROR);
}
match parse_sigma_yaml(&input) {
Ok(collection) => {
crate::print_warnings(&collection.errors);
emit_ast("rule stdin", &ctx, &collection, pretty);
}
Err(e) => {
eprintln!("Parse error: {e}");
process::exit(crate::exit_code::RULE_ERROR);
}
}
}
fn emit_ast<T: serde::Serialize>(command: &str, ctx: &OutputCtx, value: &T, pretty_flag: bool) {
match ctx.format {
OutputFormat::Ndjson => render_json(value, false),
OutputFormat::Json => render_json(value, pretty_flag || ctx.pretty_json()),
OutputFormat::Table | OutputFormat::Csv | OutputFormat::Tsv => {
ctx.warn_unsupported(command, "json");
render_json(value, pretty_flag);
}
}
}