use std::borrow::Borrow;
use syn;
pub fn fields_to_vec(fields: syn::Fields) -> Vec<syn::Field> {
use syn::Fields::*;
match fields {
Named(fields) => fields.named.into_iter().collect(),
Unnamed(fields) => fields.unnamed.into_iter().collect(),
Unit => vec![],
}
}
pub fn is_unit_type<T: Borrow<syn::Type>>(ty: T) -> bool {
ty.borrow() == &parse_quote!(())
}
pub fn self_ty() -> syn::Type {
parse_quote!(Self)
}
type CommaPS = syn::punctuated::Punctuated<syn::PathSegment, Token![::]>;
fn is_path_simple(path: &syn::Path) -> bool {
path.segments.iter().all(|ps| ps.arguments.is_empty())
}
fn eq_simple_pathseg(lhs: &str, rhs: &CommaPS) -> bool {
lhs.split("::")
.filter(|s| !s.trim().is_empty())
.eq(rhs.iter().map(|ps| ps.ident.to_string()))
}
pub fn eq_simple_path(mut lhs: &str, rhs: &syn::Path) -> bool {
if !is_path_simple(rhs) {
return false;
}
if rhs.leading_colon.is_some() {
if !lhs.starts_with("::") {
return false;
}
lhs = &lhs[2..];
}
eq_simple_pathseg(lhs, &rhs.segments)
}
pub fn match_pathsegs(path: &syn::Path, against: &[&str]) -> bool {
against.iter().any(|needle| eq_simple_path(needle, path))
}
fn pseg_has_single_tyvar(pp: &syn::PathSegment) -> bool {
use syn::GenericArgument::Type;
use syn::PathArguments::AngleBracketed;
if let AngleBracketed(ab) = &pp.arguments {
if let Some(Type(_)) = match_singleton(ab.args.iter()) {
return true;
}
}
false
}
pub fn is_phantom_data(path: &syn::Path) -> bool {
let segs = &path.segments;
if segs.is_empty() {
return false;
}
let mut path = path.clone();
let lseg = path.segments.pop().unwrap().into_value();
&lseg.ident == "PhantomData"
&& pseg_has_single_tyvar(&lseg)
&& match_pathsegs(
&path,
&[
"",
"marker",
"std::marker",
"core::marker",
"::std::marker",
"::core::marker",
],
)
}
pub fn extract_simple_path(path: &syn::Path) -> Option<&syn::Ident> {
match_singleton(&path.segments)
.filter(|f| !path_is_global(path) && f.arguments.is_empty())
.map(|f| &f.ident)
}
pub fn path_is_global(path: &syn::Path) -> bool {
path.leading_colon.is_some()
}
pub fn match_singleton<T>(it: impl IntoIterator<Item = T>) -> Option<T> {
let mut it = it.into_iter();
it.next().filter(|_| it.next().is_none())
}