use std::fmt;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::ToTokens;
#[derive(Debug, Clone)]
pub struct SpanError {
pub err: Error,
pub span: Option<Span>,
}
impl SpanError {
pub fn new(err: Error, span: Option<Span>) -> Self {
Self { err, span }
}
}
impl PartialEq for SpanError {
fn eq(&self, other: &SpanError) -> bool {
self.err == other.err
}
}
impl From<Error> for SpanError {
fn from(err: Error) -> SpanError {
SpanError { err, span: None }
}
}
impl ToTokens for SpanError {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let span = self.span.unwrap_or_else(Span::call_site);
let token_stream_err = syn::Error::new(span, self.err.clone()).to_compile_error();
token_stream_err.to_tokens(tokens);
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Error {
Parse(String),
MustBeStringLiteral,
UnableToParseTag(String),
ParseTag(String),
UnclosedPlaceholder,
UnclosedTag,
NoTagToClose,
MismatchCloseTag(String, String),
TooManyArgs,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let msg = match self {
Self::Parse(msg) => msg.clone(),
Self::MustBeStringLiteral => "Format string must be a string literal".to_owned(),
Self::UnableToParseTag(tag) => format!("Unable to parse the tag {tag}"),
Self::ParseTag(detail) => detail.clone(),
Self::UnclosedPlaceholder => "Unclosed placeholder".to_owned(),
Self::UnclosedTag => "Unclosed color tag".to_owned(),
Self::NoTagToClose => "No color tag to close".to_owned(),
Self::MismatchCloseTag(tag1, tag2) => {
format!("Mismatch close tag between {tag1} and {tag2}")
},
Self::TooManyArgs => "Too many arguments".to_owned(),
};
write!(f, "{msg}")
}
}