evitable_syn_meta_ext/error/
mod.rs1use proc_macro2::{Span, TokenStream};
2use std::error::Error as StdError;
3use std::fmt;
4use std::iter::{self, Iterator};
5use std::string::ToString;
6use std::vec;
7use syn::spanned::Spanned;
8use syn::{Lit, LitStr};
9
10mod kind;
11
12use self::kind::{ErrorKind, ErrorUnknownField};
13
14pub type Result<T> = ::std::result::Result<T, Error>;
16
17#[derive(Debug)]
22#[cfg_attr(test, derive(Clone))]
23pub struct Error {
24 kind: ErrorKind,
25 locations: Vec<String>,
26 span: Option<Span>,
28}
29
30impl Error {
32 pub(self) fn new(kind: ErrorKind) -> Self {
33 Error {
34 kind,
35 locations: Vec::new(),
36 span: None,
37 }
38 }
39
40 pub fn custom<T: fmt::Display>(msg: T) -> Self {
42 Error::new(ErrorKind::Custom(msg.to_string()))
43 }
44
45 pub fn duplicate_field(name: &str) -> Self {
47 Error::new(ErrorKind::DuplicateField(name.into()))
48 }
49
50 pub fn missing_field(name: &str) -> Self {
52 Error::new(ErrorKind::MissingField(name.into()))
53 }
54
55 pub fn unknown_field(name: &str) -> Self {
58 Error::new(ErrorKind::UnknownField(name.into()))
59 }
60
61 pub fn unknown_field_with_alts<'a, T, I>(field: &str, alternates: I) -> Self
65 where
66 T: AsRef<str> + 'a,
67 I: IntoIterator<Item = &'a T>,
68 {
69 Error::new(ErrorUnknownField::with_alts(field, alternates).into())
70 }
71
72 pub fn unsupported_shape(shape: &str) -> Self {
74 Error::new(ErrorKind::UnsupportedShape(shape.into()))
75 }
76
77 pub fn unsupported_format(format: &str) -> Self {
78 Error::new(ErrorKind::UnexpectedFormat(format.into()))
79 }
80
81 pub fn unexpected_type(ty: &str) -> Self {
83 Error::new(ErrorKind::UnexpectedType(ty.into()))
84 }
85
86 pub fn unexpected_lit_type(lit: &Lit) -> Self {
90 Error::unexpected_type(match *lit {
91 Lit::Str(_) => "string",
92 Lit::ByteStr(_) => "byte string",
93 Lit::Byte(_) => "byte",
94 Lit::Char(_) => "char",
95 Lit::Int(_) => "int",
96 Lit::Float(_) => "float",
97 Lit::Bool(_) => "bool",
98 Lit::Verbatim(_) => "verbatim",
99 })
100 .with_span(lit)
101 }
102
103 pub fn unknown_value(value: &str) -> Self {
105 Error::new(ErrorKind::UnknownValue(value.into()))
106 }
107
108 pub fn too_few_items(min: usize) -> Self {
110 Error::new(ErrorKind::TooFewItems(min))
111 }
112
113 pub fn too_many_items(max: usize) -> Self {
116 Error::new(ErrorKind::TooManyItems(max))
117 }
118
119 pub fn multiple(mut errors: Vec<Error>) -> Self {
124 if errors.len() > 1 {
125 Error::new(ErrorKind::Multiple(errors))
126 } else if errors.len() == 1 {
127 errors
128 .pop()
129 .expect("Error array of length 1 has a first item")
130 } else {
131 panic!("Can't deal with 0 errors")
132 }
133 }
134}
135
136impl From<syn::Error> for Error {
137 fn from(e: syn::Error) -> Self {
138 let mut ret = Error::new(ErrorKind::Parse(e.to_string()));
139 ret.span = Some(e.span());
140 ret
141 }
142}
143
144impl Error {
145 pub(crate) fn unknown_lit_str_value(value: &LitStr) -> Self {
149 Error::unknown_value(&value.value()).with_span(value)
150 }
151}
152
153impl Error {
155 pub fn has_span(&self) -> bool {
157 self.span.is_some()
158 }
159
160 pub fn with_span<T: Spanned>(mut self, node: &T) -> Self {
172 if !self.has_span() {
173 self.span = Some(node.span());
174 }
175
176 self
177 }
178
179 pub fn flatten(self) -> Self {
181 Error::multiple(self.into_vec())
182 }
183
184 fn into_vec(self) -> Vec<Self> {
185 if let ErrorKind::Multiple(errors) = self.kind {
186 let mut flat = Vec::new();
187 for error in errors {
188 flat.extend(error.prepend_at(self.locations.clone()).into_vec());
189 }
190
191 flat
192 } else {
193 vec![self]
194 }
195 }
196
197 pub fn at<T: fmt::Display>(mut self, location: T) -> Self {
200 self.locations.insert(0, location.to_string());
201 self
202 }
203
204 pub fn len(&self) -> usize {
209 self.kind.len()
210 }
211
212 fn prepend_at(mut self, mut locations: Vec<String>) -> Self {
214 if !locations.is_empty() {
215 locations.extend(self.locations);
216 self.locations = locations;
217 }
218
219 self
220 }
221
222 #[cfg(test)]
224 pub(crate) fn location(&self) -> Vec<&str> {
225 self.locations.iter().map(|i| i.as_str()).collect()
226 }
227
228 pub fn write_errors(self) -> TokenStream {
233 self
234 .flatten()
235 .into_iter()
236 .map(|e| e.single_to_syn_error().to_compile_error())
237 .collect()
238 }
239
240 fn single_to_syn_error(self) -> ::syn::Error {
241 match self.span {
242 Some(span) => ::syn::Error::new(span, self.kind),
243 None => ::syn::Error::new(Span::call_site(), self),
244 }
245 }
246}
247
248impl StdError for Error {
249 fn description(&self) -> &str {
250 &self.kind.description()
251 }
252
253 fn cause(&self) -> Option<&StdError> {
254 None
255 }
256}
257
258impl fmt::Display for Error {
259 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
260 write!(f, "{}", self.kind)?;
261 if !self.locations.is_empty() {
262 write!(f, " at {}", self.locations.join("/"))?;
263 }
264
265 Ok(())
266 }
267}
268
269#[cfg(test)]
273impl PartialEq for Error {
274 fn eq(&self, other: &Self) -> bool {
275 self.kind == other.kind && self.locations == other.locations
276 }
277}
278
279#[cfg(test)]
280impl Eq for Error {}
281
282impl IntoIterator for Error {
283 type Item = Error;
284 type IntoIter = IntoIter;
285
286 fn into_iter(self) -> IntoIter {
287 if let ErrorKind::Multiple(errors) = self.kind {
288 IntoIter {
289 inner: IntoIterEnum::Multiple(errors.into_iter()),
290 }
291 } else {
292 IntoIter {
293 inner: IntoIterEnum::Single(iter::once(self)),
294 }
295 }
296 }
297}
298
299enum IntoIterEnum {
300 Single(iter::Once<Error>),
301 Multiple(vec::IntoIter<Error>),
302}
303
304impl Iterator for IntoIterEnum {
305 type Item = Error;
306
307 fn next(&mut self) -> Option<Self::Item> {
308 match *self {
309 IntoIterEnum::Single(ref mut content) => content.next(),
310 IntoIterEnum::Multiple(ref mut content) => content.next(),
311 }
312 }
313}
314
315pub struct IntoIter {
317 inner: IntoIterEnum,
318}
319
320impl Iterator for IntoIter {
321 type Item = Error;
322
323 fn next(&mut self) -> Option<Error> {
324 self.inner.next()
325 }
326}
327
328#[cfg(test)]
329mod tests {
330 use super::Error;
331
332 #[test]
333 fn flatten_noop() {
334 let err = Error::duplicate_field("hello").at("world");
335 assert_eq!(err.clone().flatten(), err);
336 }
337
338 #[test]
339 fn flatten_simple() {
340 let err = Error::multiple(vec![
341 Error::unknown_field("hello").at("world"),
342 Error::missing_field("hell_no").at("world"),
343 ])
344 .at("foo")
345 .flatten();
346
347 assert!(err.location().is_empty());
348
349 let mut err_iter = err.into_iter();
350
351 let first = err_iter.next();
352 assert!(first.is_some());
353 assert_eq!(first.unwrap().location(), vec!["foo", "world"]);
354
355 let second = err_iter.next();
356 assert!(second.is_some());
357
358 assert_eq!(second.unwrap().location(), vec!["foo", "world"]);
359
360 assert!(err_iter.next().is_none());
361 }
362
363 #[test]
364 fn len_single() {
365 let err = Error::duplicate_field("hello");
366 assert_eq!(1, err.len());
367 }
368
369 #[test]
370 fn len_multiple() {
371 let err = Error::multiple(vec![
372 Error::duplicate_field("hello"),
373 Error::missing_field("hell_no"),
374 ]);
375 assert_eq!(2, err.len());
376 }
377
378 #[test]
379 fn len_nested() {
380 let err = Error::multiple(vec![
381 Error::duplicate_field("hello"),
382 Error::multiple(vec![
383 Error::duplicate_field("hi"),
384 Error::missing_field("bye"),
385 Error::multiple(vec![Error::duplicate_field("whatsup")]),
386 ]),
387 ]);
388
389 assert_eq!(4, err.len());
390 }
391}