1use crate::get_cur_exe;
4use std::{fmt, io};
5
6pub type Result<T> = std::result::Result<T, Error>;
8
9#[derive(Debug)]
11pub enum Error {
12    DataRequired(Vec<String>),
14    DataRequiredArg(String), Io(io::Error),
18    InvalidCurExe,
20    CommandNotFound((String, Vec<String>)),
22    ArgumentNotFound((String, Vec<String>)),
24    NothingInputted,
26    InvalidData(&'static str),
28}
29
30impl From<io::Error> for Error {
31    fn from(err: io::Error) -> Self {
32        Self::Io(err)
33    }
34}
35
36impl fmt::Display for Error {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        match self {
39            Error::DataRequired(call) => {
40                write!(
41                    f,
42                    "Data was required after \".. {}\" but was not found",
43                    fmt_call(call)
44                )
45            }
46            Error::DataRequiredArg(arg) => {
47                let fmt_arg = if arg.starts_with('-') {
48                    arg.clone()
49                } else if arg.len() == 1 {
50                    format!("-{}", arg)
51                } else {
52                    format!("--{}", arg)
53                };
54                write!(f, "Data was required for {} but was not found", fmt_arg)
55            }
56            Error::Io(err) => write!(f, "Input/output error, {}", err),
57            Error::InvalidCurExe => write!(f, "Current executable name is invalid"),
58            Error::CommandNotFound((cmd, call)) => {
59                write!(
60                    f,
61                    "Command `{}` not recognized, found inside of `{}` program call",
62                    cmd,
63                    fmt_call(call)
64                )
65            }
66            Error::ArgumentNotFound((arg, call)) => {
67                write!(
68                    f,
69                    "Argument {}{} not recognized, found inside of `{}` program call",
70                    arg_dashes(arg.len()),
71                    arg,
72                    fmt_call(call)
73                )
74            }
75            Error::NothingInputted => write!(f, "Nothing was inputted"),
76            Error::InvalidData(v) => write!(f, "Data provided could not be parsed to {}", v),
77        }
78    }
79}
80
81fn arg_dashes(arg_len: usize) -> &'static str {
84    if arg_len < 2 {
85        "-"
86    } else {
87        "--"
88    }
89}
90
91fn fmt_call(call: &[String]) -> String {
92    let left = match get_cur_exe() {
93        Ok(cur_exe) => cur_exe,
94        Err(_) => String::new(),
95    };
96    format!("{} {}", left, call.join(" "))
97}