1use crate::{ArgCount, ArgType, Span};
2
3pub struct Error {
4 pub span: Span,
5 pub kind: ErrorKind,
6}
7
8pub enum ErrorKind {
9 ParseIntError(std::num::ParseIntError),
11
12 IntegerNotInRange {
13 min: Option<i128>,
14 max: Option<i128>,
15 n: i128,
16 },
17
18 SameFlagMultipleTimes(String, String),
20
21 MissingArgument(String, ArgType),
23
24 WrongArgCount {
25 expected: ArgCount,
26 got: usize,
27 },
28 MissingFlag(String),
29 UnknownFlag {
30 flag: String,
31 similar_flag: Option<String>,
32 },
33}
34
35impl ErrorKind {
36 pub fn render(&self) -> String {
37 match self {
38 ErrorKind::ParseIntError(_) => String::from("Cannot parse int."),
39 ErrorKind::IntegerNotInRange { min, max, n } => match (min, max) {
40 (Some(min), Some(max)) => format!("N is supposed to be between {min} and {max}, but is {n}."),
41 (Some(min), None) => format!("N is supposed to be at least {min}, but is {n}."),
42 (None, Some(max)) => format!("N is supposed to be at most {max}, but is {n}."),
43 (None, None) => unreachable!(),
44 },
45 ErrorKind::SameFlagMultipleTimes(prev, next) => if prev == next {
46 format!("Flag `{next}` cannot be used multiple times.")
47 } else {
48 format!("Flag `{prev}` and `{next}` cannot be used together.")
49 },
50 ErrorKind::MissingArgument(arg, arg_type) => format!(
51 "A {} value is required for flag `{arg}`, but is missing.",
52 format!("{arg_type:?}").to_ascii_lowercase(),
53 ),
54 ErrorKind::WrongArgCount { expected, got } => format!(
55 "Expected {} arguments, got {got} arguments",
56 match expected {
57 ArgCount::Exact(n) => format!("exactly {n}"),
58 ArgCount::Geq(n) => format!("at least {n}"),
59 ArgCount::Leq(n) => format!("at most {n}"),
60 ArgCount::None => String::from("no"),
61 ArgCount::Any => unreachable!(),
62 },
63 ),
64 ErrorKind::MissingFlag(flag) => format!("Flag `{flag}` is missing."),
65 ErrorKind::UnknownFlag { flag, similar_flag } => format!(
66 "Unknown flag: `{flag}`.{}",
67 if let Some(flag) = similar_flag {
68 format!(" There is a similar flag: `{flag}`.")
69 } else {
70 String::new()
71 },
72 ),
73 }
74 }
75}