use proc_macro2::{Ident, Span};
use syn::parse::{Parse, ParseStream};
use syn::{parenthesized, Attribute, Expr, ExprLit, Lit, Meta, MetaNameValue, Result};
macro_rules! error {
($msg:expr) => {
syn::Error::new(proc_macro2::Span::call_site(), $msg)
};
($span:expr, $msg:expr) => {
syn::Error::new($span, $msg)
};
}
pub(crate) use error;
macro_rules! return_error {
($msg:expr) => {
return Err(crate::utils::error!($msg))
};
($span:expr, $msg:expr) => {
return Err(crate::utils::error!($span, $msg))
};
}
pub(crate) use return_error;
macro_rules! result_to_tokens {
($result:expr) => {
match $result {
Ok(data) => data,
Err(err) => err.to_compile_error().into(),
}
};
}
pub(crate) use result_to_tokens;
macro_rules! match_attr {
(for $id:ident in $attrs:ident if $name:literal && $cond:expr => $body:block) => {
for $id in $attrs {
match &$id.meta {
syn::Meta::List($id) if $id.path.is_ident($name) => {
if $cond $body else {
use syn::spanned::Spanned;
crate::utils::return_error!(
$id.span(),
concat!("attribute `", $name, "` is bound more than once")
);
}
}
_ => {}
}
}
};
}
pub(crate) use match_attr;
pub struct Parenthesized<T>(pub T);
impl<T: Parse> Parse for Parenthesized<T> {
fn parse(input: ParseStream) -> Result<Self> {
let content;
parenthesized!(content in input);
Ok(Self(content.parse()?))
}
}
pub fn ident(s: &str) -> Ident {
Ident::new(s, Span::call_site())
}
pub fn parse_doc_comments(attrs: &[Attribute]) -> Option<String> {
attrs
.iter()
.filter_map(|attr| match &attr.meta {
Meta::NameValue(MetaNameValue {
path,
value: Expr::Lit(ExprLit {
lit: Lit::Str(s), ..
}),
..
}) if path.is_ident("doc") => Some(s.value().trim().to_string()),
_ => None,
})
.reduce(|mut s, cur| {
s.reserve(cur.len() + 1);
s.push(' ');
s.push_str(&cur);
s
})
.and_then(|s| {
let s = s.trim().to_string();
(!s.is_empty()).then_some(s)
})
}
pub fn camel_to_lower(s: String) -> String {
let mut ans = String::new();
for c in s.chars() {
if c.is_ascii_uppercase() {
if !ans.is_empty() {
ans.push(' ');
}
ans.push(c.to_ascii_lowercase());
} else {
ans.push(c);
}
}
ans
}