use crate::cli_config::effective_dialect;
use crate::exit_codes::ExitCode;
use crate::{Commands, commands};
use anyhow::anyhow;
use std::convert::TryFrom;
type CommandOutcome = (anyhow::Result<ExitCode>, &'static str);
pub(crate) fn run_command(command: Commands, strict_policy: bool) -> CommandOutcome {
match command {
command @ Commands::Parse { .. } => run_parse_command(command),
command @ Commands::Inspect { .. } => run_inspect_command(command),
command @ Commands::Decode { .. } => run_decode_command(command, strict_policy),
command @ Commands::Encode { .. } => run_encode_command(command),
#[cfg(feature = "audit")]
command @ Commands::Audit { .. } => run_audit_command(command),
command @ Commands::Verify { .. } => run_verify_command(command),
Commands::Support { args } => (commands::support::run(&args), "support"),
Commands::Determinism { command } => (commands::determinism::run(&command), "determinism"),
}
}
fn dispatch_mismatch(operation: &'static str) -> CommandOutcome {
(
Err(anyhow!(
"internal command dispatch mismatch for {operation}"
)),
operation,
)
}
fn run_parse_command(command: Commands) -> CommandOutcome {
let Commands::Parse {
copybook,
output,
strict,
strict_comments,
dialect,
} = command
else {
return dispatch_mismatch("parse");
};
let effective_dialect = effective_dialect(dialect);
(
commands::parse::run(
©book,
output,
strict,
strict_comments,
effective_dialect,
),
"parse",
)
}
fn run_inspect_command(command: Commands) -> CommandOutcome {
let Commands::Inspect {
copybook,
codepage,
strict,
strict_comments,
dialect,
} = command
else {
return dispatch_mismatch("inspect");
};
let effective_dialect = effective_dialect(dialect);
(
commands::inspect::run(
©book,
codepage,
strict,
strict_comments,
effective_dialect,
),
"inspect",
)
}
fn run_decode_command(command: Commands, strict_policy: bool) -> CommandOutcome {
let Commands::Decode {
copybook,
input,
output,
format,
codepage,
json_number,
strict,
max_errors,
fail_fast,
emit_filler,
emit_meta,
emit_raw,
on_decode_unmappable,
threads,
strict_comments,
preserve_zoned_encoding,
preferred_zoned_encoding: preferred_zoned_encoding_cli,
float_format,
dialect,
select,
} = command
else {
return dispatch_mismatch("decode");
};
let effective_dialect = effective_dialect(dialect);
(
commands::decode::run(&commands::decode::DecodeArgs {
copybook: ©book,
input: &input,
output: &output,
format,
codepage,
json_number,
strict,
max_errors,
fail_fast,
emit_filler,
emit_meta,
emit_raw,
on_decode_unmappable,
threads,
strict_comments,
preserve_zoned_encoding,
preferred_zoned_encoding: preferred_zoned_encoding_cli.into(),
float_format,
strict_policy,
dialect: effective_dialect.into(),
select: &select,
}),
"decode",
)
}
fn run_encode_command(command: Commands) -> CommandOutcome {
let Commands::Encode {
copybook,
input,
output,
format,
codepage,
use_raw,
bwz_encode,
strict,
max_errors,
fail_fast,
threads,
coerce_numbers,
strict_comments,
zoned_encoding_override,
float_format,
dialect,
select,
} = command
else {
return dispatch_mismatch("encode");
};
let effective_dialect = effective_dialect(dialect);
(
commands::encode::run(
©book,
&input,
&output,
&commands::encode::EncodeCliOptions {
format,
codepage,
use_raw,
bwz_encode,
strict,
max_errors,
fail_fast,
threads,
coerce_numbers,
strict_comments,
zoned_encoding_override,
float_format,
dialect: effective_dialect.into(),
select: &select,
},
),
"encode",
)
}
#[cfg(feature = "audit")]
fn run_audit_command(command: Commands) -> CommandOutcome {
let Commands::Audit { audit_command } = command else {
return dispatch_mismatch("audit");
};
let runtime = match tokio::runtime::Runtime::new() {
Ok(runtime) => runtime,
Err(err) => return (Err(anyhow!(err)), "audit"),
};
(
runtime
.block_on(commands::audit::run(audit_command))
.map_err(|err| anyhow!(err)),
"audit",
)
}
fn run_verify_command(command: Commands) -> CommandOutcome {
let Commands::Verify {
copybook,
input,
report,
format,
codepage,
strict,
max_errors,
sample,
strict_comments,
dialect,
select,
} = command
else {
return dispatch_mismatch("verify");
};
let effective_dialect = effective_dialect(dialect);
let value = max_errors.unwrap_or(10);
let Ok(normalized_max_errors) = u32::try_from(value) else {
return (
Err(anyhow!(
"--max-errors must be between 0 and {} (received {value})",
u32::MAX
)),
"verify",
);
};
let opts = commands::verify::VerifyOptions {
format,
codepage,
strict,
max_errors: normalized_max_errors,
sample: sample.unwrap_or(5),
strict_comments,
dialect: effective_dialect.into(),
select: &select,
};
(
commands::verify::run(©book, &input, report, &opts),
"verify",
)
}