blkar_lib/
cli_macros.rs

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}