use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{GenericArgument, PathArguments, Type};
pub fn strip_arc_type(ty: &Type) -> Type {
let path = match ty {
Type::Path(tp) => &tp.path,
_ => return ty.clone(),
};
let segs = &path.segments;
if segs.len() == 1 && segs[0].ident == "Arc" {
if let PathArguments::AngleBracketed(ab) = &segs[0].arguments {
if ab.args.len() == 1 {
if let GenericArgument::Type(inner) = &ab.args[0] {
return inner.clone();
}
}
}
}
ty.clone()
}
pub fn extract_option_inner(ty: &Type) -> Option<Type> {
if let Type::Path(type_path) = ty {
if let Some(segment) = type_path.path.segments.last() {
if segment.ident == "Option" {
if let PathArguments::AngleBracketed(args) = &segment.arguments {
if let Some(GenericArgument::Type(inner_ty)) = args.args.first() {
return Some(inner_ty.clone());
}
}
}
}
}
None
}
pub fn is_option_type(ty: &Type) -> bool {
extract_option_inner(ty).is_some()
}
pub fn extract_trait_from_arc(ty: &Type) -> Option<Type> {
let path = match ty {
Type::Path(tp) => &tp.path,
_ => return None,
};
let segs = &path.segments;
if segs.len() != 1 || segs[0].ident != "Arc" {
return None;
}
if let PathArguments::AngleBracketed(ab) = &segs[0].arguments {
if let Some(GenericArgument::Type(trait_ty @ Type::TraitObject(_))) = ab.args.first() {
return Some(trait_ty.clone());
}
}
None
}
pub fn extract_trait_from_option_arc(ty: &Type) -> Option<Type> {
let inner = extract_option_inner(ty)?;
let path = match &inner {
Type::Path(tp) => &tp.path,
_ => return None,
};
let segs = &path.segments;
if segs.len() != 1 || segs[0].ident != "Arc" {
return None;
}
if let PathArguments::AngleBracketed(ab) = &segs[0].arguments {
if let Some(GenericArgument::Type(trait_ty @ Type::TraitObject(_))) = ab.args.first() {
return Some(trait_ty.clone());
}
}
None
}
pub fn is_arc_dyn_trait(ty: &Type) -> bool {
extract_trait_from_option_arc(ty).is_some()
}
pub fn is_plain_arc_dyn_trait(ty: &Type) -> bool {
extract_trait_from_arc(ty).is_some()
}
pub fn extract_trait_from_vec_arc(ty: &Type) -> Option<Type> {
let path = match ty {
Type::Path(tp) => &tp.path,
_ => return None,
};
let segs = &path.segments;
if segs.len() != 1 || segs[0].ident != "Vec" {
return None;
}
if let PathArguments::AngleBracketed(ab) = &segs[0].arguments {
if let Some(GenericArgument::Type(arc_ty)) = ab.args.first() {
return extract_trait_from_arc(arc_ty);
}
}
None
}
pub fn is_vec_arc_dyn_trait(ty: &Type) -> bool {
extract_trait_from_vec_arc(ty).is_some()
}
#[allow(dead_code)]
pub fn strip_arc_tokens(ty: &Type) -> TokenStream2 {
let inner = strip_arc_type(ty);
quote! { #inner }
}