1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
pub use proc_macro2::{Span, TokenTree};
// To keep the Error passing simple and allocation free for the common cases we define these
// common cases plus adding the generic case as dyn boxed error.
/// Error type for parsing.
pub enum Error {
/// Trying to parse `expected` but found `found`.
UnexpectedToken {
/// type name of what was expected
expected: &'static str,
/// the token that was found
found: TokenTree,
},
/// Trying to parse `expected` but found the end of the input.
UnexpectedEnd {
/// type name of what was expected
expected: &'static str,
},
/// Something else failed which can be fully formatted as `String`.
Other {
/// explanation what failed
reason: String,
},
/// Any other error.
Boxed(Box<dyn std::error::Error>),
}
impl Error {
/// Create a `Result<T>::Err(Error::UnexpectedToken)` error.
#[allow(clippy::missing_errors_doc)]
pub fn unexpected_token<T>(found: TokenTree) -> Result<T> {
Err(Error::UnexpectedToken {
expected: std::any::type_name::<T>(),
found,
})
}
/// Create a `Result<T>::Err(Error::UnexpectedEnd)` error.
#[allow(clippy::missing_errors_doc)]
pub fn unexpected_end<T>() -> Result<T> {
Err(Error::UnexpectedEnd {
expected: std::any::type_name::<T>(),
})
}
/// Create a `Result<T>::Err(Error::Other)` error.
#[allow(clippy::missing_errors_doc)]
pub fn other<T>(reason: String) -> Result<T> {
Err(Error::Other { reason })
}
/// Create a `Error::Boxed` error.
pub fn boxed(err: impl std::error::Error + 'static) -> Self {
Error::Boxed(Box::new(err))
}
}
impl std::error::Error for Error {}
impl std::fmt::Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Error::UnexpectedToken { expected, found } => {
write!(
f,
"Unexpected token: expected {expected}, found {found:?} at {:?}",
found.span().start()
)
}
Error::UnexpectedEnd { expected } => {
write!(f, "Unexpected end of input: expected {expected}")
}
Error::Other { reason } => {
write!(f, "{reason}")
}
Error::Boxed(err) => {
write!(f, "Error: {err}")
}
}
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Error::UnexpectedToken { expected, found } => {
write!(
f,
"Unexpected token: expected {expected}, found {found:?} at {:?}",
found.span().start()
)
}
Error::UnexpectedEnd { expected } => {
write!(f, "Unexpected end of input: expected {expected}")
}
Error::Other { reason } => {
write!(f, "{reason}")
}
Error::Boxed(err) => {
write!(f, "Error: {err}")
}
}
}
}
/// Result type for parsing.
pub type Result<T> = std::result::Result<T, Error>;