1use std::fmt;
2
3use beef::lean::Cow;
4use proc_macro2::{Span, TokenStream};
5use quote::quote;
6use quote::{quote_spanned, ToTokens, TokenStreamExt};
7
8pub type Result<T> = std::result::Result<T, Error>;
9
10#[derive(Default)]
11pub struct Errors {
12 collected: Vec<SpannedError>,
13}
14
15impl Errors {
16 pub fn err<M>(&mut self, message: M, span: Span) -> &mut Self
17 where
18 M: Into<Cow<'static, str>>,
19 {
20 self.collected.push(SpannedError {
21 message: message.into(),
22 span,
23 });
24
25 self
26 }
27
28 pub fn render(self) -> Option<TokenStream> {
29 let errors = self.collected;
30
31 match errors.len() {
32 0 => None,
33 _ => Some(quote! {
34 fn _logos_derive_compile_errors() {
35 #(#errors)*
36 }
37 }),
38 }
39 }
40}
41
42pub struct Error(Cow<'static, str>);
43
44#[derive(Debug)]
45pub struct SpannedError {
46 message: Cow<'static, str>,
47 span: Span,
48}
49
50impl Error {
51 pub fn new<M>(message: M) -> Self
52 where
53 M: Into<Cow<'static, str>>,
54 {
55 Error(message.into())
56 }
57
58 pub fn span(self, span: Span) -> SpannedError {
59 SpannedError {
60 message: self.0,
61 span,
62 }
63 }
64}
65
66impl fmt::Display for Error {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 self.0.fmt(f)
69 }
70}
71
72impl fmt::Debug for Error {
73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 fmt::Display::fmt(self, f)
75 }
76}
77
78impl From<regex_syntax::Error> for Error {
79 fn from(err: regex_syntax::Error) -> Error {
80 Error(err.to_string().into())
81 }
82}
83
84impl From<&'static str> for Error {
85 fn from(err: &'static str) -> Error {
86 Error(err.into())
87 }
88}
89
90impl From<String> for Error {
91 fn from(err: String) -> Error {
92 Error(err.into())
93 }
94}
95
96impl From<Error> for Cow<'static, str> {
97 fn from(err: Error) -> Self {
98 err.0
99 }
100}
101
102impl ToTokens for SpannedError {
103 fn to_tokens(&self, tokens: &mut TokenStream) {
104 let message = &*self.message;
105
106 tokens.append_all(quote_spanned!(self.span => {
107 compile_error!(#message)
108 }))
109 }
110}