1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use super::{exit, stdin_reader, Error};
use serde::Serialize;
use std::env::args;
use std::ffi::OsStr;
use std::fs::File;
use std::io::{stdout, BufRead, BufReader};
use std::path::Path;

pub fn parse_args() -> Vec<Box<dyn BufRead>> {
    let mut file_readers: Vec<Box<dyn BufRead>> = vec![];
    let mut arguments = args();
    if arguments.len() > 1 {
        let tool_path = arguments.next().unwrap();
        for arg in arguments {
            match arg.as_str() {
                "-h" | "-?" | "--help" | "-help" => {
                    let suffix = "2json";
                    let tool = Path::new(&tool_path)
                        .file_name()
                        .unwrap_or_else(|| OsStr::new(suffix))
                        .to_string_lossy();
                    let format = tool[..tool.len() - suffix.len()].to_uppercase();
                    eprintln!(
                        "Usage: {tool} [-h|--help] [{format} files... | < <{format} input>]\n\nReads {format} from files or standard input and converts this to JSON, emitted on standard output. Any errors are reported to standard error and result in a non-zero exit code."
                    );
                    exit(0);
                }
                arg => {
                    if Path::new(arg).is_file() {
                        let file = match File::open(arg) {
                            Ok(file) => file,
                            Err(e) => {
                                eprintln!("Error opening file {arg}: {e}");
                                exit(Error::FileOpening as i32);
                            }
                        };
                        file_readers.push(Box::new(BufReader::new(file)))
                    }
                }
            };
        }
    }
    if file_readers.is_empty() {
        file_readers.push(Box::new(stdin_reader()));
    }
    file_readers
}

pub fn stdout_writer<T>(input: &T)
where
    T: ?Sized + Serialize,
{
    if let Err(e) = serde_json::to_writer(stdout(), input) {
        eprintln!("Error serializing output: {e}");
        exit(Error::OutputSerialization as i32);
    }
}