133d722a9Sopenharmony_ciuse crate::syntax::attrs::OtherAttrs; 233d722a9Sopenharmony_ciuse crate::syntax::cfg::CfgExpr; 333d722a9Sopenharmony_ciuse crate::syntax::discriminant::DiscriminantSet; 433d722a9Sopenharmony_ciuse crate::syntax::file::{Item, ItemForeignMod}; 533d722a9Sopenharmony_ciuse crate::syntax::report::Errors; 633d722a9Sopenharmony_ciuse crate::syntax::Atom::*; 733d722a9Sopenharmony_ciuse crate::syntax::{ 833d722a9Sopenharmony_ci attrs, error, Api, Array, Derive, Doc, Enum, EnumRepr, ExternFn, ExternType, ForeignName, Impl, 933d722a9Sopenharmony_ci Include, IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Ptr, Receiver, Ref, 1033d722a9Sopenharmony_ci Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var, Variant, 1133d722a9Sopenharmony_ci}; 1233d722a9Sopenharmony_ciuse proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree}; 1333d722a9Sopenharmony_ciuse quote::{format_ident, quote, quote_spanned}; 1433d722a9Sopenharmony_ciuse std::mem; 1533d722a9Sopenharmony_ciuse syn::parse::{ParseStream, Parser}; 1633d722a9Sopenharmony_ciuse syn::punctuated::Punctuated; 1733d722a9Sopenharmony_ciuse syn::{ 1833d722a9Sopenharmony_ci Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, 1933d722a9Sopenharmony_ci GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr, 2033d722a9Sopenharmony_ci Pat, PathArguments, Result, ReturnType, Signature as RustSignature, Token, TraitBound, 2133d722a9Sopenharmony_ci TraitBoundModifier, Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypePtr, 2233d722a9Sopenharmony_ci TypeReference, Variant as RustVariant, Visibility, 2333d722a9Sopenharmony_ci}; 2433d722a9Sopenharmony_ci 2533d722a9Sopenharmony_cipub mod kw { 2633d722a9Sopenharmony_ci syn::custom_keyword!(Pin); 2733d722a9Sopenharmony_ci syn::custom_keyword!(Result); 2833d722a9Sopenharmony_ci} 2933d722a9Sopenharmony_ci 3033d722a9Sopenharmony_cipub fn parse_items( 3133d722a9Sopenharmony_ci cx: &mut Errors, 3233d722a9Sopenharmony_ci items: Vec<Item>, 3333d722a9Sopenharmony_ci trusted: bool, 3433d722a9Sopenharmony_ci namespace: &Namespace, 3533d722a9Sopenharmony_ci) -> Vec<Api> { 3633d722a9Sopenharmony_ci let mut apis = Vec::new(); 3733d722a9Sopenharmony_ci for item in items { 3833d722a9Sopenharmony_ci match item { 3933d722a9Sopenharmony_ci Item::Struct(item) => match parse_struct(cx, item, namespace) { 4033d722a9Sopenharmony_ci Ok(strct) => apis.push(strct), 4133d722a9Sopenharmony_ci Err(err) => cx.push(err), 4233d722a9Sopenharmony_ci }, 4333d722a9Sopenharmony_ci Item::Enum(item) => apis.push(parse_enum(cx, item, namespace)), 4433d722a9Sopenharmony_ci Item::ForeignMod(foreign_mod) => { 4533d722a9Sopenharmony_ci parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace) 4633d722a9Sopenharmony_ci } 4733d722a9Sopenharmony_ci Item::Impl(item) => match parse_impl(cx, item) { 4833d722a9Sopenharmony_ci Ok(imp) => apis.push(imp), 4933d722a9Sopenharmony_ci Err(err) => cx.push(err), 5033d722a9Sopenharmony_ci }, 5133d722a9Sopenharmony_ci Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED), 5233d722a9Sopenharmony_ci Item::Other(item) => cx.error(item, "unsupported item"), 5333d722a9Sopenharmony_ci } 5433d722a9Sopenharmony_ci } 5533d722a9Sopenharmony_ci apis 5633d722a9Sopenharmony_ci} 5733d722a9Sopenharmony_ci 5833d722a9Sopenharmony_cifn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> Result<Api> { 5933d722a9Sopenharmony_ci let mut cfg = CfgExpr::Unconditional; 6033d722a9Sopenharmony_ci let mut doc = Doc::new(); 6133d722a9Sopenharmony_ci let mut derives = Vec::new(); 6233d722a9Sopenharmony_ci let mut namespace = namespace.clone(); 6333d722a9Sopenharmony_ci let mut cxx_name = None; 6433d722a9Sopenharmony_ci let mut rust_name = None; 6533d722a9Sopenharmony_ci let attrs = attrs::parse( 6633d722a9Sopenharmony_ci cx, 6733d722a9Sopenharmony_ci mem::take(&mut item.attrs), 6833d722a9Sopenharmony_ci attrs::Parser { 6933d722a9Sopenharmony_ci cfg: Some(&mut cfg), 7033d722a9Sopenharmony_ci doc: Some(&mut doc), 7133d722a9Sopenharmony_ci derives: Some(&mut derives), 7233d722a9Sopenharmony_ci namespace: Some(&mut namespace), 7333d722a9Sopenharmony_ci cxx_name: Some(&mut cxx_name), 7433d722a9Sopenharmony_ci rust_name: Some(&mut rust_name), 7533d722a9Sopenharmony_ci ..Default::default() 7633d722a9Sopenharmony_ci }, 7733d722a9Sopenharmony_ci ); 7833d722a9Sopenharmony_ci 7933d722a9Sopenharmony_ci let named_fields = match item.fields { 8033d722a9Sopenharmony_ci Fields::Named(fields) => fields, 8133d722a9Sopenharmony_ci Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")), 8233d722a9Sopenharmony_ci Fields::Unnamed(_) => { 8333d722a9Sopenharmony_ci return Err(Error::new_spanned(item, "tuple structs are not supported")); 8433d722a9Sopenharmony_ci } 8533d722a9Sopenharmony_ci }; 8633d722a9Sopenharmony_ci 8733d722a9Sopenharmony_ci let mut lifetimes = Punctuated::new(); 8833d722a9Sopenharmony_ci let mut has_unsupported_generic_param = false; 8933d722a9Sopenharmony_ci for pair in item.generics.params.into_pairs() { 9033d722a9Sopenharmony_ci let (param, punct) = pair.into_tuple(); 9133d722a9Sopenharmony_ci match param { 9233d722a9Sopenharmony_ci GenericParam::Lifetime(param) => { 9333d722a9Sopenharmony_ci if !param.bounds.is_empty() && !has_unsupported_generic_param { 9433d722a9Sopenharmony_ci let msg = "lifetime parameter with bounds is not supported yet"; 9533d722a9Sopenharmony_ci cx.error(¶m, msg); 9633d722a9Sopenharmony_ci has_unsupported_generic_param = true; 9733d722a9Sopenharmony_ci } 9833d722a9Sopenharmony_ci lifetimes.push_value(param.lifetime); 9933d722a9Sopenharmony_ci if let Some(punct) = punct { 10033d722a9Sopenharmony_ci lifetimes.push_punct(punct); 10133d722a9Sopenharmony_ci } 10233d722a9Sopenharmony_ci } 10333d722a9Sopenharmony_ci GenericParam::Type(param) => { 10433d722a9Sopenharmony_ci if !has_unsupported_generic_param { 10533d722a9Sopenharmony_ci let msg = "struct with generic type parameter is not supported yet"; 10633d722a9Sopenharmony_ci cx.error(¶m, msg); 10733d722a9Sopenharmony_ci has_unsupported_generic_param = true; 10833d722a9Sopenharmony_ci } 10933d722a9Sopenharmony_ci } 11033d722a9Sopenharmony_ci GenericParam::Const(param) => { 11133d722a9Sopenharmony_ci if !has_unsupported_generic_param { 11233d722a9Sopenharmony_ci let msg = "struct with const generic parameter is not supported yet"; 11333d722a9Sopenharmony_ci cx.error(¶m, msg); 11433d722a9Sopenharmony_ci has_unsupported_generic_param = true; 11533d722a9Sopenharmony_ci } 11633d722a9Sopenharmony_ci } 11733d722a9Sopenharmony_ci } 11833d722a9Sopenharmony_ci } 11933d722a9Sopenharmony_ci 12033d722a9Sopenharmony_ci if let Some(where_clause) = &item.generics.where_clause { 12133d722a9Sopenharmony_ci cx.error( 12233d722a9Sopenharmony_ci where_clause, 12333d722a9Sopenharmony_ci "struct with where-clause is not supported yet", 12433d722a9Sopenharmony_ci ); 12533d722a9Sopenharmony_ci } 12633d722a9Sopenharmony_ci 12733d722a9Sopenharmony_ci let mut fields = Vec::new(); 12833d722a9Sopenharmony_ci for field in named_fields.named { 12933d722a9Sopenharmony_ci let ident = field.ident.unwrap(); 13033d722a9Sopenharmony_ci let mut cfg = CfgExpr::Unconditional; 13133d722a9Sopenharmony_ci let mut doc = Doc::new(); 13233d722a9Sopenharmony_ci let mut cxx_name = None; 13333d722a9Sopenharmony_ci let mut rust_name = None; 13433d722a9Sopenharmony_ci let attrs = attrs::parse( 13533d722a9Sopenharmony_ci cx, 13633d722a9Sopenharmony_ci field.attrs, 13733d722a9Sopenharmony_ci attrs::Parser { 13833d722a9Sopenharmony_ci cfg: Some(&mut cfg), 13933d722a9Sopenharmony_ci doc: Some(&mut doc), 14033d722a9Sopenharmony_ci cxx_name: Some(&mut cxx_name), 14133d722a9Sopenharmony_ci rust_name: Some(&mut rust_name), 14233d722a9Sopenharmony_ci ..Default::default() 14333d722a9Sopenharmony_ci }, 14433d722a9Sopenharmony_ci ); 14533d722a9Sopenharmony_ci let ty = match parse_type(&field.ty) { 14633d722a9Sopenharmony_ci Ok(ty) => ty, 14733d722a9Sopenharmony_ci Err(err) => { 14833d722a9Sopenharmony_ci cx.push(err); 14933d722a9Sopenharmony_ci continue; 15033d722a9Sopenharmony_ci } 15133d722a9Sopenharmony_ci }; 15233d722a9Sopenharmony_ci let visibility = visibility_pub(&field.vis, ident.span()); 15333d722a9Sopenharmony_ci let name = pair(Namespace::default(), &ident, cxx_name, rust_name); 15433d722a9Sopenharmony_ci let colon_token = field.colon_token.unwrap(); 15533d722a9Sopenharmony_ci fields.push(Var { 15633d722a9Sopenharmony_ci cfg, 15733d722a9Sopenharmony_ci doc, 15833d722a9Sopenharmony_ci attrs, 15933d722a9Sopenharmony_ci visibility, 16033d722a9Sopenharmony_ci name, 16133d722a9Sopenharmony_ci colon_token, 16233d722a9Sopenharmony_ci ty, 16333d722a9Sopenharmony_ci }); 16433d722a9Sopenharmony_ci } 16533d722a9Sopenharmony_ci 16633d722a9Sopenharmony_ci let struct_token = item.struct_token; 16733d722a9Sopenharmony_ci let visibility = visibility_pub(&item.vis, struct_token.span); 16833d722a9Sopenharmony_ci let name = pair(namespace, &item.ident, cxx_name, rust_name); 16933d722a9Sopenharmony_ci let generics = Lifetimes { 17033d722a9Sopenharmony_ci lt_token: item.generics.lt_token, 17133d722a9Sopenharmony_ci lifetimes, 17233d722a9Sopenharmony_ci gt_token: item.generics.gt_token, 17333d722a9Sopenharmony_ci }; 17433d722a9Sopenharmony_ci let brace_token = named_fields.brace_token; 17533d722a9Sopenharmony_ci 17633d722a9Sopenharmony_ci Ok(Api::Struct(Struct { 17733d722a9Sopenharmony_ci cfg, 17833d722a9Sopenharmony_ci doc, 17933d722a9Sopenharmony_ci derives, 18033d722a9Sopenharmony_ci attrs, 18133d722a9Sopenharmony_ci visibility, 18233d722a9Sopenharmony_ci struct_token, 18333d722a9Sopenharmony_ci name, 18433d722a9Sopenharmony_ci generics, 18533d722a9Sopenharmony_ci brace_token, 18633d722a9Sopenharmony_ci fields, 18733d722a9Sopenharmony_ci })) 18833d722a9Sopenharmony_ci} 18933d722a9Sopenharmony_ci 19033d722a9Sopenharmony_cifn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api { 19133d722a9Sopenharmony_ci let mut cfg = CfgExpr::Unconditional; 19233d722a9Sopenharmony_ci let mut doc = Doc::new(); 19333d722a9Sopenharmony_ci let mut derives = Vec::new(); 19433d722a9Sopenharmony_ci let mut repr = None; 19533d722a9Sopenharmony_ci let mut namespace = namespace.clone(); 19633d722a9Sopenharmony_ci let mut cxx_name = None; 19733d722a9Sopenharmony_ci let mut rust_name = None; 19833d722a9Sopenharmony_ci let mut variants_from_header = None; 19933d722a9Sopenharmony_ci let attrs = attrs::parse( 20033d722a9Sopenharmony_ci cx, 20133d722a9Sopenharmony_ci item.attrs, 20233d722a9Sopenharmony_ci attrs::Parser { 20333d722a9Sopenharmony_ci cfg: Some(&mut cfg), 20433d722a9Sopenharmony_ci doc: Some(&mut doc), 20533d722a9Sopenharmony_ci derives: Some(&mut derives), 20633d722a9Sopenharmony_ci repr: Some(&mut repr), 20733d722a9Sopenharmony_ci namespace: Some(&mut namespace), 20833d722a9Sopenharmony_ci cxx_name: Some(&mut cxx_name), 20933d722a9Sopenharmony_ci rust_name: Some(&mut rust_name), 21033d722a9Sopenharmony_ci variants_from_header: Some(&mut variants_from_header), 21133d722a9Sopenharmony_ci ..Default::default() 21233d722a9Sopenharmony_ci }, 21333d722a9Sopenharmony_ci ); 21433d722a9Sopenharmony_ci 21533d722a9Sopenharmony_ci if !item.generics.params.is_empty() { 21633d722a9Sopenharmony_ci let vis = &item.vis; 21733d722a9Sopenharmony_ci let enum_token = item.enum_token; 21833d722a9Sopenharmony_ci let ident = &item.ident; 21933d722a9Sopenharmony_ci let generics = &item.generics; 22033d722a9Sopenharmony_ci let span = quote!(#vis #enum_token #ident #generics); 22133d722a9Sopenharmony_ci cx.error(span, "enum with generic parameters is not supported"); 22233d722a9Sopenharmony_ci } else if let Some(where_clause) = &item.generics.where_clause { 22333d722a9Sopenharmony_ci cx.error(where_clause, "enum with where-clause is not supported"); 22433d722a9Sopenharmony_ci } 22533d722a9Sopenharmony_ci 22633d722a9Sopenharmony_ci let mut variants = Vec::new(); 22733d722a9Sopenharmony_ci let mut discriminants = DiscriminantSet::new(repr); 22833d722a9Sopenharmony_ci for variant in item.variants { 22933d722a9Sopenharmony_ci match parse_variant(cx, variant, &mut discriminants) { 23033d722a9Sopenharmony_ci Ok(variant) => variants.push(variant), 23133d722a9Sopenharmony_ci Err(err) => cx.push(err), 23233d722a9Sopenharmony_ci } 23333d722a9Sopenharmony_ci } 23433d722a9Sopenharmony_ci 23533d722a9Sopenharmony_ci let enum_token = item.enum_token; 23633d722a9Sopenharmony_ci let visibility = visibility_pub(&item.vis, enum_token.span); 23733d722a9Sopenharmony_ci let brace_token = item.brace_token; 23833d722a9Sopenharmony_ci 23933d722a9Sopenharmony_ci let explicit_repr = repr.is_some(); 24033d722a9Sopenharmony_ci let mut repr = U8; 24133d722a9Sopenharmony_ci match discriminants.inferred_repr() { 24233d722a9Sopenharmony_ci Ok(inferred) => repr = inferred, 24333d722a9Sopenharmony_ci Err(err) => { 24433d722a9Sopenharmony_ci let span = quote_spanned!(brace_token.span=> #enum_token {}); 24533d722a9Sopenharmony_ci cx.error(span, err); 24633d722a9Sopenharmony_ci variants.clear(); 24733d722a9Sopenharmony_ci } 24833d722a9Sopenharmony_ci } 24933d722a9Sopenharmony_ci 25033d722a9Sopenharmony_ci let name = pair(namespace, &item.ident, cxx_name, rust_name); 25133d722a9Sopenharmony_ci let repr_ident = Ident::new(repr.as_ref(), Span::call_site()); 25233d722a9Sopenharmony_ci let repr_type = Type::Ident(NamedType::new(repr_ident)); 25333d722a9Sopenharmony_ci let repr = EnumRepr::Native { 25433d722a9Sopenharmony_ci atom: repr, 25533d722a9Sopenharmony_ci repr_type, 25633d722a9Sopenharmony_ci }; 25733d722a9Sopenharmony_ci let generics = Lifetimes { 25833d722a9Sopenharmony_ci lt_token: None, 25933d722a9Sopenharmony_ci lifetimes: Punctuated::new(), 26033d722a9Sopenharmony_ci gt_token: None, 26133d722a9Sopenharmony_ci }; 26233d722a9Sopenharmony_ci let variants_from_header_attr = variants_from_header; 26333d722a9Sopenharmony_ci let variants_from_header = variants_from_header_attr.is_some(); 26433d722a9Sopenharmony_ci 26533d722a9Sopenharmony_ci Api::Enum(Enum { 26633d722a9Sopenharmony_ci cfg, 26733d722a9Sopenharmony_ci doc, 26833d722a9Sopenharmony_ci derives, 26933d722a9Sopenharmony_ci attrs, 27033d722a9Sopenharmony_ci visibility, 27133d722a9Sopenharmony_ci enum_token, 27233d722a9Sopenharmony_ci name, 27333d722a9Sopenharmony_ci generics, 27433d722a9Sopenharmony_ci brace_token, 27533d722a9Sopenharmony_ci variants, 27633d722a9Sopenharmony_ci variants_from_header, 27733d722a9Sopenharmony_ci variants_from_header_attr, 27833d722a9Sopenharmony_ci repr, 27933d722a9Sopenharmony_ci explicit_repr, 28033d722a9Sopenharmony_ci }) 28133d722a9Sopenharmony_ci} 28233d722a9Sopenharmony_ci 28333d722a9Sopenharmony_cifn parse_variant( 28433d722a9Sopenharmony_ci cx: &mut Errors, 28533d722a9Sopenharmony_ci mut variant: RustVariant, 28633d722a9Sopenharmony_ci discriminants: &mut DiscriminantSet, 28733d722a9Sopenharmony_ci) -> Result<Variant> { 28833d722a9Sopenharmony_ci let mut cfg = CfgExpr::Unconditional; 28933d722a9Sopenharmony_ci let mut doc = Doc::new(); 29033d722a9Sopenharmony_ci let mut cxx_name = None; 29133d722a9Sopenharmony_ci let mut rust_name = None; 29233d722a9Sopenharmony_ci let attrs = attrs::parse( 29333d722a9Sopenharmony_ci cx, 29433d722a9Sopenharmony_ci mem::take(&mut variant.attrs), 29533d722a9Sopenharmony_ci attrs::Parser { 29633d722a9Sopenharmony_ci cfg: Some(&mut cfg), 29733d722a9Sopenharmony_ci doc: Some(&mut doc), 29833d722a9Sopenharmony_ci cxx_name: Some(&mut cxx_name), 29933d722a9Sopenharmony_ci rust_name: Some(&mut rust_name), 30033d722a9Sopenharmony_ci ..Default::default() 30133d722a9Sopenharmony_ci }, 30233d722a9Sopenharmony_ci ); 30333d722a9Sopenharmony_ci 30433d722a9Sopenharmony_ci match variant.fields { 30533d722a9Sopenharmony_ci Fields::Unit => {} 30633d722a9Sopenharmony_ci _ => { 30733d722a9Sopenharmony_ci let msg = "enums with data are not supported yet"; 30833d722a9Sopenharmony_ci return Err(Error::new_spanned(variant, msg)); 30933d722a9Sopenharmony_ci } 31033d722a9Sopenharmony_ci } 31133d722a9Sopenharmony_ci 31233d722a9Sopenharmony_ci let expr = variant.discriminant.as_ref().map(|(_, expr)| expr); 31333d722a9Sopenharmony_ci let try_discriminant = match &expr { 31433d722a9Sopenharmony_ci Some(lit) => discriminants.insert(lit), 31533d722a9Sopenharmony_ci None => discriminants.insert_next(), 31633d722a9Sopenharmony_ci }; 31733d722a9Sopenharmony_ci let discriminant = match try_discriminant { 31833d722a9Sopenharmony_ci Ok(discriminant) => discriminant, 31933d722a9Sopenharmony_ci Err(err) => return Err(Error::new_spanned(variant, err)), 32033d722a9Sopenharmony_ci }; 32133d722a9Sopenharmony_ci 32233d722a9Sopenharmony_ci let name = pair(Namespace::ROOT, &variant.ident, cxx_name, rust_name); 32333d722a9Sopenharmony_ci let expr = variant.discriminant.map(|(_, expr)| expr); 32433d722a9Sopenharmony_ci 32533d722a9Sopenharmony_ci Ok(Variant { 32633d722a9Sopenharmony_ci cfg, 32733d722a9Sopenharmony_ci doc, 32833d722a9Sopenharmony_ci attrs, 32933d722a9Sopenharmony_ci name, 33033d722a9Sopenharmony_ci discriminant, 33133d722a9Sopenharmony_ci expr, 33233d722a9Sopenharmony_ci }) 33333d722a9Sopenharmony_ci} 33433d722a9Sopenharmony_ci 33533d722a9Sopenharmony_cifn parse_foreign_mod( 33633d722a9Sopenharmony_ci cx: &mut Errors, 33733d722a9Sopenharmony_ci foreign_mod: ItemForeignMod, 33833d722a9Sopenharmony_ci out: &mut Vec<Api>, 33933d722a9Sopenharmony_ci trusted: bool, 34033d722a9Sopenharmony_ci namespace: &Namespace, 34133d722a9Sopenharmony_ci) { 34233d722a9Sopenharmony_ci let lang = match parse_lang(&foreign_mod.abi) { 34333d722a9Sopenharmony_ci Ok(lang) => lang, 34433d722a9Sopenharmony_ci Err(err) => return cx.push(err), 34533d722a9Sopenharmony_ci }; 34633d722a9Sopenharmony_ci 34733d722a9Sopenharmony_ci match lang { 34833d722a9Sopenharmony_ci Lang::Rust => { 34933d722a9Sopenharmony_ci if foreign_mod.unsafety.is_some() { 35033d722a9Sopenharmony_ci let unsafety = foreign_mod.unsafety; 35133d722a9Sopenharmony_ci let abi = &foreign_mod.abi; 35233d722a9Sopenharmony_ci let span = quote!(#unsafety #abi); 35333d722a9Sopenharmony_ci cx.error(span, "extern \"Rust\" block does not need to be unsafe"); 35433d722a9Sopenharmony_ci } 35533d722a9Sopenharmony_ci } 35633d722a9Sopenharmony_ci Lang::Cxx => {} 35733d722a9Sopenharmony_ci } 35833d722a9Sopenharmony_ci 35933d722a9Sopenharmony_ci let trusted = trusted || foreign_mod.unsafety.is_some(); 36033d722a9Sopenharmony_ci 36133d722a9Sopenharmony_ci let mut cfg = CfgExpr::Unconditional; 36233d722a9Sopenharmony_ci let mut namespace = namespace.clone(); 36333d722a9Sopenharmony_ci let attrs = attrs::parse( 36433d722a9Sopenharmony_ci cx, 36533d722a9Sopenharmony_ci foreign_mod.attrs, 36633d722a9Sopenharmony_ci attrs::Parser { 36733d722a9Sopenharmony_ci cfg: Some(&mut cfg), 36833d722a9Sopenharmony_ci namespace: Some(&mut namespace), 36933d722a9Sopenharmony_ci ..Default::default() 37033d722a9Sopenharmony_ci }, 37133d722a9Sopenharmony_ci ); 37233d722a9Sopenharmony_ci 37333d722a9Sopenharmony_ci let mut items = Vec::new(); 37433d722a9Sopenharmony_ci for foreign in foreign_mod.items { 37533d722a9Sopenharmony_ci match foreign { 37633d722a9Sopenharmony_ci ForeignItem::Type(foreign) => { 37733d722a9Sopenharmony_ci let ety = parse_extern_type(cx, foreign, lang, trusted, &cfg, &namespace, &attrs); 37833d722a9Sopenharmony_ci items.push(ety); 37933d722a9Sopenharmony_ci } 38033d722a9Sopenharmony_ci ForeignItem::Fn(foreign) => { 38133d722a9Sopenharmony_ci match parse_extern_fn(cx, foreign, lang, trusted, &cfg, &namespace, &attrs) { 38233d722a9Sopenharmony_ci Ok(efn) => items.push(efn), 38333d722a9Sopenharmony_ci Err(err) => cx.push(err), 38433d722a9Sopenharmony_ci } 38533d722a9Sopenharmony_ci } 38633d722a9Sopenharmony_ci ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => { 38733d722a9Sopenharmony_ci match foreign.mac.parse_body_with(parse_include) { 38833d722a9Sopenharmony_ci Ok(mut include) => { 38933d722a9Sopenharmony_ci include.cfg = cfg.clone(); 39033d722a9Sopenharmony_ci items.push(Api::Include(include)); 39133d722a9Sopenharmony_ci } 39233d722a9Sopenharmony_ci Err(err) => cx.push(err), 39333d722a9Sopenharmony_ci } 39433d722a9Sopenharmony_ci } 39533d722a9Sopenharmony_ci ForeignItem::Verbatim(tokens) => { 39633d722a9Sopenharmony_ci match parse_extern_verbatim(cx, tokens, lang, trusted, &cfg, &namespace, &attrs) { 39733d722a9Sopenharmony_ci Ok(api) => items.push(api), 39833d722a9Sopenharmony_ci Err(err) => cx.push(err), 39933d722a9Sopenharmony_ci } 40033d722a9Sopenharmony_ci } 40133d722a9Sopenharmony_ci _ => cx.error(foreign, "unsupported foreign item"), 40233d722a9Sopenharmony_ci } 40333d722a9Sopenharmony_ci } 40433d722a9Sopenharmony_ci 40533d722a9Sopenharmony_ci if !trusted 40633d722a9Sopenharmony_ci && items.iter().any(|api| match api { 40733d722a9Sopenharmony_ci Api::CxxFunction(efn) => efn.unsafety.is_none(), 40833d722a9Sopenharmony_ci _ => false, 40933d722a9Sopenharmony_ci }) 41033d722a9Sopenharmony_ci { 41133d722a9Sopenharmony_ci cx.error( 41233d722a9Sopenharmony_ci foreign_mod.abi, 41333d722a9Sopenharmony_ci "block must be declared `unsafe extern \"C++\"` if it contains any safe-to-call C++ functions", 41433d722a9Sopenharmony_ci ); 41533d722a9Sopenharmony_ci } 41633d722a9Sopenharmony_ci 41733d722a9Sopenharmony_ci let mut types = items.iter().filter_map(|item| match item { 41833d722a9Sopenharmony_ci Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.name), 41933d722a9Sopenharmony_ci Api::TypeAlias(alias) => Some(&alias.name), 42033d722a9Sopenharmony_ci _ => None, 42133d722a9Sopenharmony_ci }); 42233d722a9Sopenharmony_ci if let (Some(single_type), None) = (types.next(), types.next()) { 42333d722a9Sopenharmony_ci let single_type = single_type.clone(); 42433d722a9Sopenharmony_ci for item in &mut items { 42533d722a9Sopenharmony_ci if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item { 42633d722a9Sopenharmony_ci if let Some(receiver) = &mut efn.receiver { 42733d722a9Sopenharmony_ci if receiver.ty.rust == "Self" { 42833d722a9Sopenharmony_ci receiver.ty.rust = single_type.rust.clone(); 42933d722a9Sopenharmony_ci } 43033d722a9Sopenharmony_ci } 43133d722a9Sopenharmony_ci } 43233d722a9Sopenharmony_ci } 43333d722a9Sopenharmony_ci } 43433d722a9Sopenharmony_ci 43533d722a9Sopenharmony_ci out.extend(items); 43633d722a9Sopenharmony_ci} 43733d722a9Sopenharmony_ci 43833d722a9Sopenharmony_cifn parse_lang(abi: &Abi) -> Result<Lang> { 43933d722a9Sopenharmony_ci let name = match &abi.name { 44033d722a9Sopenharmony_ci Some(name) => name, 44133d722a9Sopenharmony_ci None => { 44233d722a9Sopenharmony_ci return Err(Error::new_spanned( 44333d722a9Sopenharmony_ci abi, 44433d722a9Sopenharmony_ci "ABI name is required, extern \"C++\" or extern \"Rust\"", 44533d722a9Sopenharmony_ci )); 44633d722a9Sopenharmony_ci } 44733d722a9Sopenharmony_ci }; 44833d722a9Sopenharmony_ci 44933d722a9Sopenharmony_ci match name.value().as_str() { 45033d722a9Sopenharmony_ci "C++" => Ok(Lang::Cxx), 45133d722a9Sopenharmony_ci "Rust" => Ok(Lang::Rust), 45233d722a9Sopenharmony_ci _ => Err(Error::new_spanned( 45333d722a9Sopenharmony_ci abi, 45433d722a9Sopenharmony_ci "unrecognized ABI, requires either \"C++\" or \"Rust\"", 45533d722a9Sopenharmony_ci )), 45633d722a9Sopenharmony_ci } 45733d722a9Sopenharmony_ci} 45833d722a9Sopenharmony_ci 45933d722a9Sopenharmony_cifn parse_extern_type( 46033d722a9Sopenharmony_ci cx: &mut Errors, 46133d722a9Sopenharmony_ci foreign_type: ForeignItemType, 46233d722a9Sopenharmony_ci lang: Lang, 46333d722a9Sopenharmony_ci trusted: bool, 46433d722a9Sopenharmony_ci extern_block_cfg: &CfgExpr, 46533d722a9Sopenharmony_ci namespace: &Namespace, 46633d722a9Sopenharmony_ci attrs: &OtherAttrs, 46733d722a9Sopenharmony_ci) -> Api { 46833d722a9Sopenharmony_ci let mut cfg = extern_block_cfg.clone(); 46933d722a9Sopenharmony_ci let mut doc = Doc::new(); 47033d722a9Sopenharmony_ci let mut derives = Vec::new(); 47133d722a9Sopenharmony_ci let mut namespace = namespace.clone(); 47233d722a9Sopenharmony_ci let mut cxx_name = None; 47333d722a9Sopenharmony_ci let mut rust_name = None; 47433d722a9Sopenharmony_ci let mut attrs = attrs.clone(); 47533d722a9Sopenharmony_ci attrs.extend(attrs::parse( 47633d722a9Sopenharmony_ci cx, 47733d722a9Sopenharmony_ci foreign_type.attrs, 47833d722a9Sopenharmony_ci attrs::Parser { 47933d722a9Sopenharmony_ci cfg: Some(&mut cfg), 48033d722a9Sopenharmony_ci doc: Some(&mut doc), 48133d722a9Sopenharmony_ci derives: Some(&mut derives), 48233d722a9Sopenharmony_ci namespace: Some(&mut namespace), 48333d722a9Sopenharmony_ci cxx_name: Some(&mut cxx_name), 48433d722a9Sopenharmony_ci rust_name: Some(&mut rust_name), 48533d722a9Sopenharmony_ci ..Default::default() 48633d722a9Sopenharmony_ci }, 48733d722a9Sopenharmony_ci )); 48833d722a9Sopenharmony_ci 48933d722a9Sopenharmony_ci let type_token = foreign_type.type_token; 49033d722a9Sopenharmony_ci let visibility = visibility_pub(&foreign_type.vis, type_token.span); 49133d722a9Sopenharmony_ci let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name); 49233d722a9Sopenharmony_ci let generics = extern_type_lifetimes(cx, foreign_type.generics); 49333d722a9Sopenharmony_ci let colon_token = None; 49433d722a9Sopenharmony_ci let bounds = Vec::new(); 49533d722a9Sopenharmony_ci let semi_token = foreign_type.semi_token; 49633d722a9Sopenharmony_ci 49733d722a9Sopenharmony_ci (match lang { 49833d722a9Sopenharmony_ci Lang::Cxx => Api::CxxType, 49933d722a9Sopenharmony_ci Lang::Rust => Api::RustType, 50033d722a9Sopenharmony_ci })(ExternType { 50133d722a9Sopenharmony_ci cfg, 50233d722a9Sopenharmony_ci lang, 50333d722a9Sopenharmony_ci doc, 50433d722a9Sopenharmony_ci derives, 50533d722a9Sopenharmony_ci attrs, 50633d722a9Sopenharmony_ci visibility, 50733d722a9Sopenharmony_ci type_token, 50833d722a9Sopenharmony_ci name, 50933d722a9Sopenharmony_ci generics, 51033d722a9Sopenharmony_ci colon_token, 51133d722a9Sopenharmony_ci bounds, 51233d722a9Sopenharmony_ci semi_token, 51333d722a9Sopenharmony_ci trusted, 51433d722a9Sopenharmony_ci }) 51533d722a9Sopenharmony_ci} 51633d722a9Sopenharmony_ci 51733d722a9Sopenharmony_cifn parse_extern_fn( 51833d722a9Sopenharmony_ci cx: &mut Errors, 51933d722a9Sopenharmony_ci mut foreign_fn: ForeignItemFn, 52033d722a9Sopenharmony_ci lang: Lang, 52133d722a9Sopenharmony_ci trusted: bool, 52233d722a9Sopenharmony_ci extern_block_cfg: &CfgExpr, 52333d722a9Sopenharmony_ci namespace: &Namespace, 52433d722a9Sopenharmony_ci attrs: &OtherAttrs, 52533d722a9Sopenharmony_ci) -> Result<Api> { 52633d722a9Sopenharmony_ci let mut cfg = extern_block_cfg.clone(); 52733d722a9Sopenharmony_ci let mut doc = Doc::new(); 52833d722a9Sopenharmony_ci let mut namespace = namespace.clone(); 52933d722a9Sopenharmony_ci let mut cxx_name = None; 53033d722a9Sopenharmony_ci let mut rust_name = None; 53133d722a9Sopenharmony_ci let mut attrs = attrs.clone(); 53233d722a9Sopenharmony_ci attrs.extend(attrs::parse( 53333d722a9Sopenharmony_ci cx, 53433d722a9Sopenharmony_ci mem::take(&mut foreign_fn.attrs), 53533d722a9Sopenharmony_ci attrs::Parser { 53633d722a9Sopenharmony_ci cfg: Some(&mut cfg), 53733d722a9Sopenharmony_ci doc: Some(&mut doc), 53833d722a9Sopenharmony_ci namespace: Some(&mut namespace), 53933d722a9Sopenharmony_ci cxx_name: Some(&mut cxx_name), 54033d722a9Sopenharmony_ci rust_name: Some(&mut rust_name), 54133d722a9Sopenharmony_ci ..Default::default() 54233d722a9Sopenharmony_ci }, 54333d722a9Sopenharmony_ci )); 54433d722a9Sopenharmony_ci 54533d722a9Sopenharmony_ci let generics = &foreign_fn.sig.generics; 54633d722a9Sopenharmony_ci if generics.where_clause.is_some() 54733d722a9Sopenharmony_ci || generics.params.iter().any(|param| match param { 54833d722a9Sopenharmony_ci GenericParam::Lifetime(lifetime) => !lifetime.bounds.is_empty(), 54933d722a9Sopenharmony_ci GenericParam::Type(_) | GenericParam::Const(_) => true, 55033d722a9Sopenharmony_ci }) 55133d722a9Sopenharmony_ci { 55233d722a9Sopenharmony_ci return Err(Error::new_spanned( 55333d722a9Sopenharmony_ci foreign_fn, 55433d722a9Sopenharmony_ci "extern function with generic parameters is not supported yet", 55533d722a9Sopenharmony_ci )); 55633d722a9Sopenharmony_ci } 55733d722a9Sopenharmony_ci 55833d722a9Sopenharmony_ci if let Some(variadic) = &foreign_fn.sig.variadic { 55933d722a9Sopenharmony_ci return Err(Error::new_spanned( 56033d722a9Sopenharmony_ci variadic, 56133d722a9Sopenharmony_ci "variadic function is not supported yet", 56233d722a9Sopenharmony_ci )); 56333d722a9Sopenharmony_ci } 56433d722a9Sopenharmony_ci 56533d722a9Sopenharmony_ci if foreign_fn.sig.asyncness.is_some() && !cfg!(feature = "experimental-async-fn") { 56633d722a9Sopenharmony_ci return Err(Error::new_spanned( 56733d722a9Sopenharmony_ci foreign_fn, 56833d722a9Sopenharmony_ci "async function is not directly supported yet, but see https://cxx.rs/async.html \ 56933d722a9Sopenharmony_ci for a working approach, and https://github.com/pcwalton/cxx-async for some helpers; \ 57033d722a9Sopenharmony_ci eventually what you wrote will work but it isn't integrated into the cxx::bridge \ 57133d722a9Sopenharmony_ci macro yet", 57233d722a9Sopenharmony_ci )); 57333d722a9Sopenharmony_ci } 57433d722a9Sopenharmony_ci 57533d722a9Sopenharmony_ci if foreign_fn.sig.constness.is_some() { 57633d722a9Sopenharmony_ci return Err(Error::new_spanned( 57733d722a9Sopenharmony_ci foreign_fn, 57833d722a9Sopenharmony_ci "const extern function is not supported", 57933d722a9Sopenharmony_ci )); 58033d722a9Sopenharmony_ci } 58133d722a9Sopenharmony_ci 58233d722a9Sopenharmony_ci if let Some(abi) = &foreign_fn.sig.abi { 58333d722a9Sopenharmony_ci return Err(Error::new_spanned( 58433d722a9Sopenharmony_ci abi, 58533d722a9Sopenharmony_ci "explicit ABI on extern function is not supported", 58633d722a9Sopenharmony_ci )); 58733d722a9Sopenharmony_ci } 58833d722a9Sopenharmony_ci 58933d722a9Sopenharmony_ci let mut receiver = None; 59033d722a9Sopenharmony_ci let mut args = Punctuated::new(); 59133d722a9Sopenharmony_ci for arg in foreign_fn.sig.inputs.pairs() { 59233d722a9Sopenharmony_ci let (arg, comma) = arg.into_tuple(); 59333d722a9Sopenharmony_ci match arg { 59433d722a9Sopenharmony_ci FnArg::Receiver(arg) => { 59533d722a9Sopenharmony_ci if let Some((ampersand, lifetime)) = &arg.reference { 59633d722a9Sopenharmony_ci receiver = Some(Receiver { 59733d722a9Sopenharmony_ci pinned: false, 59833d722a9Sopenharmony_ci ampersand: *ampersand, 59933d722a9Sopenharmony_ci lifetime: lifetime.clone(), 60033d722a9Sopenharmony_ci mutable: arg.mutability.is_some(), 60133d722a9Sopenharmony_ci var: arg.self_token, 60233d722a9Sopenharmony_ci colon_token: Token, 60333d722a9Sopenharmony_ci ty: NamedType::new(Ident::new("Self", arg.self_token.span)), 60433d722a9Sopenharmony_ci shorthand: true, 60533d722a9Sopenharmony_ci pin_tokens: None, 60633d722a9Sopenharmony_ci mutability: arg.mutability, 60733d722a9Sopenharmony_ci }); 60833d722a9Sopenharmony_ci continue; 60933d722a9Sopenharmony_ci } 61033d722a9Sopenharmony_ci if let Some(colon_token) = arg.colon_token { 61133d722a9Sopenharmony_ci let ty = parse_type(&arg.ty)?; 61233d722a9Sopenharmony_ci if let Type::Ref(reference) = ty { 61333d722a9Sopenharmony_ci if let Type::Ident(ident) = reference.inner { 61433d722a9Sopenharmony_ci receiver = Some(Receiver { 61533d722a9Sopenharmony_ci pinned: reference.pinned, 61633d722a9Sopenharmony_ci ampersand: reference.ampersand, 61733d722a9Sopenharmony_ci lifetime: reference.lifetime, 61833d722a9Sopenharmony_ci mutable: reference.mutable, 61933d722a9Sopenharmony_ci var: Token), 62033d722a9Sopenharmony_ci colon_token, 62133d722a9Sopenharmony_ci ty: ident, 62233d722a9Sopenharmony_ci shorthand: false, 62333d722a9Sopenharmony_ci pin_tokens: reference.pin_tokens, 62433d722a9Sopenharmony_ci mutability: reference.mutability, 62533d722a9Sopenharmony_ci }); 62633d722a9Sopenharmony_ci continue; 62733d722a9Sopenharmony_ci } 62833d722a9Sopenharmony_ci } 62933d722a9Sopenharmony_ci } 63033d722a9Sopenharmony_ci return Err(Error::new_spanned(arg, "unsupported method receiver")); 63133d722a9Sopenharmony_ci } 63233d722a9Sopenharmony_ci FnArg::Typed(arg) => { 63333d722a9Sopenharmony_ci let ident = match arg.pat.as_ref() { 63433d722a9Sopenharmony_ci Pat::Ident(pat) => pat.ident.clone(), 63533d722a9Sopenharmony_ci Pat::Wild(pat) => { 63633d722a9Sopenharmony_ci Ident::new(&format!("arg{}", args.len()), pat.underscore_token.span) 63733d722a9Sopenharmony_ci } 63833d722a9Sopenharmony_ci _ => return Err(Error::new_spanned(arg, "unsupported signature")), 63933d722a9Sopenharmony_ci }; 64033d722a9Sopenharmony_ci let ty = parse_type(&arg.ty)?; 64133d722a9Sopenharmony_ci let cfg = CfgExpr::Unconditional; 64233d722a9Sopenharmony_ci let doc = Doc::new(); 64333d722a9Sopenharmony_ci let attrs = OtherAttrs::none(); 64433d722a9Sopenharmony_ci let visibility = Token); 64533d722a9Sopenharmony_ci let name = pair(Namespace::default(), &ident, None, None); 64633d722a9Sopenharmony_ci let colon_token = arg.colon_token; 64733d722a9Sopenharmony_ci args.push_value(Var { 64833d722a9Sopenharmony_ci cfg, 64933d722a9Sopenharmony_ci doc, 65033d722a9Sopenharmony_ci attrs, 65133d722a9Sopenharmony_ci visibility, 65233d722a9Sopenharmony_ci name, 65333d722a9Sopenharmony_ci colon_token, 65433d722a9Sopenharmony_ci ty, 65533d722a9Sopenharmony_ci }); 65633d722a9Sopenharmony_ci if let Some(comma) = comma { 65733d722a9Sopenharmony_ci args.push_punct(*comma); 65833d722a9Sopenharmony_ci } 65933d722a9Sopenharmony_ci } 66033d722a9Sopenharmony_ci } 66133d722a9Sopenharmony_ci } 66233d722a9Sopenharmony_ci 66333d722a9Sopenharmony_ci let mut throws_tokens = None; 66433d722a9Sopenharmony_ci let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?; 66533d722a9Sopenharmony_ci let throws = throws_tokens.is_some(); 66633d722a9Sopenharmony_ci let asyncness = foreign_fn.sig.asyncness; 66733d722a9Sopenharmony_ci let unsafety = foreign_fn.sig.unsafety; 66833d722a9Sopenharmony_ci let fn_token = foreign_fn.sig.fn_token; 66933d722a9Sopenharmony_ci let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span); 67033d722a9Sopenharmony_ci let visibility = visibility_pub(&foreign_fn.vis, inherited_span); 67133d722a9Sopenharmony_ci let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name); 67233d722a9Sopenharmony_ci let generics = generics.clone(); 67333d722a9Sopenharmony_ci let paren_token = foreign_fn.sig.paren_token; 67433d722a9Sopenharmony_ci let semi_token = foreign_fn.semi_token; 67533d722a9Sopenharmony_ci 67633d722a9Sopenharmony_ci Ok(match lang { 67733d722a9Sopenharmony_ci Lang::Cxx => Api::CxxFunction, 67833d722a9Sopenharmony_ci Lang::Rust => Api::RustFunction, 67933d722a9Sopenharmony_ci }(ExternFn { 68033d722a9Sopenharmony_ci cfg, 68133d722a9Sopenharmony_ci lang, 68233d722a9Sopenharmony_ci doc, 68333d722a9Sopenharmony_ci attrs, 68433d722a9Sopenharmony_ci visibility, 68533d722a9Sopenharmony_ci name, 68633d722a9Sopenharmony_ci sig: Signature { 68733d722a9Sopenharmony_ci asyncness, 68833d722a9Sopenharmony_ci unsafety, 68933d722a9Sopenharmony_ci fn_token, 69033d722a9Sopenharmony_ci generics, 69133d722a9Sopenharmony_ci receiver, 69233d722a9Sopenharmony_ci args, 69333d722a9Sopenharmony_ci ret, 69433d722a9Sopenharmony_ci throws, 69533d722a9Sopenharmony_ci paren_token, 69633d722a9Sopenharmony_ci throws_tokens, 69733d722a9Sopenharmony_ci }, 69833d722a9Sopenharmony_ci semi_token, 69933d722a9Sopenharmony_ci trusted, 70033d722a9Sopenharmony_ci })) 70133d722a9Sopenharmony_ci} 70233d722a9Sopenharmony_ci 70333d722a9Sopenharmony_cifn parse_extern_verbatim( 70433d722a9Sopenharmony_ci cx: &mut Errors, 70533d722a9Sopenharmony_ci tokens: TokenStream, 70633d722a9Sopenharmony_ci lang: Lang, 70733d722a9Sopenharmony_ci trusted: bool, 70833d722a9Sopenharmony_ci extern_block_cfg: &CfgExpr, 70933d722a9Sopenharmony_ci namespace: &Namespace, 71033d722a9Sopenharmony_ci attrs: &OtherAttrs, 71133d722a9Sopenharmony_ci) -> Result<Api> { 71233d722a9Sopenharmony_ci |input: ParseStream| -> Result<Api> { 71333d722a9Sopenharmony_ci let unparsed_attrs = input.call(Attribute::parse_outer)?; 71433d722a9Sopenharmony_ci let visibility: Visibility = input.parse()?; 71533d722a9Sopenharmony_ci if input.peek(Token![type]) { 71633d722a9Sopenharmony_ci parse_extern_verbatim_type( 71733d722a9Sopenharmony_ci cx, 71833d722a9Sopenharmony_ci unparsed_attrs, 71933d722a9Sopenharmony_ci visibility, 72033d722a9Sopenharmony_ci input, 72133d722a9Sopenharmony_ci lang, 72233d722a9Sopenharmony_ci trusted, 72333d722a9Sopenharmony_ci extern_block_cfg, 72433d722a9Sopenharmony_ci namespace, 72533d722a9Sopenharmony_ci attrs, 72633d722a9Sopenharmony_ci ) 72733d722a9Sopenharmony_ci } else if input.peek(Token![fn]) { 72833d722a9Sopenharmony_ci parse_extern_verbatim_fn(input) 72933d722a9Sopenharmony_ci } else { 73033d722a9Sopenharmony_ci let span = input.cursor().token_stream(); 73133d722a9Sopenharmony_ci Err(Error::new_spanned( 73233d722a9Sopenharmony_ci span, 73333d722a9Sopenharmony_ci "unsupported foreign item, expected `type` or `fn`", 73433d722a9Sopenharmony_ci )) 73533d722a9Sopenharmony_ci } 73633d722a9Sopenharmony_ci } 73733d722a9Sopenharmony_ci .parse2(tokens) 73833d722a9Sopenharmony_ci} 73933d722a9Sopenharmony_ci 74033d722a9Sopenharmony_cifn parse_extern_verbatim_type( 74133d722a9Sopenharmony_ci cx: &mut Errors, 74233d722a9Sopenharmony_ci unparsed_attrs: Vec<Attribute>, 74333d722a9Sopenharmony_ci visibility: Visibility, 74433d722a9Sopenharmony_ci input: ParseStream, 74533d722a9Sopenharmony_ci lang: Lang, 74633d722a9Sopenharmony_ci trusted: bool, 74733d722a9Sopenharmony_ci extern_block_cfg: &CfgExpr, 74833d722a9Sopenharmony_ci namespace: &Namespace, 74933d722a9Sopenharmony_ci attrs: &OtherAttrs, 75033d722a9Sopenharmony_ci) -> Result<Api> { 75133d722a9Sopenharmony_ci let type_token: Token![type] = input.parse()?; 75233d722a9Sopenharmony_ci let ident: Ident = input.parse()?; 75333d722a9Sopenharmony_ci let generics: Generics = input.parse()?; 75433d722a9Sopenharmony_ci let lifetimes = extern_type_lifetimes(cx, generics); 75533d722a9Sopenharmony_ci let lookahead = input.lookahead1(); 75633d722a9Sopenharmony_ci if lookahead.peek(Token![=]) { 75733d722a9Sopenharmony_ci // type Alias = crate::path::to::Type; 75833d722a9Sopenharmony_ci parse_type_alias( 75933d722a9Sopenharmony_ci cx, 76033d722a9Sopenharmony_ci unparsed_attrs, 76133d722a9Sopenharmony_ci visibility, 76233d722a9Sopenharmony_ci type_token, 76333d722a9Sopenharmony_ci ident, 76433d722a9Sopenharmony_ci lifetimes, 76533d722a9Sopenharmony_ci input, 76633d722a9Sopenharmony_ci lang, 76733d722a9Sopenharmony_ci extern_block_cfg, 76833d722a9Sopenharmony_ci namespace, 76933d722a9Sopenharmony_ci attrs, 77033d722a9Sopenharmony_ci ) 77133d722a9Sopenharmony_ci } else if lookahead.peek(Token![:]) { 77233d722a9Sopenharmony_ci // type Opaque: Bound2 + Bound2; 77333d722a9Sopenharmony_ci parse_extern_type_bounded( 77433d722a9Sopenharmony_ci cx, 77533d722a9Sopenharmony_ci unparsed_attrs, 77633d722a9Sopenharmony_ci visibility, 77733d722a9Sopenharmony_ci type_token, 77833d722a9Sopenharmony_ci ident, 77933d722a9Sopenharmony_ci lifetimes, 78033d722a9Sopenharmony_ci input, 78133d722a9Sopenharmony_ci lang, 78233d722a9Sopenharmony_ci trusted, 78333d722a9Sopenharmony_ci extern_block_cfg, 78433d722a9Sopenharmony_ci namespace, 78533d722a9Sopenharmony_ci attrs, 78633d722a9Sopenharmony_ci ) 78733d722a9Sopenharmony_ci } else { 78833d722a9Sopenharmony_ci Err(lookahead.error()) 78933d722a9Sopenharmony_ci } 79033d722a9Sopenharmony_ci} 79133d722a9Sopenharmony_ci 79233d722a9Sopenharmony_cifn extern_type_lifetimes(cx: &mut Errors, generics: Generics) -> Lifetimes { 79333d722a9Sopenharmony_ci let mut lifetimes = Punctuated::new(); 79433d722a9Sopenharmony_ci let mut has_unsupported_generic_param = false; 79533d722a9Sopenharmony_ci for pair in generics.params.into_pairs() { 79633d722a9Sopenharmony_ci let (param, punct) = pair.into_tuple(); 79733d722a9Sopenharmony_ci match param { 79833d722a9Sopenharmony_ci GenericParam::Lifetime(param) => { 79933d722a9Sopenharmony_ci if !param.bounds.is_empty() && !has_unsupported_generic_param { 80033d722a9Sopenharmony_ci let msg = "lifetime parameter with bounds is not supported yet"; 80133d722a9Sopenharmony_ci cx.error(¶m, msg); 80233d722a9Sopenharmony_ci has_unsupported_generic_param = true; 80333d722a9Sopenharmony_ci } 80433d722a9Sopenharmony_ci lifetimes.push_value(param.lifetime); 80533d722a9Sopenharmony_ci if let Some(punct) = punct { 80633d722a9Sopenharmony_ci lifetimes.push_punct(punct); 80733d722a9Sopenharmony_ci } 80833d722a9Sopenharmony_ci } 80933d722a9Sopenharmony_ci GenericParam::Type(param) => { 81033d722a9Sopenharmony_ci if !has_unsupported_generic_param { 81133d722a9Sopenharmony_ci let msg = "extern type with generic type parameter is not supported yet"; 81233d722a9Sopenharmony_ci cx.error(¶m, msg); 81333d722a9Sopenharmony_ci has_unsupported_generic_param = true; 81433d722a9Sopenharmony_ci } 81533d722a9Sopenharmony_ci } 81633d722a9Sopenharmony_ci GenericParam::Const(param) => { 81733d722a9Sopenharmony_ci if !has_unsupported_generic_param { 81833d722a9Sopenharmony_ci let msg = "extern type with const generic parameter is not supported yet"; 81933d722a9Sopenharmony_ci cx.error(¶m, msg); 82033d722a9Sopenharmony_ci has_unsupported_generic_param = true; 82133d722a9Sopenharmony_ci } 82233d722a9Sopenharmony_ci } 82333d722a9Sopenharmony_ci } 82433d722a9Sopenharmony_ci } 82533d722a9Sopenharmony_ci Lifetimes { 82633d722a9Sopenharmony_ci lt_token: generics.lt_token, 82733d722a9Sopenharmony_ci lifetimes, 82833d722a9Sopenharmony_ci gt_token: generics.gt_token, 82933d722a9Sopenharmony_ci } 83033d722a9Sopenharmony_ci} 83133d722a9Sopenharmony_ci 83233d722a9Sopenharmony_cifn parse_extern_verbatim_fn(input: ParseStream) -> Result<Api> { 83333d722a9Sopenharmony_ci input.parse::<RustSignature>()?; 83433d722a9Sopenharmony_ci input.parse::<Token![;]>()?; 83533d722a9Sopenharmony_ci unreachable!() 83633d722a9Sopenharmony_ci} 83733d722a9Sopenharmony_ci 83833d722a9Sopenharmony_cifn parse_type_alias( 83933d722a9Sopenharmony_ci cx: &mut Errors, 84033d722a9Sopenharmony_ci unparsed_attrs: Vec<Attribute>, 84133d722a9Sopenharmony_ci visibility: Visibility, 84233d722a9Sopenharmony_ci type_token: Token![type], 84333d722a9Sopenharmony_ci ident: Ident, 84433d722a9Sopenharmony_ci generics: Lifetimes, 84533d722a9Sopenharmony_ci input: ParseStream, 84633d722a9Sopenharmony_ci lang: Lang, 84733d722a9Sopenharmony_ci extern_block_cfg: &CfgExpr, 84833d722a9Sopenharmony_ci namespace: &Namespace, 84933d722a9Sopenharmony_ci attrs: &OtherAttrs, 85033d722a9Sopenharmony_ci) -> Result<Api> { 85133d722a9Sopenharmony_ci let eq_token: Token![=] = input.parse()?; 85233d722a9Sopenharmony_ci let ty: RustType = input.parse()?; 85333d722a9Sopenharmony_ci let semi_token: Token![;] = input.parse()?; 85433d722a9Sopenharmony_ci 85533d722a9Sopenharmony_ci let mut cfg = extern_block_cfg.clone(); 85633d722a9Sopenharmony_ci let mut doc = Doc::new(); 85733d722a9Sopenharmony_ci let mut derives = Vec::new(); 85833d722a9Sopenharmony_ci let mut namespace = namespace.clone(); 85933d722a9Sopenharmony_ci let mut cxx_name = None; 86033d722a9Sopenharmony_ci let mut rust_name = None; 86133d722a9Sopenharmony_ci let mut attrs = attrs.clone(); 86233d722a9Sopenharmony_ci attrs.extend(attrs::parse( 86333d722a9Sopenharmony_ci cx, 86433d722a9Sopenharmony_ci unparsed_attrs, 86533d722a9Sopenharmony_ci attrs::Parser { 86633d722a9Sopenharmony_ci cfg: Some(&mut cfg), 86733d722a9Sopenharmony_ci doc: Some(&mut doc), 86833d722a9Sopenharmony_ci derives: Some(&mut derives), 86933d722a9Sopenharmony_ci namespace: Some(&mut namespace), 87033d722a9Sopenharmony_ci cxx_name: Some(&mut cxx_name), 87133d722a9Sopenharmony_ci rust_name: Some(&mut rust_name), 87233d722a9Sopenharmony_ci ..Default::default() 87333d722a9Sopenharmony_ci }, 87433d722a9Sopenharmony_ci )); 87533d722a9Sopenharmony_ci 87633d722a9Sopenharmony_ci if lang == Lang::Rust { 87733d722a9Sopenharmony_ci let span = quote!(#type_token #semi_token); 87833d722a9Sopenharmony_ci let msg = "type alias in extern \"Rust\" block is not supported"; 87933d722a9Sopenharmony_ci return Err(Error::new_spanned(span, msg)); 88033d722a9Sopenharmony_ci } 88133d722a9Sopenharmony_ci 88233d722a9Sopenharmony_ci let visibility = visibility_pub(&visibility, type_token.span); 88333d722a9Sopenharmony_ci let name = pair(namespace, &ident, cxx_name, rust_name); 88433d722a9Sopenharmony_ci 88533d722a9Sopenharmony_ci Ok(Api::TypeAlias(TypeAlias { 88633d722a9Sopenharmony_ci cfg, 88733d722a9Sopenharmony_ci doc, 88833d722a9Sopenharmony_ci derives, 88933d722a9Sopenharmony_ci attrs, 89033d722a9Sopenharmony_ci visibility, 89133d722a9Sopenharmony_ci type_token, 89233d722a9Sopenharmony_ci name, 89333d722a9Sopenharmony_ci generics, 89433d722a9Sopenharmony_ci eq_token, 89533d722a9Sopenharmony_ci ty, 89633d722a9Sopenharmony_ci semi_token, 89733d722a9Sopenharmony_ci })) 89833d722a9Sopenharmony_ci} 89933d722a9Sopenharmony_ci 90033d722a9Sopenharmony_cifn parse_extern_type_bounded( 90133d722a9Sopenharmony_ci cx: &mut Errors, 90233d722a9Sopenharmony_ci unparsed_attrs: Vec<Attribute>, 90333d722a9Sopenharmony_ci visibility: Visibility, 90433d722a9Sopenharmony_ci type_token: Token![type], 90533d722a9Sopenharmony_ci ident: Ident, 90633d722a9Sopenharmony_ci generics: Lifetimes, 90733d722a9Sopenharmony_ci input: ParseStream, 90833d722a9Sopenharmony_ci lang: Lang, 90933d722a9Sopenharmony_ci trusted: bool, 91033d722a9Sopenharmony_ci extern_block_cfg: &CfgExpr, 91133d722a9Sopenharmony_ci namespace: &Namespace, 91233d722a9Sopenharmony_ci attrs: &OtherAttrs, 91333d722a9Sopenharmony_ci) -> Result<Api> { 91433d722a9Sopenharmony_ci let mut bounds = Vec::new(); 91533d722a9Sopenharmony_ci let colon_token: Option<Token![:]> = input.parse()?; 91633d722a9Sopenharmony_ci if colon_token.is_some() { 91733d722a9Sopenharmony_ci loop { 91833d722a9Sopenharmony_ci match input.parse()? { 91933d722a9Sopenharmony_ci TypeParamBound::Trait(TraitBound { 92033d722a9Sopenharmony_ci paren_token: None, 92133d722a9Sopenharmony_ci modifier: TraitBoundModifier::None, 92233d722a9Sopenharmony_ci lifetimes: None, 92333d722a9Sopenharmony_ci path, 92433d722a9Sopenharmony_ci }) if if let Some(derive) = path.get_ident().and_then(Derive::from) { 92533d722a9Sopenharmony_ci bounds.push(derive); 92633d722a9Sopenharmony_ci true 92733d722a9Sopenharmony_ci } else { 92833d722a9Sopenharmony_ci false 92933d722a9Sopenharmony_ci } => {} 93033d722a9Sopenharmony_ci bound => cx.error(bound, "unsupported trait"), 93133d722a9Sopenharmony_ci } 93233d722a9Sopenharmony_ci 93333d722a9Sopenharmony_ci let lookahead = input.lookahead1(); 93433d722a9Sopenharmony_ci if lookahead.peek(Token![+]) { 93533d722a9Sopenharmony_ci input.parse::<Token![+]>()?; 93633d722a9Sopenharmony_ci } else if lookahead.peek(Token![;]) { 93733d722a9Sopenharmony_ci break; 93833d722a9Sopenharmony_ci } else { 93933d722a9Sopenharmony_ci return Err(lookahead.error()); 94033d722a9Sopenharmony_ci } 94133d722a9Sopenharmony_ci } 94233d722a9Sopenharmony_ci } 94333d722a9Sopenharmony_ci let semi_token: Token![;] = input.parse()?; 94433d722a9Sopenharmony_ci 94533d722a9Sopenharmony_ci let mut cfg = extern_block_cfg.clone(); 94633d722a9Sopenharmony_ci let mut doc = Doc::new(); 94733d722a9Sopenharmony_ci let mut derives = Vec::new(); 94833d722a9Sopenharmony_ci let mut namespace = namespace.clone(); 94933d722a9Sopenharmony_ci let mut cxx_name = None; 95033d722a9Sopenharmony_ci let mut rust_name = None; 95133d722a9Sopenharmony_ci let mut attrs = attrs.clone(); 95233d722a9Sopenharmony_ci attrs.extend(attrs::parse( 95333d722a9Sopenharmony_ci cx, 95433d722a9Sopenharmony_ci unparsed_attrs, 95533d722a9Sopenharmony_ci attrs::Parser { 95633d722a9Sopenharmony_ci cfg: Some(&mut cfg), 95733d722a9Sopenharmony_ci doc: Some(&mut doc), 95833d722a9Sopenharmony_ci derives: Some(&mut derives), 95933d722a9Sopenharmony_ci namespace: Some(&mut namespace), 96033d722a9Sopenharmony_ci cxx_name: Some(&mut cxx_name), 96133d722a9Sopenharmony_ci rust_name: Some(&mut rust_name), 96233d722a9Sopenharmony_ci ..Default::default() 96333d722a9Sopenharmony_ci }, 96433d722a9Sopenharmony_ci )); 96533d722a9Sopenharmony_ci 96633d722a9Sopenharmony_ci let visibility = visibility_pub(&visibility, type_token.span); 96733d722a9Sopenharmony_ci let name = pair(namespace, &ident, cxx_name, rust_name); 96833d722a9Sopenharmony_ci 96933d722a9Sopenharmony_ci Ok(match lang { 97033d722a9Sopenharmony_ci Lang::Cxx => Api::CxxType, 97133d722a9Sopenharmony_ci Lang::Rust => Api::RustType, 97233d722a9Sopenharmony_ci }(ExternType { 97333d722a9Sopenharmony_ci cfg, 97433d722a9Sopenharmony_ci lang, 97533d722a9Sopenharmony_ci doc, 97633d722a9Sopenharmony_ci derives, 97733d722a9Sopenharmony_ci attrs, 97833d722a9Sopenharmony_ci visibility, 97933d722a9Sopenharmony_ci type_token, 98033d722a9Sopenharmony_ci name, 98133d722a9Sopenharmony_ci generics, 98233d722a9Sopenharmony_ci colon_token, 98333d722a9Sopenharmony_ci bounds, 98433d722a9Sopenharmony_ci semi_token, 98533d722a9Sopenharmony_ci trusted, 98633d722a9Sopenharmony_ci })) 98733d722a9Sopenharmony_ci} 98833d722a9Sopenharmony_ci 98933d722a9Sopenharmony_cifn parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result<Api> { 99033d722a9Sopenharmony_ci let impl_token = imp.impl_token; 99133d722a9Sopenharmony_ci 99233d722a9Sopenharmony_ci let mut cfg = CfgExpr::Unconditional; 99333d722a9Sopenharmony_ci attrs::parse( 99433d722a9Sopenharmony_ci cx, 99533d722a9Sopenharmony_ci imp.attrs, 99633d722a9Sopenharmony_ci attrs::Parser { 99733d722a9Sopenharmony_ci cfg: Some(&mut cfg), 99833d722a9Sopenharmony_ci ..Default::default() 99933d722a9Sopenharmony_ci }, 100033d722a9Sopenharmony_ci ); 100133d722a9Sopenharmony_ci 100233d722a9Sopenharmony_ci if !imp.items.is_empty() { 100333d722a9Sopenharmony_ci let mut span = Group::new(Delimiter::Brace, TokenStream::new()); 100433d722a9Sopenharmony_ci span.set_span(imp.brace_token.span.join()); 100533d722a9Sopenharmony_ci return Err(Error::new_spanned(span, "expected an empty impl block")); 100633d722a9Sopenharmony_ci } 100733d722a9Sopenharmony_ci 100833d722a9Sopenharmony_ci if let Some((bang, path, for_token)) = &imp.trait_ { 100933d722a9Sopenharmony_ci let self_ty = &imp.self_ty; 101033d722a9Sopenharmony_ci let span = quote!(#bang #path #for_token #self_ty); 101133d722a9Sopenharmony_ci return Err(Error::new_spanned( 101233d722a9Sopenharmony_ci span, 101333d722a9Sopenharmony_ci "unexpected impl, expected something like `impl UniquePtr<T> {}`", 101433d722a9Sopenharmony_ci )); 101533d722a9Sopenharmony_ci } 101633d722a9Sopenharmony_ci 101733d722a9Sopenharmony_ci if let Some(where_clause) = imp.generics.where_clause { 101833d722a9Sopenharmony_ci return Err(Error::new_spanned( 101933d722a9Sopenharmony_ci where_clause, 102033d722a9Sopenharmony_ci "where-clause on an impl is not supported yet", 102133d722a9Sopenharmony_ci )); 102233d722a9Sopenharmony_ci } 102333d722a9Sopenharmony_ci let mut impl_generics = Lifetimes { 102433d722a9Sopenharmony_ci lt_token: imp.generics.lt_token, 102533d722a9Sopenharmony_ci lifetimes: Punctuated::new(), 102633d722a9Sopenharmony_ci gt_token: imp.generics.gt_token, 102733d722a9Sopenharmony_ci }; 102833d722a9Sopenharmony_ci for pair in imp.generics.params.into_pairs() { 102933d722a9Sopenharmony_ci let (param, punct) = pair.into_tuple(); 103033d722a9Sopenharmony_ci match param { 103133d722a9Sopenharmony_ci GenericParam::Lifetime(def) if def.bounds.is_empty() => { 103233d722a9Sopenharmony_ci impl_generics.lifetimes.push_value(def.lifetime); 103333d722a9Sopenharmony_ci if let Some(punct) = punct { 103433d722a9Sopenharmony_ci impl_generics.lifetimes.push_punct(punct); 103533d722a9Sopenharmony_ci } 103633d722a9Sopenharmony_ci } 103733d722a9Sopenharmony_ci _ => { 103833d722a9Sopenharmony_ci let span = quote!(#impl_token #impl_generics); 103933d722a9Sopenharmony_ci return Err(Error::new_spanned( 104033d722a9Sopenharmony_ci span, 104133d722a9Sopenharmony_ci "generic parameter on an impl is not supported yet", 104233d722a9Sopenharmony_ci )); 104333d722a9Sopenharmony_ci } 104433d722a9Sopenharmony_ci } 104533d722a9Sopenharmony_ci } 104633d722a9Sopenharmony_ci 104733d722a9Sopenharmony_ci let mut negative_token = None; 104833d722a9Sopenharmony_ci let mut self_ty = *imp.self_ty; 104933d722a9Sopenharmony_ci if let RustType::Verbatim(ty) = &self_ty { 105033d722a9Sopenharmony_ci let mut iter = ty.clone().into_iter(); 105133d722a9Sopenharmony_ci if let Some(TokenTree::Punct(punct)) = iter.next() { 105233d722a9Sopenharmony_ci if punct.as_char() == '!' { 105333d722a9Sopenharmony_ci let ty = iter.collect::<TokenStream>(); 105433d722a9Sopenharmony_ci if !ty.is_empty() { 105533d722a9Sopenharmony_ci negative_token = Some(Token)); 105633d722a9Sopenharmony_ci self_ty = syn::parse2(ty)?; 105733d722a9Sopenharmony_ci } 105833d722a9Sopenharmony_ci } 105933d722a9Sopenharmony_ci } 106033d722a9Sopenharmony_ci } 106133d722a9Sopenharmony_ci 106233d722a9Sopenharmony_ci let ty = parse_type(&self_ty)?; 106333d722a9Sopenharmony_ci let ty_generics = match &ty { 106433d722a9Sopenharmony_ci Type::RustBox(ty) 106533d722a9Sopenharmony_ci | Type::RustVec(ty) 106633d722a9Sopenharmony_ci | Type::UniquePtr(ty) 106733d722a9Sopenharmony_ci | Type::SharedPtr(ty) 106833d722a9Sopenharmony_ci | Type::WeakPtr(ty) 106933d722a9Sopenharmony_ci | Type::CxxVector(ty) => match &ty.inner { 107033d722a9Sopenharmony_ci Type::Ident(ident) => ident.generics.clone(), 107133d722a9Sopenharmony_ci _ => Lifetimes::default(), 107233d722a9Sopenharmony_ci }, 107333d722a9Sopenharmony_ci Type::Ident(_) 107433d722a9Sopenharmony_ci | Type::Ref(_) 107533d722a9Sopenharmony_ci | Type::Ptr(_) 107633d722a9Sopenharmony_ci | Type::Str(_) 107733d722a9Sopenharmony_ci | Type::Fn(_) 107833d722a9Sopenharmony_ci | Type::Void(_) 107933d722a9Sopenharmony_ci | Type::SliceRef(_) 108033d722a9Sopenharmony_ci | Type::Array(_) => Lifetimes::default(), 108133d722a9Sopenharmony_ci }; 108233d722a9Sopenharmony_ci 108333d722a9Sopenharmony_ci let negative = negative_token.is_some(); 108433d722a9Sopenharmony_ci let brace_token = imp.brace_token; 108533d722a9Sopenharmony_ci 108633d722a9Sopenharmony_ci Ok(Api::Impl(Impl { 108733d722a9Sopenharmony_ci cfg, 108833d722a9Sopenharmony_ci impl_token, 108933d722a9Sopenharmony_ci impl_generics, 109033d722a9Sopenharmony_ci negative, 109133d722a9Sopenharmony_ci ty, 109233d722a9Sopenharmony_ci ty_generics, 109333d722a9Sopenharmony_ci brace_token, 109433d722a9Sopenharmony_ci negative_token, 109533d722a9Sopenharmony_ci })) 109633d722a9Sopenharmony_ci} 109733d722a9Sopenharmony_ci 109833d722a9Sopenharmony_cifn parse_include(input: ParseStream) -> Result<Include> { 109933d722a9Sopenharmony_ci if input.peek(LitStr) { 110033d722a9Sopenharmony_ci let lit: LitStr = input.parse()?; 110133d722a9Sopenharmony_ci let span = lit.span(); 110233d722a9Sopenharmony_ci return Ok(Include { 110333d722a9Sopenharmony_ci cfg: CfgExpr::Unconditional, 110433d722a9Sopenharmony_ci path: lit.value(), 110533d722a9Sopenharmony_ci kind: IncludeKind::Quoted, 110633d722a9Sopenharmony_ci begin_span: span, 110733d722a9Sopenharmony_ci end_span: span, 110833d722a9Sopenharmony_ci }); 110933d722a9Sopenharmony_ci } 111033d722a9Sopenharmony_ci 111133d722a9Sopenharmony_ci if input.peek(Token![<]) { 111233d722a9Sopenharmony_ci let mut path = String::new(); 111333d722a9Sopenharmony_ci 111433d722a9Sopenharmony_ci let langle: Token![<] = input.parse()?; 111533d722a9Sopenharmony_ci while !input.is_empty() && !input.peek(Token![>]) { 111633d722a9Sopenharmony_ci let token: TokenTree = input.parse()?; 111733d722a9Sopenharmony_ci match token { 111833d722a9Sopenharmony_ci TokenTree::Ident(token) => path += &token.to_string(), 111933d722a9Sopenharmony_ci TokenTree::Literal(token) 112033d722a9Sopenharmony_ci if token 112133d722a9Sopenharmony_ci .to_string() 112233d722a9Sopenharmony_ci .starts_with(|ch: char| ch.is_ascii_digit()) => 112333d722a9Sopenharmony_ci { 112433d722a9Sopenharmony_ci path += &token.to_string(); 112533d722a9Sopenharmony_ci } 112633d722a9Sopenharmony_ci TokenTree::Punct(token) => path.push(token.as_char()), 112733d722a9Sopenharmony_ci _ => return Err(Error::new(token.span(), "unexpected token in include path")), 112833d722a9Sopenharmony_ci } 112933d722a9Sopenharmony_ci } 113033d722a9Sopenharmony_ci let rangle: Token![>] = input.parse()?; 113133d722a9Sopenharmony_ci 113233d722a9Sopenharmony_ci return Ok(Include { 113333d722a9Sopenharmony_ci cfg: CfgExpr::Unconditional, 113433d722a9Sopenharmony_ci path, 113533d722a9Sopenharmony_ci kind: IncludeKind::Bracketed, 113633d722a9Sopenharmony_ci begin_span: langle.span, 113733d722a9Sopenharmony_ci end_span: rangle.span, 113833d722a9Sopenharmony_ci }); 113933d722a9Sopenharmony_ci } 114033d722a9Sopenharmony_ci 114133d722a9Sopenharmony_ci Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>")) 114233d722a9Sopenharmony_ci} 114333d722a9Sopenharmony_ci 114433d722a9Sopenharmony_cifn parse_type(ty: &RustType) -> Result<Type> { 114533d722a9Sopenharmony_ci match ty { 114633d722a9Sopenharmony_ci RustType::Reference(ty) => parse_type_reference(ty), 114733d722a9Sopenharmony_ci RustType::Ptr(ty) => parse_type_ptr(ty), 114833d722a9Sopenharmony_ci RustType::Path(ty) => parse_type_path(ty), 114933d722a9Sopenharmony_ci RustType::Array(ty) => parse_type_array(ty), 115033d722a9Sopenharmony_ci RustType::BareFn(ty) => parse_type_fn(ty), 115133d722a9Sopenharmony_ci RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span.join())), 115233d722a9Sopenharmony_ci _ => Err(Error::new_spanned(ty, "unsupported type")), 115333d722a9Sopenharmony_ci } 115433d722a9Sopenharmony_ci} 115533d722a9Sopenharmony_ci 115633d722a9Sopenharmony_cifn parse_type_reference(ty: &TypeReference) -> Result<Type> { 115733d722a9Sopenharmony_ci let ampersand = ty.and_token; 115833d722a9Sopenharmony_ci let lifetime = ty.lifetime.clone(); 115933d722a9Sopenharmony_ci let mutable = ty.mutability.is_some(); 116033d722a9Sopenharmony_ci let mutability = ty.mutability; 116133d722a9Sopenharmony_ci 116233d722a9Sopenharmony_ci if let RustType::Slice(slice) = ty.elem.as_ref() { 116333d722a9Sopenharmony_ci let inner = parse_type(&slice.elem)?; 116433d722a9Sopenharmony_ci let bracket = slice.bracket_token; 116533d722a9Sopenharmony_ci return Ok(Type::SliceRef(Box::new(SliceRef { 116633d722a9Sopenharmony_ci ampersand, 116733d722a9Sopenharmony_ci lifetime, 116833d722a9Sopenharmony_ci mutable, 116933d722a9Sopenharmony_ci bracket, 117033d722a9Sopenharmony_ci inner, 117133d722a9Sopenharmony_ci mutability, 117233d722a9Sopenharmony_ci }))); 117333d722a9Sopenharmony_ci } 117433d722a9Sopenharmony_ci 117533d722a9Sopenharmony_ci let inner = parse_type(&ty.elem)?; 117633d722a9Sopenharmony_ci let pinned = false; 117733d722a9Sopenharmony_ci let pin_tokens = None; 117833d722a9Sopenharmony_ci 117933d722a9Sopenharmony_ci Ok(match &inner { 118033d722a9Sopenharmony_ci Type::Ident(ident) if ident.rust == "str" => { 118133d722a9Sopenharmony_ci if ty.mutability.is_some() { 118233d722a9Sopenharmony_ci return Err(Error::new_spanned(ty, "unsupported type")); 118333d722a9Sopenharmony_ci } else { 118433d722a9Sopenharmony_ci Type::Str 118533d722a9Sopenharmony_ci } 118633d722a9Sopenharmony_ci } 118733d722a9Sopenharmony_ci _ => Type::Ref, 118833d722a9Sopenharmony_ci }(Box::new(Ref { 118933d722a9Sopenharmony_ci pinned, 119033d722a9Sopenharmony_ci ampersand, 119133d722a9Sopenharmony_ci lifetime, 119233d722a9Sopenharmony_ci mutable, 119333d722a9Sopenharmony_ci inner, 119433d722a9Sopenharmony_ci pin_tokens, 119533d722a9Sopenharmony_ci mutability, 119633d722a9Sopenharmony_ci }))) 119733d722a9Sopenharmony_ci} 119833d722a9Sopenharmony_ci 119933d722a9Sopenharmony_cifn parse_type_ptr(ty: &TypePtr) -> Result<Type> { 120033d722a9Sopenharmony_ci let star = ty.star_token; 120133d722a9Sopenharmony_ci let mutable = ty.mutability.is_some(); 120233d722a9Sopenharmony_ci let constness = ty.const_token; 120333d722a9Sopenharmony_ci let mutability = ty.mutability; 120433d722a9Sopenharmony_ci 120533d722a9Sopenharmony_ci let inner = parse_type(&ty.elem)?; 120633d722a9Sopenharmony_ci 120733d722a9Sopenharmony_ci Ok(Type::Ptr(Box::new(Ptr { 120833d722a9Sopenharmony_ci star, 120933d722a9Sopenharmony_ci mutable, 121033d722a9Sopenharmony_ci inner, 121133d722a9Sopenharmony_ci mutability, 121233d722a9Sopenharmony_ci constness, 121333d722a9Sopenharmony_ci }))) 121433d722a9Sopenharmony_ci} 121533d722a9Sopenharmony_ci 121633d722a9Sopenharmony_cifn parse_type_path(ty: &TypePath) -> Result<Type> { 121733d722a9Sopenharmony_ci let path = &ty.path; 121833d722a9Sopenharmony_ci if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 { 121933d722a9Sopenharmony_ci let segment = &path.segments[0]; 122033d722a9Sopenharmony_ci let ident = segment.ident.clone(); 122133d722a9Sopenharmony_ci match &segment.arguments { 122233d722a9Sopenharmony_ci PathArguments::None => return Ok(Type::Ident(NamedType::new(ident))), 122333d722a9Sopenharmony_ci PathArguments::AngleBracketed(generic) => { 122433d722a9Sopenharmony_ci if ident == "UniquePtr" && generic.args.len() == 1 { 122533d722a9Sopenharmony_ci if let GenericArgument::Type(arg) = &generic.args[0] { 122633d722a9Sopenharmony_ci let inner = parse_type(arg)?; 122733d722a9Sopenharmony_ci return Ok(Type::UniquePtr(Box::new(Ty1 { 122833d722a9Sopenharmony_ci name: ident, 122933d722a9Sopenharmony_ci langle: generic.lt_token, 123033d722a9Sopenharmony_ci inner, 123133d722a9Sopenharmony_ci rangle: generic.gt_token, 123233d722a9Sopenharmony_ci }))); 123333d722a9Sopenharmony_ci } 123433d722a9Sopenharmony_ci } else if ident == "SharedPtr" && generic.args.len() == 1 { 123533d722a9Sopenharmony_ci if let GenericArgument::Type(arg) = &generic.args[0] { 123633d722a9Sopenharmony_ci let inner = parse_type(arg)?; 123733d722a9Sopenharmony_ci return Ok(Type::SharedPtr(Box::new(Ty1 { 123833d722a9Sopenharmony_ci name: ident, 123933d722a9Sopenharmony_ci langle: generic.lt_token, 124033d722a9Sopenharmony_ci inner, 124133d722a9Sopenharmony_ci rangle: generic.gt_token, 124233d722a9Sopenharmony_ci }))); 124333d722a9Sopenharmony_ci } 124433d722a9Sopenharmony_ci } else if ident == "WeakPtr" && generic.args.len() == 1 { 124533d722a9Sopenharmony_ci if let GenericArgument::Type(arg) = &generic.args[0] { 124633d722a9Sopenharmony_ci let inner = parse_type(arg)?; 124733d722a9Sopenharmony_ci return Ok(Type::WeakPtr(Box::new(Ty1 { 124833d722a9Sopenharmony_ci name: ident, 124933d722a9Sopenharmony_ci langle: generic.lt_token, 125033d722a9Sopenharmony_ci inner, 125133d722a9Sopenharmony_ci rangle: generic.gt_token, 125233d722a9Sopenharmony_ci }))); 125333d722a9Sopenharmony_ci } 125433d722a9Sopenharmony_ci } else if ident == "CxxVector" && generic.args.len() == 1 { 125533d722a9Sopenharmony_ci if let GenericArgument::Type(arg) = &generic.args[0] { 125633d722a9Sopenharmony_ci let inner = parse_type(arg)?; 125733d722a9Sopenharmony_ci return Ok(Type::CxxVector(Box::new(Ty1 { 125833d722a9Sopenharmony_ci name: ident, 125933d722a9Sopenharmony_ci langle: generic.lt_token, 126033d722a9Sopenharmony_ci inner, 126133d722a9Sopenharmony_ci rangle: generic.gt_token, 126233d722a9Sopenharmony_ci }))); 126333d722a9Sopenharmony_ci } 126433d722a9Sopenharmony_ci } else if ident == "Box" && generic.args.len() == 1 { 126533d722a9Sopenharmony_ci if let GenericArgument::Type(arg) = &generic.args[0] { 126633d722a9Sopenharmony_ci let inner = parse_type(arg)?; 126733d722a9Sopenharmony_ci return Ok(Type::RustBox(Box::new(Ty1 { 126833d722a9Sopenharmony_ci name: ident, 126933d722a9Sopenharmony_ci langle: generic.lt_token, 127033d722a9Sopenharmony_ci inner, 127133d722a9Sopenharmony_ci rangle: generic.gt_token, 127233d722a9Sopenharmony_ci }))); 127333d722a9Sopenharmony_ci } 127433d722a9Sopenharmony_ci } else if ident == "Vec" && generic.args.len() == 1 { 127533d722a9Sopenharmony_ci if let GenericArgument::Type(arg) = &generic.args[0] { 127633d722a9Sopenharmony_ci let inner = parse_type(arg)?; 127733d722a9Sopenharmony_ci return Ok(Type::RustVec(Box::new(Ty1 { 127833d722a9Sopenharmony_ci name: ident, 127933d722a9Sopenharmony_ci langle: generic.lt_token, 128033d722a9Sopenharmony_ci inner, 128133d722a9Sopenharmony_ci rangle: generic.gt_token, 128233d722a9Sopenharmony_ci }))); 128333d722a9Sopenharmony_ci } 128433d722a9Sopenharmony_ci } else if ident == "Pin" && generic.args.len() == 1 { 128533d722a9Sopenharmony_ci if let GenericArgument::Type(arg) = &generic.args[0] { 128633d722a9Sopenharmony_ci let inner = parse_type(arg)?; 128733d722a9Sopenharmony_ci let pin_token = kw::Pin(ident.span()); 128833d722a9Sopenharmony_ci if let Type::Ref(mut inner) = inner { 128933d722a9Sopenharmony_ci inner.pinned = true; 129033d722a9Sopenharmony_ci inner.pin_tokens = 129133d722a9Sopenharmony_ci Some((pin_token, generic.lt_token, generic.gt_token)); 129233d722a9Sopenharmony_ci return Ok(Type::Ref(inner)); 129333d722a9Sopenharmony_ci } 129433d722a9Sopenharmony_ci } 129533d722a9Sopenharmony_ci } else { 129633d722a9Sopenharmony_ci let mut lifetimes = Punctuated::new(); 129733d722a9Sopenharmony_ci let mut only_lifetimes = true; 129833d722a9Sopenharmony_ci for pair in generic.args.pairs() { 129933d722a9Sopenharmony_ci let (param, punct) = pair.into_tuple(); 130033d722a9Sopenharmony_ci if let GenericArgument::Lifetime(param) = param { 130133d722a9Sopenharmony_ci lifetimes.push_value(param.clone()); 130233d722a9Sopenharmony_ci if let Some(punct) = punct { 130333d722a9Sopenharmony_ci lifetimes.push_punct(*punct); 130433d722a9Sopenharmony_ci } 130533d722a9Sopenharmony_ci } else { 130633d722a9Sopenharmony_ci only_lifetimes = false; 130733d722a9Sopenharmony_ci break; 130833d722a9Sopenharmony_ci } 130933d722a9Sopenharmony_ci } 131033d722a9Sopenharmony_ci if only_lifetimes { 131133d722a9Sopenharmony_ci return Ok(Type::Ident(NamedType { 131233d722a9Sopenharmony_ci rust: ident, 131333d722a9Sopenharmony_ci generics: Lifetimes { 131433d722a9Sopenharmony_ci lt_token: Some(generic.lt_token), 131533d722a9Sopenharmony_ci lifetimes, 131633d722a9Sopenharmony_ci gt_token: Some(generic.gt_token), 131733d722a9Sopenharmony_ci }, 131833d722a9Sopenharmony_ci })); 131933d722a9Sopenharmony_ci } 132033d722a9Sopenharmony_ci } 132133d722a9Sopenharmony_ci } 132233d722a9Sopenharmony_ci PathArguments::Parenthesized(_) => {} 132333d722a9Sopenharmony_ci } 132433d722a9Sopenharmony_ci } 132533d722a9Sopenharmony_ci 132633d722a9Sopenharmony_ci Err(Error::new_spanned(ty, "unsupported type")) 132733d722a9Sopenharmony_ci} 132833d722a9Sopenharmony_ci 132933d722a9Sopenharmony_cifn parse_type_array(ty: &TypeArray) -> Result<Type> { 133033d722a9Sopenharmony_ci let inner = parse_type(&ty.elem)?; 133133d722a9Sopenharmony_ci 133233d722a9Sopenharmony_ci let len_expr = if let Expr::Lit(lit) = &ty.len { 133333d722a9Sopenharmony_ci lit 133433d722a9Sopenharmony_ci } else { 133533d722a9Sopenharmony_ci let msg = "unsupported expression, array length must be an integer literal"; 133633d722a9Sopenharmony_ci return Err(Error::new_spanned(&ty.len, msg)); 133733d722a9Sopenharmony_ci }; 133833d722a9Sopenharmony_ci 133933d722a9Sopenharmony_ci let len_token = if let Lit::Int(int) = &len_expr.lit { 134033d722a9Sopenharmony_ci int.clone() 134133d722a9Sopenharmony_ci } else { 134233d722a9Sopenharmony_ci let msg = "array length must be an integer literal"; 134333d722a9Sopenharmony_ci return Err(Error::new_spanned(len_expr, msg)); 134433d722a9Sopenharmony_ci }; 134533d722a9Sopenharmony_ci 134633d722a9Sopenharmony_ci let len = len_token.base10_parse::<usize>()?; 134733d722a9Sopenharmony_ci if len == 0 { 134833d722a9Sopenharmony_ci let msg = "array with zero size is not supported"; 134933d722a9Sopenharmony_ci return Err(Error::new_spanned(ty, msg)); 135033d722a9Sopenharmony_ci } 135133d722a9Sopenharmony_ci 135233d722a9Sopenharmony_ci let bracket = ty.bracket_token; 135333d722a9Sopenharmony_ci let semi_token = ty.semi_token; 135433d722a9Sopenharmony_ci 135533d722a9Sopenharmony_ci Ok(Type::Array(Box::new(Array { 135633d722a9Sopenharmony_ci bracket, 135733d722a9Sopenharmony_ci inner, 135833d722a9Sopenharmony_ci semi_token, 135933d722a9Sopenharmony_ci len, 136033d722a9Sopenharmony_ci len_token, 136133d722a9Sopenharmony_ci }))) 136233d722a9Sopenharmony_ci} 136333d722a9Sopenharmony_ci 136433d722a9Sopenharmony_cifn parse_type_fn(ty: &TypeBareFn) -> Result<Type> { 136533d722a9Sopenharmony_ci if ty.lifetimes.is_some() { 136633d722a9Sopenharmony_ci return Err(Error::new_spanned( 136733d722a9Sopenharmony_ci ty, 136833d722a9Sopenharmony_ci "function pointer with lifetime parameters is not supported yet", 136933d722a9Sopenharmony_ci )); 137033d722a9Sopenharmony_ci } 137133d722a9Sopenharmony_ci 137233d722a9Sopenharmony_ci if ty.variadic.is_some() { 137333d722a9Sopenharmony_ci return Err(Error::new_spanned( 137433d722a9Sopenharmony_ci ty, 137533d722a9Sopenharmony_ci "variadic function pointer is not supported yet", 137633d722a9Sopenharmony_ci )); 137733d722a9Sopenharmony_ci } 137833d722a9Sopenharmony_ci 137933d722a9Sopenharmony_ci let args = ty 138033d722a9Sopenharmony_ci .inputs 138133d722a9Sopenharmony_ci .iter() 138233d722a9Sopenharmony_ci .enumerate() 138333d722a9Sopenharmony_ci .map(|(i, arg)| { 138433d722a9Sopenharmony_ci let (ident, colon_token) = match &arg.name { 138533d722a9Sopenharmony_ci Some((ident, colon_token)) => (ident.clone(), *colon_token), 138633d722a9Sopenharmony_ci None => { 138733d722a9Sopenharmony_ci let fn_span = ty.paren_token.span.join(); 138833d722a9Sopenharmony_ci let ident = format_ident!("arg{}", i, span = fn_span); 138933d722a9Sopenharmony_ci let colon_token = Token; 139033d722a9Sopenharmony_ci (ident, colon_token) 139133d722a9Sopenharmony_ci } 139233d722a9Sopenharmony_ci }; 139333d722a9Sopenharmony_ci let ty = parse_type(&arg.ty)?; 139433d722a9Sopenharmony_ci let cfg = CfgExpr::Unconditional; 139533d722a9Sopenharmony_ci let doc = Doc::new(); 139633d722a9Sopenharmony_ci let attrs = OtherAttrs::none(); 139733d722a9Sopenharmony_ci let visibility = Token); 139833d722a9Sopenharmony_ci let name = pair(Namespace::default(), &ident, None, None); 139933d722a9Sopenharmony_ci Ok(Var { 140033d722a9Sopenharmony_ci cfg, 140133d722a9Sopenharmony_ci doc, 140233d722a9Sopenharmony_ci attrs, 140333d722a9Sopenharmony_ci visibility, 140433d722a9Sopenharmony_ci name, 140533d722a9Sopenharmony_ci colon_token, 140633d722a9Sopenharmony_ci ty, 140733d722a9Sopenharmony_ci }) 140833d722a9Sopenharmony_ci }) 140933d722a9Sopenharmony_ci .collect::<Result<_>>()?; 141033d722a9Sopenharmony_ci 141133d722a9Sopenharmony_ci let mut throws_tokens = None; 141233d722a9Sopenharmony_ci let ret = parse_return_type(&ty.output, &mut throws_tokens)?; 141333d722a9Sopenharmony_ci let throws = throws_tokens.is_some(); 141433d722a9Sopenharmony_ci 141533d722a9Sopenharmony_ci let asyncness = None; 141633d722a9Sopenharmony_ci let unsafety = ty.unsafety; 141733d722a9Sopenharmony_ci let fn_token = ty.fn_token; 141833d722a9Sopenharmony_ci let generics = Generics::default(); 141933d722a9Sopenharmony_ci let receiver = None; 142033d722a9Sopenharmony_ci let paren_token = ty.paren_token; 142133d722a9Sopenharmony_ci 142233d722a9Sopenharmony_ci Ok(Type::Fn(Box::new(Signature { 142333d722a9Sopenharmony_ci asyncness, 142433d722a9Sopenharmony_ci unsafety, 142533d722a9Sopenharmony_ci fn_token, 142633d722a9Sopenharmony_ci generics, 142733d722a9Sopenharmony_ci receiver, 142833d722a9Sopenharmony_ci args, 142933d722a9Sopenharmony_ci ret, 143033d722a9Sopenharmony_ci throws, 143133d722a9Sopenharmony_ci paren_token, 143233d722a9Sopenharmony_ci throws_tokens, 143333d722a9Sopenharmony_ci }))) 143433d722a9Sopenharmony_ci} 143533d722a9Sopenharmony_ci 143633d722a9Sopenharmony_cifn parse_return_type( 143733d722a9Sopenharmony_ci ty: &ReturnType, 143833d722a9Sopenharmony_ci throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>, 143933d722a9Sopenharmony_ci) -> Result<Option<Type>> { 144033d722a9Sopenharmony_ci let mut ret = match ty { 144133d722a9Sopenharmony_ci ReturnType::Default => return Ok(None), 144233d722a9Sopenharmony_ci ReturnType::Type(_, ret) => ret.as_ref(), 144333d722a9Sopenharmony_ci }; 144433d722a9Sopenharmony_ci 144533d722a9Sopenharmony_ci if let RustType::Path(ty) = ret { 144633d722a9Sopenharmony_ci let path = &ty.path; 144733d722a9Sopenharmony_ci if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 { 144833d722a9Sopenharmony_ci let segment = &path.segments[0]; 144933d722a9Sopenharmony_ci let ident = segment.ident.clone(); 145033d722a9Sopenharmony_ci if let PathArguments::AngleBracketed(generic) = &segment.arguments { 145133d722a9Sopenharmony_ci if ident == "Result" && generic.args.len() == 1 { 145233d722a9Sopenharmony_ci if let GenericArgument::Type(arg) = &generic.args[0] { 145333d722a9Sopenharmony_ci ret = arg; 145433d722a9Sopenharmony_ci *throws_tokens = 145533d722a9Sopenharmony_ci Some((kw::Result(ident.span()), generic.lt_token, generic.gt_token)); 145633d722a9Sopenharmony_ci } 145733d722a9Sopenharmony_ci } 145833d722a9Sopenharmony_ci } 145933d722a9Sopenharmony_ci } 146033d722a9Sopenharmony_ci } 146133d722a9Sopenharmony_ci 146233d722a9Sopenharmony_ci match parse_type(ret)? { 146333d722a9Sopenharmony_ci Type::Void(_) => Ok(None), 146433d722a9Sopenharmony_ci ty => Ok(Some(ty)), 146533d722a9Sopenharmony_ci } 146633d722a9Sopenharmony_ci} 146733d722a9Sopenharmony_ci 146833d722a9Sopenharmony_cifn visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub] { 146933d722a9Sopenharmony_ci Token => vis.span, 147133d722a9Sopenharmony_ci Visibility::Restricted(vis) => vis.pub_token.span, 147233d722a9Sopenharmony_ci Visibility::Inherited => inherited, 147333d722a9Sopenharmony_ci }) 147433d722a9Sopenharmony_ci} 147533d722a9Sopenharmony_ci 147633d722a9Sopenharmony_cifn pair( 147733d722a9Sopenharmony_ci namespace: Namespace, 147833d722a9Sopenharmony_ci default: &Ident, 147933d722a9Sopenharmony_ci cxx: Option<ForeignName>, 148033d722a9Sopenharmony_ci rust: Option<Ident>, 148133d722a9Sopenharmony_ci) -> Pair { 148233d722a9Sopenharmony_ci Pair { 148333d722a9Sopenharmony_ci namespace, 148433d722a9Sopenharmony_ci cxx: cxx 148533d722a9Sopenharmony_ci .unwrap_or_else(|| ForeignName::parse(&default.to_string(), default.span()).unwrap()), 148633d722a9Sopenharmony_ci rust: rust.unwrap_or_else(|| default.clone()), 148733d722a9Sopenharmony_ci } 148833d722a9Sopenharmony_ci} 1489