1#[cfg(not(feature = "no_std"))]
10use std::fmt::{Display, Error, Formatter};
11#[cfg(not(feature = "no_std"))]
12use std::slice::Iter;
13
14#[cfg(feature = "no_std")]
15use core::fmt::{Display, Error, Formatter};
16#[cfg(feature = "no_std")]
17use core::slice::Iter;
18
19#[cfg(feature = "no_std")]
20use alloc::string::{String, ToString};
21#[cfg(feature = "no_std")]
22use alloc::vec::Vec;
23
24use crate::HelpVersion;
25
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub enum OptParseErrorKind {
28 HelpMessage,
29 VersionMessage,
30 InvalidOption,
32 MissingOption,
33 #[cfg(feature = "option_argument")]
35 InvalidOptionArgument,
36 #[cfg(feature = "option_argument")]
37 UnexpectedOptionArgument,
38 #[cfg(feature = "option_argument")]
39 MissingOptionArgument,
40 #[cfg(feature = "argument")]
42 UnexpectedArgument,
43 #[cfg(feature = "argument")]
44 MissingArgument,
45 #[cfg(feature = "subcommand")]
47 InvalidSubcommand,
48 #[cfg(feature = "subcommand")]
49 MissingSubcommand,
50 #[cfg(feature = "abbreviate")]
52 AmbiguousOption,
53 #[cfg(all(feature = "abbreviate", feature = "subcommand"))]
54 AmbiguousSubcommand,
55}
56
57#[derive(Debug, PartialEq, Eq)]
59pub struct OptParseError {
60 kind: OptParseErrorKind,
61 desc1: String,
62 desc2: Option<String>,
63}
64
65impl HelpVersion for OptParseError {
66 fn is_help(&self) -> bool {
67 self.kind == OptParseErrorKind::HelpMessage
68 }
69 fn is_version(&self) -> bool {
70 self.kind == OptParseErrorKind::VersionMessage
71 }
72}
73
74impl OptParseError {
75 pub fn kind(&self) -> OptParseErrorKind {
76 self.kind.clone()
77 }
78 pub fn desc1_str(&self) -> &str {
79 self.desc1.as_str()
80 }
81}
82
83impl OptParseError {
84 #[inline(never)]
85 fn new_p1(a_kind: OptParseErrorKind, a_desc1: &str) -> Self {
86 Self {
87 kind: a_kind,
88 desc1: a_desc1.to_string(),
89 desc2: None,
90 }
91 }
92 #[cfg(any(feature = "option_argument", feature = "abbreviate"))]
93 #[inline(never)]
94 fn new_p2(a_kind: OptParseErrorKind, a_desc1: &str, a_desc2: &str) -> Self {
95 let mut r = Self::new_p1(a_kind, a_desc1);
96 r.desc2 = Some(a_desc2.to_string());
97 r
98 }
99 pub fn help_message(desc1: &str) -> Self {
100 Self::new_p1(OptParseErrorKind::HelpMessage, desc1)
101 }
102 pub fn version_message(desc1: &str) -> Self {
103 Self::new_p1(OptParseErrorKind::VersionMessage, desc1)
104 }
105 pub fn invalid_option(desc1: &str) -> Self {
107 Self::new_p1(OptParseErrorKind::InvalidOption, desc1)
108 }
109 pub fn missing_option(desc1: &str) -> Self {
110 Self::new_p1(OptParseErrorKind::MissingOption, desc1)
111 }
112 #[cfg(any(feature = "option_argument", feature = "dox"))]
114 pub fn invalid_option_argument(desc1: &str, desc2: &str) -> Self {
115 Self::new_p2(OptParseErrorKind::InvalidOptionArgument, desc1, desc2)
116 }
117 #[cfg(any(feature = "option_argument", feature = "dox"))]
118 pub fn unexpected_option_argument(desc1: &str, desc2: &str) -> Self {
119 Self::new_p2(OptParseErrorKind::UnexpectedOptionArgument, desc1, desc2)
120 }
121 #[cfg(any(feature = "option_argument", feature = "dox"))]
122 pub fn missing_option_argument(desc1: &str) -> Self {
123 Self::new_p1(OptParseErrorKind::MissingOptionArgument, desc1)
124 }
125 #[cfg(any(feature = "argument", feature = "dox"))]
127 pub fn unexpected_argument(desc1: &str) -> Self {
128 Self::new_p1(OptParseErrorKind::UnexpectedArgument, desc1)
129 }
130 #[cfg(any(feature = "argument", feature = "dox"))]
131 pub fn missing_argument(desc1: &str) -> Self {
132 Self::new_p1(OptParseErrorKind::MissingArgument, desc1)
133 }
134 #[cfg(any(feature = "subcommand", feature = "dox"))]
136 pub fn invalid_subcommand(desc1: &str) -> Self {
137 Self::new_p1(OptParseErrorKind::InvalidSubcommand, desc1)
138 }
139 #[cfg(any(feature = "subcommand", feature = "dox"))]
140 pub fn missing_subcommand(desc1: &str) -> Self {
141 Self::new_p1(OptParseErrorKind::MissingSubcommand, desc1)
142 }
143 #[cfg(any(feature = "abbreviate", feature = "dox"))]
145 pub fn ambiguous_option(desc1: &str, desc2: &str) -> Self {
146 Self::new_p2(OptParseErrorKind::AmbiguousOption, desc1, desc2)
147 }
148 #[cfg(any(all(feature = "abbreviate", feature = "subcommand"), feature = "dox"))]
149 pub fn ambiguous_subcommand(desc1: &str, desc2: &str) -> Self {
150 Self::new_p2(OptParseErrorKind::AmbiguousSubcommand, desc1, desc2)
151 }
152}
153
154impl Display for OptParseError {
155 fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
156 use self::OptParseErrorKind::*;
157 let msg: &str = match self.kind {
159 HelpMessage | VersionMessage => {
160 return write!(fmt, "{}", &self.desc1);
161 }
162 InvalidOption => "Invalid option",
164 MissingOption => "Missing option",
165 #[cfg(feature = "option_argument")]
167 InvalidOptionArgument => "Invalid option argument",
168 #[cfg(feature = "option_argument")]
169 UnexpectedOptionArgument => "Unexpected option argument",
170 #[cfg(feature = "option_argument")]
171 MissingOptionArgument => "Missing option argument",
172 #[cfg(feature = "argument")]
174 UnexpectedArgument => "Unexpected argument",
175 #[cfg(feature = "argument")]
176 MissingArgument => "Missing argument",
177 #[cfg(feature = "subcommand")]
179 InvalidSubcommand => "Invalid subcommand",
180 #[cfg(feature = "subcommand")]
181 MissingSubcommand => "Missing subcommand",
182 #[cfg(feature = "abbreviate")]
184 AmbiguousOption => "Ambiguous option",
185 #[cfg(all(feature = "abbreviate", feature = "subcommand"))]
186 AmbiguousSubcommand => "Ambiguous subcommand",
187 };
188 match self.desc2 {
189 Some(ref s) => write!(fmt, "{}: {}: {}", msg, &self.desc1, &s),
190 None => write!(fmt, "{}: {}", msg, &self.desc1),
191 }
192 }
193}
194
195#[cfg(any(not(feature = "no_std"), feature = "dox"))]
196impl std::error::Error for OptParseError {}
197
198#[derive(Debug, PartialEq, Eq)]
200pub struct OptParseErrors(Vec<OptParseError>);
201
202impl OptParseErrors {
203 pub fn new() -> OptParseErrors {
204 OptParseErrors(Vec::with_capacity(0))
205 }
206 pub fn is_empty(&self) -> bool {
207 self.0.is_empty()
208 }
209 pub fn len(&self) -> usize {
210 self.0.len()
211 }
212 pub fn push(&mut self, e: OptParseError) {
213 self.0.push(e)
214 }
215 pub fn iter(&self) -> Iter<'_, OptParseError> {
216 self.0.iter()
217 }
218 pub fn append(&mut self, other: Self) {
219 self.0.extend(other.0)
220 }
221}
222impl Default for OptParseErrors {
223 fn default() -> Self {
224 Self::new()
225 }
226}
227impl Display for OptParseErrors {
228 fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
229 use std::fmt::Write;
230 if self.is_empty() {
232 write!(fmt, "")
233 } else {
234 let mut s = String::new();
235 for err in self.iter() {
236 let _ = writeln!(s, "{err}");
237 }
238 write!(fmt, "{}", &s[0..(s.len() - 1)])
239 }
240 }
241}
242#[cfg(any(not(feature = "no_std"), feature = "dox"))]
243impl std::error::Error for OptParseErrors {}