119625d8cSopenharmony_ci//! Special types handling 219625d8cSopenharmony_ci 319625d8cSopenharmony_ciuse super::spanned::Sp; 419625d8cSopenharmony_ci 519625d8cSopenharmony_ciuse syn::{ 619625d8cSopenharmony_ci spanned::Spanned, GenericArgument, Path, PathArguments, PathArguments::AngleBracketed, 719625d8cSopenharmony_ci PathSegment, Type, TypePath, 819625d8cSopenharmony_ci}; 919625d8cSopenharmony_ci 1019625d8cSopenharmony_ci#[derive(Copy, Clone, PartialEq, Eq, Debug)] 1119625d8cSopenharmony_cipub enum Ty { 1219625d8cSopenharmony_ci Unit, 1319625d8cSopenharmony_ci Vec, 1419625d8cSopenharmony_ci VecVec, 1519625d8cSopenharmony_ci Option, 1619625d8cSopenharmony_ci OptionOption, 1719625d8cSopenharmony_ci OptionVec, 1819625d8cSopenharmony_ci OptionVecVec, 1919625d8cSopenharmony_ci Other, 2019625d8cSopenharmony_ci} 2119625d8cSopenharmony_ci 2219625d8cSopenharmony_ciimpl Ty { 2319625d8cSopenharmony_ci pub fn from_syn_ty(ty: &syn::Type) -> Sp<Self> { 2419625d8cSopenharmony_ci use self::Ty::*; 2519625d8cSopenharmony_ci let t = |kind| Sp::new(kind, ty.span()); 2619625d8cSopenharmony_ci 2719625d8cSopenharmony_ci if is_unit_ty(ty) { 2819625d8cSopenharmony_ci t(Unit) 2919625d8cSopenharmony_ci } else if let Some(vt) = get_vec_ty(ty, Vec, VecVec) { 3019625d8cSopenharmony_ci t(vt) 3119625d8cSopenharmony_ci } else if let Some(subty) = subty_if_name(ty, "Option") { 3219625d8cSopenharmony_ci if is_generic_ty(subty, "Option") { 3319625d8cSopenharmony_ci t(OptionOption) 3419625d8cSopenharmony_ci } else if let Some(vt) = get_vec_ty(subty, OptionVec, OptionVecVec) { 3519625d8cSopenharmony_ci t(vt) 3619625d8cSopenharmony_ci } else { 3719625d8cSopenharmony_ci t(Option) 3819625d8cSopenharmony_ci } 3919625d8cSopenharmony_ci } else { 4019625d8cSopenharmony_ci t(Other) 4119625d8cSopenharmony_ci } 4219625d8cSopenharmony_ci } 4319625d8cSopenharmony_ci 4419625d8cSopenharmony_ci pub fn as_str(&self) -> &'static str { 4519625d8cSopenharmony_ci match self { 4619625d8cSopenharmony_ci Self::Unit => "()", 4719625d8cSopenharmony_ci Self::Vec => "Vec<T>", 4819625d8cSopenharmony_ci Self::Option => "Option<T>", 4919625d8cSopenharmony_ci Self::OptionOption => "Option<Option<T>>", 5019625d8cSopenharmony_ci Self::OptionVec => "Option<Vec<T>>", 5119625d8cSopenharmony_ci Self::VecVec => "Vec<Vec<T>>", 5219625d8cSopenharmony_ci Self::OptionVecVec => "Option<Vec<Vec<T>>>", 5319625d8cSopenharmony_ci Self::Other => "...other...", 5419625d8cSopenharmony_ci } 5519625d8cSopenharmony_ci } 5619625d8cSopenharmony_ci} 5719625d8cSopenharmony_ci 5819625d8cSopenharmony_cipub fn inner_type(field_ty: &syn::Type) -> &syn::Type { 5919625d8cSopenharmony_ci let ty = Ty::from_syn_ty(field_ty); 6019625d8cSopenharmony_ci match *ty { 6119625d8cSopenharmony_ci Ty::Vec | Ty::Option => sub_type(field_ty).unwrap_or(field_ty), 6219625d8cSopenharmony_ci Ty::OptionOption | Ty::OptionVec | Ty::VecVec => { 6319625d8cSopenharmony_ci sub_type(field_ty).and_then(sub_type).unwrap_or(field_ty) 6419625d8cSopenharmony_ci } 6519625d8cSopenharmony_ci Ty::OptionVecVec => sub_type(field_ty) 6619625d8cSopenharmony_ci .and_then(sub_type) 6719625d8cSopenharmony_ci .and_then(sub_type) 6819625d8cSopenharmony_ci .unwrap_or(field_ty), 6919625d8cSopenharmony_ci _ => field_ty, 7019625d8cSopenharmony_ci } 7119625d8cSopenharmony_ci} 7219625d8cSopenharmony_ci 7319625d8cSopenharmony_cipub fn sub_type(ty: &syn::Type) -> Option<&syn::Type> { 7419625d8cSopenharmony_ci subty_if(ty, |_| true) 7519625d8cSopenharmony_ci} 7619625d8cSopenharmony_ci 7719625d8cSopenharmony_cifn only_last_segment(mut ty: &syn::Type) -> Option<&PathSegment> { 7819625d8cSopenharmony_ci while let syn::Type::Group(syn::TypeGroup { elem, .. }) = ty { 7919625d8cSopenharmony_ci ty = elem; 8019625d8cSopenharmony_ci } 8119625d8cSopenharmony_ci match ty { 8219625d8cSopenharmony_ci Type::Path(TypePath { 8319625d8cSopenharmony_ci qself: None, 8419625d8cSopenharmony_ci path: 8519625d8cSopenharmony_ci Path { 8619625d8cSopenharmony_ci leading_colon: None, 8719625d8cSopenharmony_ci segments, 8819625d8cSopenharmony_ci }, 8919625d8cSopenharmony_ci }) => only_one(segments.iter()), 9019625d8cSopenharmony_ci 9119625d8cSopenharmony_ci _ => None, 9219625d8cSopenharmony_ci } 9319625d8cSopenharmony_ci} 9419625d8cSopenharmony_ci 9519625d8cSopenharmony_cifn subty_if<F>(ty: &syn::Type, f: F) -> Option<&syn::Type> 9619625d8cSopenharmony_ciwhere 9719625d8cSopenharmony_ci F: FnOnce(&PathSegment) -> bool, 9819625d8cSopenharmony_ci{ 9919625d8cSopenharmony_ci only_last_segment(ty) 10019625d8cSopenharmony_ci .filter(|segment| f(segment)) 10119625d8cSopenharmony_ci .and_then(|segment| { 10219625d8cSopenharmony_ci if let AngleBracketed(args) = &segment.arguments { 10319625d8cSopenharmony_ci only_one(args.args.iter()).and_then(|genneric| { 10419625d8cSopenharmony_ci if let GenericArgument::Type(ty) = genneric { 10519625d8cSopenharmony_ci Some(ty) 10619625d8cSopenharmony_ci } else { 10719625d8cSopenharmony_ci None 10819625d8cSopenharmony_ci } 10919625d8cSopenharmony_ci }) 11019625d8cSopenharmony_ci } else { 11119625d8cSopenharmony_ci None 11219625d8cSopenharmony_ci } 11319625d8cSopenharmony_ci }) 11419625d8cSopenharmony_ci} 11519625d8cSopenharmony_ci 11619625d8cSopenharmony_cipub fn subty_if_name<'a>(ty: &'a syn::Type, name: &str) -> Option<&'a syn::Type> { 11719625d8cSopenharmony_ci subty_if(ty, |seg| seg.ident == name) 11819625d8cSopenharmony_ci} 11919625d8cSopenharmony_ci 12019625d8cSopenharmony_cipub fn is_simple_ty(ty: &syn::Type, name: &str) -> bool { 12119625d8cSopenharmony_ci only_last_segment(ty) 12219625d8cSopenharmony_ci .map(|segment| { 12319625d8cSopenharmony_ci if let PathArguments::None = segment.arguments { 12419625d8cSopenharmony_ci segment.ident == name 12519625d8cSopenharmony_ci } else { 12619625d8cSopenharmony_ci false 12719625d8cSopenharmony_ci } 12819625d8cSopenharmony_ci }) 12919625d8cSopenharmony_ci .unwrap_or(false) 13019625d8cSopenharmony_ci} 13119625d8cSopenharmony_ci 13219625d8cSopenharmony_cifn is_generic_ty(ty: &syn::Type, name: &str) -> bool { 13319625d8cSopenharmony_ci subty_if_name(ty, name).is_some() 13419625d8cSopenharmony_ci} 13519625d8cSopenharmony_ci 13619625d8cSopenharmony_cifn is_unit_ty(ty: &syn::Type) -> bool { 13719625d8cSopenharmony_ci if let syn::Type::Tuple(tuple) = ty { 13819625d8cSopenharmony_ci tuple.elems.is_empty() 13919625d8cSopenharmony_ci } else { 14019625d8cSopenharmony_ci false 14119625d8cSopenharmony_ci } 14219625d8cSopenharmony_ci} 14319625d8cSopenharmony_ci 14419625d8cSopenharmony_cifn only_one<I, T>(mut iter: I) -> Option<T> 14519625d8cSopenharmony_ciwhere 14619625d8cSopenharmony_ci I: Iterator<Item = T>, 14719625d8cSopenharmony_ci{ 14819625d8cSopenharmony_ci iter.next().filter(|_| iter.next().is_none()) 14919625d8cSopenharmony_ci} 15019625d8cSopenharmony_ci 15119625d8cSopenharmony_ci#[cfg(feature = "unstable-v5")] 15219625d8cSopenharmony_cifn get_vec_ty(ty: &Type, vec_ty: Ty, vecvec_ty: Ty) -> Option<Ty> { 15319625d8cSopenharmony_ci subty_if_name(ty, "Vec").map(|subty| { 15419625d8cSopenharmony_ci if is_generic_ty(subty, "Vec") { 15519625d8cSopenharmony_ci vecvec_ty 15619625d8cSopenharmony_ci } else { 15719625d8cSopenharmony_ci vec_ty 15819625d8cSopenharmony_ci } 15919625d8cSopenharmony_ci }) 16019625d8cSopenharmony_ci} 16119625d8cSopenharmony_ci 16219625d8cSopenharmony_ci#[cfg(not(feature = "unstable-v5"))] 16319625d8cSopenharmony_cifn get_vec_ty(ty: &Type, vec_ty: Ty, _vecvec_ty: Ty) -> Option<Ty> { 16419625d8cSopenharmony_ci is_generic_ty(ty, "Vec").then_some(vec_ty) 16519625d8cSopenharmony_ci} 166