1use crate::cli_utils::*;
2use crate::decode_core;
3use crate::decode_core::Param;
4use crate::file_utils;
5use crate::json_printer::BracketType;
6use crate::output_channel::OutputChannel;
7use clap::*;
8use std::sync::Arc;
9
10pub fn sub_command<'a, 'b>() -> App<'a, 'b> {
11 SubCommand::with_name("decode")
12 .about("Decode SBX container")
13 .arg(in_file_arg().help("SBX container to decode"))
14 .arg(out_arg().help(
15 "Decoded file name. Supply - to use stdout as output. Use ./- for files named -.
16If output is stdout, progress text and final stats are outputted to stderr instead.
17If OUT is not provided, then the original file name stored in the SBX container
18(STOREDNAME) is used if present (only the file part of STOREDNAME is used). If
19OUT is provided and is a directory, then the output file is stored as OUT/STOREDNAME
20if STOREDNAME is present (only the file part of STOREDNAME is used). If OUT is
21provided and is not a directory, then it is used directly.",
22 ))
23 .arg(force_arg().help("Force overwrite even if OUT exists"))
24 .arg(multi_pass_arg().help(
25 "Disable truncation of OUT, and skip writing if a non-blank data
26chunk already exists at the location. This allows writing to OUT
27multiple times to update it gradually. Ignored if output is stdout.",
28 ))
29 .arg(multi_pass_no_skip_arg().help(
30 "Disable truncation of OUT, write even if a non-blank data chunk
31exists at the location. This allows writing to OUT multiple times
32to update it gradually. Ignored if output is stdout.",
33 ))
34 .arg(no_meta_arg())
35 .arg(pr_verbosity_level_arg())
36 .arg(ref_from_byte_arg())
37 .arg(ref_to_byte_inc_arg())
38 .arg(ref_to_byte_exc_arg())
39 .arg(guess_burst_from_byte_arg())
40 .arg(from_byte_arg().help(FROM_BYTE_ARG_HELP_MSG_REF_BLOCK))
41 .arg(to_byte_inc_arg())
42 .arg(to_byte_exc_arg())
43 .arg(force_misalign_arg())
44 .arg(burst_arg().help(
45 "Burst error resistance level used by the container.
46Use this if the level used by the container is above 1000,
47as blkar will only guess up to 1000. Or use this when blkar
48fails to guess correctly. blkar uses this value only if
49output is stdout and container version is RS enabled.",
50 ))
51 .arg(verbose_arg().help("Show reference block info"))
52 .arg(json_arg())
53}
54
55pub fn decode<'a>(matches: &ArgMatches<'a>) -> i32 {
56 let mut json_printer = get_json_printer!(matches);
57
58 let out = matches.value_of("out");
59
60 if let Some(ref f) = out {
62 if file_utils::check_if_file_is_stdout(f) {
63 let output_channel = OutputChannel::Stderr;
64
65 if !json_printer.json_enabled() {
66 print_block!(output_channel =>
67 "Warning :";
68 "";
69 " Since output is stdout, blkar can only output data chunks in the";
70 " anticipated encoding order.";
71 "";
72 " For version with no FEC enabled (version 1, 2, 3), this means blkar";
73 " reads in the sequential pattern with optional metadata block and";
74 " outputs the data chunks.";
75 "";
76 " For version with FEC enabled (version 17, 18, 19), this means blkar";
77 " first guesses the burst resistance level, then reads using the block";
78 " set interleaving pattern and outputs the data chunks.";
79 "";
80 " blkar also tries to strip the data padding at the end of the container";
81 " at a best effort basis, but does not provide any guarantees.";
82 "";
83 " If the ordering matches the anticipated ordering, output of blkar to";
84 " stdout should match the one produced in output to file mode. If the";
85 " ordering is not as anticipated, you may fix it by sorting the SBX";
86 " container using the blkar sort command first.";
87 "";
88 );
89 }
90
91 Arc::get_mut(&mut json_printer)
92 .unwrap()
93 .set_output_channel(output_channel);
94 }
95 }
96
97 json_printer.print_open_bracket(None, BracketType::Curly);
98
99 let pr_verbosity_level = get_pr_verbosity_level!(matches, json_printer);
100
101 let burst = get_burst_opt!(matches, json_printer);
102
103 let in_file = get_in_file!(matches, json_printer);
104
105 let from_pos = get_from_pos!(matches, json_printer);
106 let to_pos = get_to_pos!(matches, json_printer);
107
108 let ref_from_pos = get_ref_from_pos!(matches, json_printer);
109 let ref_to_pos = get_ref_to_pos!(matches, json_printer);
110
111 let guess_burst_from_pos = get_guess_burst_from_pos!(matches, json_printer);
112
113 let param = Param::new(
114 get_ref_block_choice!(matches),
115 ref_from_pos,
116 ref_to_pos,
117 guess_burst_from_pos,
118 matches.is_present("force"),
119 get_multi_pass!(matches, json_printer),
120 &json_printer,
121 from_pos,
122 to_pos,
123 matches.is_present("force_misalign"),
124 in_file,
125 out,
126 matches.is_present("verbose"),
127 pr_verbosity_level,
128 burst,
129 );
130 match decode_core::decode_file(¶m) {
131 Ok(Some(s)) => exit_with_msg!(ok json_printer => "{}", s),
132 Ok(None) => exit_with_msg!(ok json_printer => ""),
133 Err(e) => exit_with_msg!(op json_printer => "{}", e),
134 }
135}