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