pub fn from_ast(
        crate_name: &str,
        attr: TokenStream,
        item: TokenStream,
    ) -> ParseResult<ComInterface>
    {
        let item: syn::Item = ::syn::parse2(item).map_err(|_| {
            ParseError::ComInterface("<Unknown>".into(), "Item syntax error".into())
        })?;

        let attr: ComInterfaceAttr = ::syn::parse2(attr).map_err(|_| {
            ParseError::ComInterface(
                item.get_ident().unwrap().to_string(),
                "Attribute syntax error".into(),
            )
        })?;

        // Get the interface details. As [com_interface] can be applied to both
        // impls and traits this handles both of those.
        let (path, fns, itf_type, unsafety) =
            crate::utils::get_ident_and_fns(&item).ok_or_else(|| {
                ParseError::ComInterface(
                    item.get_ident().unwrap().to_string(),
                    "Unsupported associated item".into(),
                )
            })?;

        let ident = path.get_some_ident().ok_or_else(|| {
            ParseError::ComInterface(
                path.to_token_stream().to_string(),
                "Could not resolve ident for".to_string(),
            )
        })?;

        // The second argument is the optional base class. If there's no base
        // class defined, use IUnknown as the default. The value of NO_BASE will
        // construct an interface that has no base class.
        //
        // In practice the NO_BASE should be used ONLY for the IUnknown itself.
        let base = attr
            .base()
            .map_err(|msg| ParseError::ComInterface(item.get_ident().unwrap().to_string(), msg))?;
        let base = match base {
            Some(b) => {
                if b.get_ident().map(|i| i == "NO_BASE") == Some(true) {
                    None
                } else {
                    Some(b.to_owned())
                }
            }
            None => Some(syn::parse2(quote!(intercom::IUnknown)).unwrap()),
        };

        // Visibility for trait interfaces is the visibility of the trait.
        //
        // For implicit interfaces (impl Struct) the visibility is always public.
        // These interfaces should only exist for COM types that are meant to be
        // called from external sources as they can't be impl'd for random ComItf.
        //
        // Note this may conflict with visibility of the actual [com_class], but
        // nothing we can do for this really.
        let visibility = if let ::syn::Item::Trait(ref t) = item {
            t.vis.clone()
        } else {
            parse_quote!(pub)
        };

        let variants = IndexMap::from_iter(
            [ModelTypeSystem::Automation, ModelTypeSystem::Raw]
                .iter()
                .map(|&ts| {
                    let iid_attr = attr.iid(ts).map_err(|msg| {
                        ParseError::ComInterface(item.get_ident().unwrap().to_string(), msg)
                    })?;
                    let iid = match iid_attr {
                        Some(iid) => GUID::parse(&iid.value()).map_err(|_| {
                            ParseError::ComInterface(
                                item.get_ident().unwrap().to_string(),
                                "Bad IID format".into(),
                            )
                        })?,
                        None => crate::utils::generate_iid(crate_name, &ident.to_string(), ts),
                    };

                    // Read the method details.
                    //
                    // TODO: Currently we ignore invalid methods. We should probably do
                    //       something smarter.
                    let methods = fns
                        .iter()
                        .map(|sig| ComMethodInfo::new(sig, ts))
                        .filter_map(Result::ok)
                        .collect::<Vec<_>>();

                    Ok((
                        ts,
                        ComInterfaceVariant {
                            type_system: ts,
                            iid,
                            methods,
                        },
                    ))
                })
                .collect::<Result<Vec<_>, _>>()?,
        );

        let itf_ref = match itf_type {
            crate::utils::InterfaceType::Trait => quote_spanned!(ident.span() => dyn #path),
            crate::utils::InterfaceType::Struct => quote_spanned!(ident.span() => #path),
        };

        Ok(ComInterface {
            base_interface: base,
            item_type: itf_type,
            is_unsafe: unsafety.is_some(),
            span: ident.span(),
            vtable_of: attr
                .vtable_of()
                .map_err(|e| ParseError::ComInterface(ident.to_string(), e))?
                .cloned(),
            implemented_by: attr
                .implemented_by()
                .map_err(|e| ParseError::ComInterface(ident.to_string(), e))?
                .cloned(),
            path,
            ident,
            visibility,
            variants,
            itf_ref,
        })
    }
/// Creates ComInterface from AST elements.
Creates ComInterface from AST elements.
Creates ComInterface from AST elements .
pub fn from_ast(
        crate_name: &str,
        attr: TokenStream,
        item: TokenStream,
    ) -> ParseResult<ComInterface>
    {
        let item: syn::Item = ::syn::parse2(item).map_err(|_| {
            ParseError::ComInterface("<Unknown>".into(), "Item syntax error".into())
        })?;
        let attr: ComInterfaceAttr = ::syn::parse2(attr).map_err(|_| {
            ParseError::ComInterface(
                item.get_ident().unwrap().to_string(),
                "Attribute syntax error".into(),
            )
        })?;
        // Get the interface details. As [com_interface] can be applied to both
        // impls and traits this handles both of those.
        let (path, fns, itf_type, unsafety) =
            crate::utils::get_ident_and_fns(&item).ok_or_else(|| {
                ParseError::ComInterface(
                    item.get_ident().unwrap().to_string(),
                    "Unsupported associated item".into(),
                )
            })?;
        let ident = path.get_some_ident().ok_or_else(|| {
            ParseError::ComInterface(
                path.to_token_stream().to_string(),
                "Could not resolve ident for".to_string(),
            )
        })?;
        // The second argument is the optional base class. If there's no base
        // class defined, use IUnknown as the default. The value of NO_BASE will
        // construct an interface that has no base class.
        //
        // In practice the NO_BASE should be used ONLY for the IUnknown itself.
        let base = attr
            .base()
            .map_err(|msg| ParseError::ComInterface(item.get_ident().unwrap().to_string(), msg))?;
        let base = match base {
            Some(b) => {
                if b.get_ident().map(|i| i == "NO_BASE") == Some(true) {
                    None
                } else {
                    Some(b.to_owned())
                }
            }
            None => Some(syn::parse2(quote!(intercom::IUnknown)).unwrap()),
        };
        // Visibility for trait interfaces is the visibility of the trait.
        //
        // For implicit interfaces (impl Struct) the visibility is always public.
        // These interfaces should only exist for COM types that are meant to be
        // called from external sources as they can't be impl'd for random ComItf.
        //
        // Note this may conflict with visibility of the actual [com_class], but
        // nothing we can do for this really.
        let visibility = if let ::syn::Item::Trait(ref t) = item {
            t.vis.clone()
        } else {
            parse_quote!(pub)
        };
        let variants = IndexMap::from_iter(
            [ModelTypeSystem::Automation, ModelTypeSystem::Raw]
                .iter()
                .map(|&ts| {
                    let iid_attr = attr.iid(ts).map_err(|msg| {
                        ParseError::ComInterface(item.get_ident().unwrap().to_string(), msg)
                    })?;
                    let iid = match iid_attr {
                        Some(iid) => GUID::parse(&iid.value()).map_err(|_| {
                            ParseError::ComInterface(
                                item.get_ident().unwrap().to_string(),
                                "Bad IID format".into(),
                            )
                        })?,
                        None => crate::utils::generate_iid(crate_name, &ident.to_string(), ts),
                    };
                    // Read the method details.
                    //
                    // TODO: Currently we ignore invalid methods. We should probably do
                    //       something smarter.
                    let methods = fns
                        .iter()
                        .map(|sig| ComMethodInfo::new(sig, ts))
                        .filter_map(Result::ok)
                        .collect::<Vec<_>>();
                    Ok((
                        ts,
                        ComInterfaceVariant {
                            type_system: ts,
                            iid,
                            methods,
                        },
                    ))
                })
                .collect::<Result<Vec<_>, _>>()?,
        );
        let itf_ref = match itf_type {
            crate::utils::InterfaceType::Trait => quote_spanned!(ident.span() => dyn #path),
            crate::utils::InterfaceType::Struct => quote_spanned!(ident.span() => #path),
        };
        Ok(ComInterface {
            base_interface: base,
            item_type: itf_type,
            is_unsafe: unsafety.is_some(),
            span: ident.span(),
            vtable_of: attr
                .vtable_of()
                .map_err(|e| ParseError::ComInterface(ident.to_string(), e))?
                .cloned(),
            implemented_by: attr
                .implemented_by()
                .map_err(|e| ParseError::ComInterface(ident.to_string(), e))?
                .cloned(),
            path,
            ident,
            visibility,
            variants,
            itf_ref,
        })
    }
pub fn from_ast ( crate_name : & str , attr : TokenStream , item : TokenStream , ) -> ParseResult < ComInterface > { let item : syn :: Item = :: syn :: parse2 ( item ) . map_err ( | _ | { ParseError :: ComInterface ( " " . into ( ) , " " . into ( ) ) } ) ? ; let attr : ComInterfaceAttr = :: syn :: parse2 ( attr ) . map_err ( | _ | { ParseError :: ComInterface ( item . get_ident ( ) . unwrap ( ) . to_string ( ) , " " . into ( ) , ) } ) ? ; // Get the interface details. As [com_interface] can be applied to both // impls and traits this handles both of those. let ( path , fns , itf_type , unsafety ) = crate :: utils :: get_ident_and_fns ( & item ) . ok_or_else ( | | { ParseError :: ComInterface ( item . get_ident ( ) . unwrap ( ) . to_string ( ) , " " . into ( ) , ) } ) ? ; let ident = path . get_some_ident ( ) . ok_or_else ( | | { ParseError :: ComInterface ( path . to_token_stream ( ) . to_string ( ) , " " . to_string ( ) , ) } ) ? ; // The second argument is the optional base class. If there's no base // class defined, use IUnknown as the default. The value of NO_BASE will // construct an interface that has no base class. // // In practice the NO_BASE should be used ONLY for the IUnknown itself. let base = attr . base ( ) . map_err ( | msg | ParseError :: ComInterface ( item . get_ident ( ) . unwrap ( ) . to_string ( ) , msg ) ) ? ; let base = match base { Some ( b ) => { if b . get_ident ( ) . map ( | i | i == " " ) == Some ( true ) { None } else { Some ( b . to_owned ( ) ) } } None => Some ( syn :: parse2 ( quote ! ( intercom IUnknown ) ) . unwrap ( ) ) , } ; // Visibility for trait interfaces is the visibility of the trait. // // For implicit interfaces (impl Struct) the visibility is always public. // These interfaces should only exist for COM types that are meant to be // called from external sources as they can't be impl'd for random ComItf. // // Note this may conflict with visibility of the actual [com_class], but // nothing we can do for this really. let visibility = if let :: syn :: Item :: Trait ( ref t ) = item { t . vis . clone ( ) } else { parse_quote ! ( pub ) } ; let variants = IndexMap :: from_iter ( [ ModelTypeSystem :: Automation , ModelTypeSystem :: Raw ] . iter ( ) . map ( | & ts | { let iid_attr = attr . iid ( ts ) . map_err ( | msg | { ParseError :: ComInterface ( item . get_ident ( ) . unwrap ( ) . to_string ( ) , msg ) } ) ? ; let iid = match iid_attr { Some ( iid ) => GUID :: parse ( & iid . value ( ) ) . map_err ( | _ | { ParseError :: ComInterface ( item . get_ident ( ) . unwrap ( ) . to_string ( ) , " " . into ( ) , ) } ) ? , None => crate :: utils :: generate_iid ( crate_name , & ident . to_string ( ) , ts ) , } ; // Read the method details. // // TODO: Currently we ignore invalid methods. We should probably do //       something smarter. let methods = fns . iter ( ) . map ( | sig | ComMethodInfo :: new ( sig , ts ) ) . filter_map ( Result :: ok ) . collect :: < Vec < _ > > ( ) ; Ok ( ( ts , ComInterfaceVariant { type_system : ts , iid , methods , } , ) ) } ) . collect :: < Result < Vec < _ > , _ > > ( ) ? , ) ; let itf_ref = match itf_type { crate :: utils :: InterfaceType :: Trait => quote_spanned ! ( ident span ( ) dyn path ) , crate :: utils :: InterfaceType :: Struct => quote_spanned ! ( ident span ( ) path ) , } ; Ok ( ComInterface { base_interface : base , item_type : itf_type , is_unsafe : unsafety . is_some ( ) , span : ident . span ( ) , vtable_of : attr . vtable_of ( ) . map_err ( | e | ParseError :: ComInterface ( ident . to_string ( ) , e ) ) ? . cloned ( ) , implemented_by : attr . implemented_by ( ) . map_err ( | e | ParseError :: ComInterface ( ident . to_string ( ) , e ) ) ? . cloned ( ) , path , ident , visibility , variants , itf_ref , } ) }
Creates ComInterface from AST elements.
Creates ComInterface from AST elements .
crate_name
&str
attr
TokenStream
item
TokenStream
crate_name
&str
attr
TokenStream
item
TokenStream