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, 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);
render_json(&collection, effective_pretty(ctx, 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) => render_json(&ast, effective_pretty(ctx, 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);
render_json(&collection, effective_pretty(ctx, pretty));
}
Err(e) => {
eprintln!("Parse error: {e}");
process::exit(crate::exit_code::RULE_ERROR);
}
}
}
fn effective_pretty(ctx: OutputCtx, flag: bool) -> bool {
use crate::output::OutputFormat;
match ctx.format {
OutputFormat::Ndjson => false,
OutputFormat::Json => flag || ctx.pretty_json(),
_ => flag,
}
}