use proc_macro2::TokenStream;
#[cfg(feature = "debug")]
use quote::ToTokens;
use syn::{Attribute, Expr, ExprLit, ItemStruct, Lit, Path};
use crate::error::err;
pub fn attribute(
src_struct: &ItemStruct,
derive_name: &str,
name: &str,
) -> Result<Attribute, TokenStream> {
for attribute in src_struct.attrs.iter() {
let path = &attribute.path();
if path.segments.len() != 1 {
continue;
}
let attribute_name = path.segments.first().unwrap().ident.to_string();
if name == attribute_name.as_str() {
return Ok(attribute.clone());
}
}
Err(err!(
src_struct.ident,
"{} requires the '{}' attribute.",
derive_name,
name
))
}
pub fn input_paths(args: Expr) -> Result<Vec<Path>, TokenStream> {
fn lit_to_path(expr: ExprLit) -> Result<Path, TokenStream> {
match expr.lit {
Lit::Str(lit_str) => match lit_str.parse_with(syn::Path::parse_mod_style) {
Err(_) => Err(err!(
lit_str,
"Only paths are allowed in inter_struct's attributes."
)),
Ok(path) => Ok(path),
},
_ => Err(err!(
expr,
"Only paths are allowed in inter_struct's attribute."
)),
}
}
match args {
Expr::Lit(expr) => lit_to_path(expr).map(|path| vec![path]),
Expr::Array(array) => {
let mut paths = vec![];
for expr in array.elems {
match expr {
Expr::Lit(expr) => {
let path = lit_to_path(expr)?;
paths.push(path);
}
_ => {
err!(expr, "Only paths are allowed in inter_struct's attribute.");
}
}
}
Ok(paths)
}
_ => Err(err!(
args,
"inter_struct's macro parameters should be either a single path {} ",
"or a vector of paths as str, such as '[\"crate::your::path\"]'."
)),
}
}