use super::bindgen::ExternEnum;
use syn::TypePath;
pub(crate) fn type_path_ends_with(tp: &TypePath, ty: &str) -> bool {
match tp.path.segments.last() {
Some(last) => last.ident == ty,
None => false,
}
}
pub(crate) fn type_path_is_enum<'a>(
tp: &TypePath,
enums: &'a [ExternEnum],
) -> Option<&'a ExternEnum> {
match tp.path.segments.last() {
Some(segment) => enums.iter().find(|ee| ee.ident == segment.ident),
None => None,
}
}
pub(crate) fn search_enum_attribute(
attr: &syn::Attribute,
path_search: &str,
token_searches: &[&str],
) -> Option<syn::Ident> {
if let Ok(meta) = attr.parse_meta() {
if let syn::Meta::List(list) = &meta {
if let Some(path) = list.path.segments.last() {
if path.ident != path_search {
return None;
}
} else {
return None;
}
}
match &meta {
syn::Meta::List(list) => {
for nested_meta in &list.nested {
if let syn::NestedMeta::Meta(syn::Meta::Path(path)) = nested_meta {
for segment in &path.segments {
if token_searches.iter().any(|search| segment.ident == search) {
return Some(segment.ident.clone());
}
}
}
}
}
_ => return None,
}
}
None
}
pub(crate) fn has_custom_attribute(attr: &syn::Attribute, to_compare: &syn::Attribute) -> bool {
attr.path == to_compare.path
}
pub(crate) fn extract_generic_type(
pos: usize,
expected_len: Option<usize>,
ty: &syn::TypePath,
) -> syn::parse::Result<Option<syn::TypePath>> {
use syn::parse::Error;
use syn::spanned::Spanned;
use syn::Type;
match ty.path.segments.last() {
Some(last) => {
if let syn::PathArguments::AngleBracketed(args) = &last.arguments {
if let Some(expected_len) = expected_len {
if args.args.len() != expected_len {
return Err(Error::new(
args.span(),
format!("expected {} type arguments", expected_len),
));
}
}
if pos >= args.args.len() {
return Err(Error::new(
args.span(),
format!("missing {}th type argument", pos),
));
}
if let syn::GenericArgument::Type(ty) = &args.args[pos] {
match ty {
Type::Path(tp) => Ok(Some(tp.clone())),
Type::Tuple(t) => {
if t.elems.is_empty() {
Ok(None)
} else {
Err(Error::new(ty.span(), "non-unit tuples are not supported"))
}
}
_ => Err(Error::new(ty.span(), "unsupported generic argument")),
}
} else {
Err(Error::new(args.args[0].span(), "expected a type argument"))
}
} else {
Err(Error::new(last.span(), "expected a generic"))
}
}
None => Err(Error::new(ty.span(), "expected a generic")),
}
}
pub(crate) fn extract_first_generic_type(
ty: &syn::TypePath,
) -> syn::parse::Result<Option<syn::TypePath>> {
extract_generic_type(0, None, ty)
}
pub(crate) fn extract_single_generic_type(
ty: &syn::TypePath,
) -> syn::parse::Result<Option<syn::TypePath>> {
extract_generic_type(0, Some(1), ty)
}