1#[macro_export]
2macro_rules! exit_with_msg {
3 (
4 ok $json_printer:expr => $($x:expr),*
5 ) => {{
6 print_at_output_channel!($json_printer.output_channel() => $($x),*);
7 print_field_if_json!($json_printer, "error : null");
8 $json_printer.print_close_bracket();
9 return 0;
10 }};
11 (
12 usr $json_printer:expr => $($x:expr),*
13 ) => {{
14 if $json_printer.json_enabled() {
15 print_json_field!($json_printer.output_channel() => "error", format!($($x),*), false, $json_printer.first_item());
16 } else {
17 println_at_output_channel!($json_printer.output_channel() => $($x),*);
18 }
19 $json_printer.print_close_bracket();
20 return 1;
21 }};
22 (
23 op $json_printer:expr => $($x:expr),*
24 ) => {{
25 if $json_printer.json_enabled() {
26 print_json_field!($json_printer.output_channel() => "error", format!($($x),*), false, $json_printer.first_item());
27 } else {
28 println_at_output_channel!($json_printer.output_channel() => $($x),*);
29 }
30 $json_printer.print_close_bracket();
31 return 2;
32 }}
33}
34
35macro_rules! exit_if_file {
36 (
37 exists $file:expr => $force_write:expr => $json_printer:expr => $($x:expr),*
38 ) => {{
39 use file_utils;
40 if file_utils::check_if_file_exists($file)
41 && !$force_write
42 {
43 exit_with_msg!(usr $json_printer => $($x),*);
44 }
45 }};
46 (
47 not_exists $file:expr => $json_printer:expr => $($x:expr),*
48 ) => {{
49 use file_utils;
50 if !file_utils::check_if_file_exists($file) {
51 exit_with_msg!(usr $json_printer => $($x),*);
52 }
53 }}
54}
55
56macro_rules! get_pr_verbosity_level {
57 (
58 $matches:expr, $json_enabled:expr
59 ) => {{
60 use progress_report;
61 use progress_report::PRVerbosityLevel;
62 match $matches.value_of("pr_verbosity_level") {
63 None => if get_json_enabled!($matches) { PRVerbosityLevel::L0 } else { PRVerbosityLevel::L2 },
64 Some(x) => match progress_report::string_to_verbosity_level(x) {
65 Ok(x) => x,
66 Err(_) => exit_with_msg!(usr $json_enabled => "Invalid progress report verbosity level")
67 }
68 }
69 }}
70}
71
72macro_rules! get_from_pos {
73 (
74 $matches:expr, $json_enabled:expr
75 ) => {{
76 match $matches.value_of("from_pos") {
77 None => None,
78 Some(x) => match u64::from_str(x) {
79 Ok(x) => Some(x),
80 Err(_) => exit_with_msg!(usr $json_enabled => "Invalid from position")
81 }
82 }
83 }}
84}
85
86macro_rules! get_to_pos {
87 (
88 $matches:expr, $json_enabled:expr
89 ) => {{
90 match $matches.value_of("to_pos") {
91 None => None,
92 Some(x) => match u64::from_str(x) {
93 Ok(x) => Some(x),
94 Err(_) => exit_with_msg!(usr $json_enabled => "Invalid to position")
95 }
96 }
97 }}
98}
99
100macro_rules! get_in_file {
101 (
102 $matches:expr, $json_enabled:expr
103 ) => {{
104 let in_file = $matches.value_of("in_file").unwrap();
105 exit_if_file!(not_exists in_file
106 => $json_enabled
107 => "File \"{}\" does not exist", in_file);
108 in_file
109 }};
110 (
111 accept_stdin $matches:expr, $json_enabled:expr
112 ) => {{
113 use file_utils;
114 let in_file = $matches.value_of("in_file").unwrap();
115 if !file_utils::check_if_file_is_stdin(in_file) {
116 exit_if_file!(not_exists in_file
117 => $json_enabled
118 => "File \"{}\" does not exist", in_file);
119 }
120 in_file
121 }};
122}
123
124macro_rules! get_version {
125 (
126 $matches:expr, $json_enabled:expr
127 ) => {{
128 use sbx_specs::string_to_ver;
129 match $matches.value_of("sbx_version") {
130 None => Version::V1,
131 Some(x) => match string_to_ver(&x) {
132 Ok(v) => v,
133 Err(()) => {
134 exit_with_msg!(usr $json_enabled => "Invalid SBX version");
135 }
136 }
137 }
138 }}
139}
140
141macro_rules! get_data_shards {
142 (
143 $matches:expr, $version:expr, $json_enabled:expr
144 ) => {{
145 use sbx_specs::ver_to_usize;
146
147 let ver_usize = ver_to_usize($version);
148
149 match $matches.value_of("rs_data") {
150 None => {
151 exit_with_msg!(usr $json_enabled => "Reed-Solomon erasure code data shard count must be specified for version {}", ver_usize);
152 },
153 Some(x) => {
154 match usize::from_str(&x) {
155 Ok(x) => x,
156 Err(_) => {
157 exit_with_msg!(usr $json_enabled => "Failed to parse Reed-Solomon erasure code data shard count");
158 }
159 }
160 }
161 }
162 }}
163}
164
165macro_rules! get_parity_shards {
166 (
167 $matches:expr, $version:expr, $json_enabled:expr
168 ) => {{
169 use sbx_specs::ver_to_usize;
170
171 let ver_usize = ver_to_usize($version);
172
173 match $matches.value_of("rs_parity") {
174 None => {
175 exit_with_msg!(usr $json_enabled => "Reed-Solomon erasure code parity shard count must be specified for version {}", ver_usize);
176 },
177 Some(x) => {
178 match usize::from_str(&x) {
179 Ok(x) => x,
180 Err(_) => {
181 exit_with_msg!(usr $json_enabled => "Failed to parse Reed-Solomon erasure code parity shard count");
182 }
183 }
184 }
185 }
186 }}
187}
188
189macro_rules! check_data_parity_shards {
190 (
191 $data_shards:expr, $parity_shards:expr, $json_enabled:expr
192 ) => {{
193 use reed_solomon_erasure::ReedSolomon;
194 use reed_solomon_erasure::Error;
195
196 match ReedSolomon::new($data_shards, $parity_shards) {
197 Ok(_) => {},
198 Err(Error::TooFewDataShards) => {
199 exit_with_msg!(usr $json_enabled => "Too few data shards for Reed-Solomon erasure code");
200 },
201 Err(Error::TooFewParityShards) => {
202 exit_with_msg!(usr $json_enabled => "Too few parity shards for Reed-Solomon erasure code");
203 },
204 Err(Error::TooManyShards) => {
205 exit_with_msg!(usr $json_enabled => "Too many shards for Reed-Solomon erasure code");
206 },
207 Err(_) => { panic!(); }
208 }
209 }}
210}
211
212macro_rules! get_burst_or_zero {
213 (
214 $matches:expr, $json_enabled:expr
215 ) => {{
216 match $matches.value_of("burst") {
217 None => 0,
218 Some(x) => {
219 match usize::from_str(&x) {
220 Ok(x) => x,
221 Err(_) => {
222 exit_with_msg!(usr $json_enabled => "Failed to parse burst error resistance level");
223 }
224 }
225 }
226 }
227 }}
228}
229
230macro_rules! ask_if_wish_to_continue {
231 (
232 ) => {{
233 use std::io::{stdin, stdout, Read, Write};
234
235 print!("Do you wish to continue? [y/N] ");
236
237 stdout().flush().unwrap();
238
239 let mut ans : [u8; 1] = [0; 1];
240
241 let _ = stdin().read(&mut ans).unwrap();
242
243 if ans != *b"y" {
244 return 0;
245 }
246 }}
247}
248
249macro_rules! get_burst_opt {
250 (
251 $matches:expr, $json_enabled:expr
252 ) => {{
253 match $matches.value_of("burst") {
254 None => None,
255 Some(x) => {
256 match usize::from_str(&x) {
257 Ok(x) => Some(x),
258 Err(_) => {
259 exit_with_msg!(usr $json_enabled => "Failed to parse burst error resistance level");
260 }
261 }
262 }
263 }
264 }}
265}
266
267macro_rules! parse_uid {
268 (
269 $buf:expr, $uid:expr, $json_printer:expr
270 ) => {{
271 use misc_utils::HexError;
272 use misc_utils;
273 match misc_utils::hex_string_to_bytes($uid) {
274 Ok(x) => {
275 if x.len() != SBX_FILE_UID_LEN {
276 exit_with_msg!(usr $json_printer => "UID provided does not have the correct number of hex digits, provided : {}, need : {}",
277 $uid.len(),
278 SBX_FILE_UID_LEN * 2);
279 }
280
281 $buf.copy_from_slice(&x);
282 },
283 Err(HexError::InvalidHexString) => {
284 exit_with_msg!(usr $json_printer => "UID provided is not a valid hex string");
285 },
286 Err(HexError::InvalidLen) => {
287 exit_with_msg!(usr $json_printer => "UID provided does not have the correct number of hex digits, provided : {}, need : {}",
288 $uid.len(),
289 SBX_FILE_UID_LEN * 2);
290 }
291 }
292 }}
293}
294
295macro_rules! get_ref_block_choice {
296 (
297 $matches:expr
298 ) => {{
299 use block_utils::RefBlockChoice::*;
300 use sbx_block::BlockType;
301
302 if $matches.is_present("no_meta") {
303 Any
304 } else {
305 Prefer(BlockType::Meta)
306 }
307 }}
308}
309
310macro_rules! get_meta_enabled {
311 (
312 $matches:expr
313 ) => {{
314 !$matches.is_present("no_meta")
315 }}
316}
317
318macro_rules! get_json_enabled {
319 (
320 $matches:expr
321 ) => {{
322 $matches.is_present("json")
323 }}
324}
325
326macro_rules! get_json_printer {
327 (
328 $matches:expr
329 ) => {{
330 use json_printer::JSONPrinter;
331 use std::sync::Arc;
332 use output_channel::OutputChannel;
333
334 Arc::new(JSONPrinter::new($matches.is_present("json"), OutputChannel::Stdout))
335 }}
336}
337
338#[macro_export]
339macro_rules! print_at_output_channel {
340 (
341 $channel:expr => $($x:expr),*
342 ) => {{
343 use output_channel::OutputChannel;
344
345 match $channel {
346 OutputChannel::Stdout => print!($($x),*),
347 OutputChannel::Stderr => eprint!($($x),*),
348 }
349 }}
350}
351
352#[macro_export]
353macro_rules! println_at_output_channel {
354 (
355 $channel:expr => $($x:expr),*
356 ) => {{
357 use output_channel::OutputChannel;
358
359 match $channel {
360 OutputChannel::Stdout => println!($($x),*),
361 OutputChannel::Stderr => eprintln!($($x),*),
362 }
363 }}
364}