ferment-sys 0.2.14

Syntax tree morphing of FFI-compatible stuff
Documentation
use syn::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, Path, Signature, TraitBound, Type, TypeArray, TypeParamBound, TypePath, TypePtr, TypeReference, TypeTraitObject};
use proc_macro2::{Ident, Span, TokenStream as TokenStream2};
use quote::ToTokens;
use crate::ast::AddPunctuated;
use crate::ext::MaybeTraitBound;
use crate::kind::ScopeItemKind;

pub trait MaybeIdent {
    fn maybe_ident(&self) -> Option<&Ident>;
    fn ident_string(&self) -> String {
        self.maybe_ident().map_or("(None)".to_string(), Ident::to_string)
    }
}
impl MaybeIdent for Item {
    fn maybe_ident(&self) -> Option<&Ident> {
        match self {
            Item::Const(ItemConst { ident, .. }) |
            Item::Enum(ItemEnum { ident, .. }) |
            Item::ExternCrate(ItemExternCrate { ident, .. }) |
            Item::Fn(ItemFn { sig: Signature { ident, .. }, .. }) |
            Item::Mod(ItemMod { ident, .. }) |
            Item::Struct(ItemStruct { ident, ..  }) |
            Item::Static(ItemStatic { ident, ..  }) |
            Item::Trait(ItemTrait { ident, ..  }) |
            Item::TraitAlias(ItemTraitAlias { ident, ..  }) |
            Item::Type(ItemType { ident, .. }) |
            Item::Union(ItemUnion { ident, .. }) => Some(ident),
            Item::Macro(ItemMacro { ident, .. }) => ident.as_ref(),
            Item::Impl(ItemImpl { self_ty, .. }) => type_ident_ref(self_ty),
            _ => None
        }
    }
}
impl MaybeIdent for Signature {
    fn maybe_ident(&self) -> Option<&Ident> {
        Some(&self.ident)
    }
}
impl MaybeIdent for ScopeItemKind {
    fn maybe_ident(&self) -> Option<&Ident> {
        match self {
            ScopeItemKind::Item(item, ..) => item.maybe_ident(),
            ScopeItemKind::Fn(sig, ..) => sig.maybe_ident()
        }
    }
}


pub fn usize_to_tokenstream(value: usize) -> TokenStream2 {
    let lit = syn::LitInt::new(&value.to_string(), Span::call_site());
    lit.to_token_stream()
}

pub fn collect_bounds(bounds: &AddPunctuated<TypeParamBound>) -> Vec<Path> {
    bounds.iter()
        .filter_map(MaybeTraitBound::maybe_trait_bound)
        .map(|TraitBound { path, .. }| path.clone())
        .collect()
}
fn path_ident_ref(path: &Path) -> Option<&Ident> {
    path.segments.last().map(|last_segment| &last_segment.ident)
}

fn type_ident_ref(ty: &Type) -> Option<&Ident> {
    match ty {
        Type::Path(TypePath { path, .. }) =>
            path_ident_ref(path),
        Type::Reference(TypeReference { elem, .. }) |
        Type::Ptr(TypePtr { elem, .. }) |
        Type::Array(TypeArray { elem, .. }) =>
            type_ident_ref(elem),
        Type::TraitObject(TypeTraitObject { bounds, .. }) =>
            bounds.iter().find_map(|b| b.maybe_trait_bound().and_then(|TraitBound { path, .. }| path_ident_ref(path))),
        _ => None
    }
}