///|
pub(all) struct CliResponse {
exit_code : Int
stdout : String
stderr : String
}
///|
pub fn version() -> String {
"0.1.0"
}
///|
pub fn dispatch(args : ArrayView[String]) -> CliResponse {
// --help / -h
if args.length() == 0 ||
(args.length() == 1 && (args[0] == "--help" || args[0] == "-h")) {
return { exit_code: 0, stdout: root_command().render_help(), stderr: "" }
}
// --version / -V
if args.length() == 1 && (args[0] == "--version" || args[0] == "-V") {
return { exit_code: 0, stdout: version(), stderr: "" }
}
// 解析 subcommand
let matches = root_command().parse(argv=args, env={}) catch {
err => return { exit_code: 2, stdout: "", stderr: "\{err}" }
}
match matches.subcommand {
Some((name, sub_matches)) =>
match name {
"invoice" => dispatch_invoice(sub_matches)
_ => { exit_code: 2, stdout: "", stderr: "unknown subcommand: \{name}" }
}
None => { exit_code: 0, stdout: root_command().render_help(), stderr: "" }
}
}
///|
fn root_command() -> @argparse.Command {
@argparse.Command(
"ofdx",
about="OFD 版式文档执行工具",
version=version(),
subcommands=[invoice_command()],
)
}
///|
fn invoice_command() -> @argparse.Command {
@argparse.Command(
"invoice",
about="解析 OFD 增值税电子发票,输出结构化 JSON",
positionals=[
@argparse.PositionArg(
"file",
about="OFD 文件路径(.ofd)",
num_args=@argparse.ValueRange(lower=1, upper=1),
),
],
)
}
///|
fn dispatch_invoice(matches : @argparse.Matches) -> CliResponse {
let values : Map[String, Array[String]] = matches.values
guard values is { "file": [file, ..], .. } else {
return { exit_code: 1, stdout: "", stderr: "missing file argument" }
}
let data = @fs.read_file_to_bytes(file) catch {
_ =>
return { exit_code: 1, stdout: "", stderr: "无法读取文件: " + file }
}
let port = @adaptor.MooncakeOfdPort::from_bytes(data) catch {
e =>
return {
exit_code: 1,
stdout: "",
stderr: "OFD 解包失败: " + e.to_string(),
}
}
let reader = match @reader.OfdReader::open(port) {
Ok(r) => r
Err(e) =>
return {
exit_code: 1,
stdout: "",
stderr: "OFD 解析失败: " + e.to_string(),
}
}
match @invoice.extract_invoice(reader) {
Ok(inv) =>
{ exit_code: 0, stdout: @invoice.invoice_to_json(inv), stderr: "" }
Err(e) =>
{
exit_code: 1,
stdout: "",
stderr: "发票提取失败: " + e.to_string(),
}
}
}