use proc_macro2::Ident;
use quote::format_ident;
use syn::parse::ParseStream;
use syn::Result;
use syn::{Expr, Field, GenericArgument, PathArguments, Token, Type};
pub fn type_is_option(ty: &Type) -> bool {
type_of_option(ty).is_some()
}
pub fn type_of_option(ty: &Type) -> Option<&Type> {
let path = match ty {
Type::Path(ty) => &ty.path,
_ => return None,
};
let last = path.segments.last().unwrap();
if last.ident != "Option" {
return None;
}
let bracketed = match &last.arguments {
PathArguments::AngleBracketed(bracketed) => bracketed,
_ => return None,
};
if bracketed.args.len() != 1 {
return None;
}
match &bracketed.args[0] {
GenericArgument::Type(arg) => Some(arg),
_ => None,
}
}
pub fn type_add_colon2(ret: &mut Type) {
if let Type::Path(p) = ret {
let path = &mut p.path;
let segs = &mut path.segments;
for seg in segs {
if let PathArguments::AngleBracketed(ref mut ab) = &mut seg.arguments {
if ab.colon2_token.is_none() {
ab.colon2_token = Some(<Token![::]>::default());
}
}
}
}
}
pub fn meta_list_to_fields(list: &syn::MetaList) -> Result<Vec<Field>> {
list.parse_args_with(|stream: ParseStream| -> Result<Vec<Field>> {
let mut fields: Vec<Field> = vec![];
let named = stream.parse_terminated(Field::parse_named, Token![,])?;
for field in named {
fields.push(field);
}
Ok(fields)
})
}
pub fn meta_list_to_expr(list: &syn::MetaList) -> Result<Vec<Expr>> {
list.parse_args_with(|stream: ParseStream| -> Result<Vec<Expr>> {
let mut exprs = vec![];
while !stream.is_empty() {
let field: Expr = stream.parse()?;
exprs.push(field);
if !stream.is_empty() {
stream.parse::<Token![,]>()?;
}
}
Ok(exprs)
})
}
pub fn get_unname_field_ident(index: usize) -> Ident {
format_ident!("unnamed_{}", index)
}
pub fn is_new_type(fields: &syn::Fields) -> bool {
if let syn::Fields::Unnamed(fields) = fields {
if fields.unnamed.len() == 1 {
return true;
}
}
false
}