1+ //! # Macros for PHP bindings
12mod class;
23mod constant;
34mod extern_;
@@ -11,17 +12,16 @@ mod startup_function;
1112mod syn_ext;
1213mod zval;
1314
14- use std:: {
15- collections:: HashMap ,
16- sync:: { Mutex , MutexGuard } ,
17- } ;
15+ use std:: collections:: HashMap ;
1816
1917use constant:: Constant ;
18+ use darling:: FromMeta ;
2019use proc_macro:: TokenStream ;
21- use proc_macro2:: Span ;
20+ use proc_macro2:: { Span , TokenStream as TokenStream2 } ;
21+ use quote:: { quote, ToTokens } ;
2222use syn:: {
23- parse_macro_input, AttributeArgs , DeriveInput , ItemConst , ItemFn , ItemForeignMod , ItemImpl ,
24- ItemStruct ,
23+ parse_macro_input, spanned :: Spanned , Attribute , AttributeArgs , DeriveInput , Item , ItemConst ,
24+ ItemFn , ItemForeignMod , ItemImpl , ItemMod , ItemStruct , NestedMeta ,
2525} ;
2626
2727extern crate proc_macro;
@@ -32,22 +32,83 @@ struct State {
3232 classes : HashMap < String , class:: Class > ,
3333 constants : Vec < Constant > ,
3434 startup_function : Option < String > ,
35- built_module : bool ,
3635}
3736
38- lazy_static:: lazy_static! {
39- pub ( crate ) static ref STATE : StateMutex = StateMutex :: new( ) ;
40- }
37+ impl State {
38+ fn parse_item ( & mut self , item : & Item ) -> TokenStream2 {
39+ let mut unparsed_attr = vec ! [ ] ;
40+ let tokens: TokenStream2 = match item {
41+ Item :: Fn ( func) => {
42+ for attr in & func. attrs {
43+ if attr. style == syn:: AttrStyle :: Outer && attr. path . is_ident ( "php_function" ) {
44+ match Self :: parse_attr ( attr) {
45+ Ok ( attr_args) => {
46+ let ( tokens, func) = function:: parser ( attr_args, func)
47+ . expect ( "Failed to parse function" ) ;
48+ self . functions . push ( func) ;
49+ return tokens;
50+ }
51+ Err ( e) => return e,
52+ }
53+ } else if attr. style == syn:: AttrStyle :: Outer
54+ && attr. path . is_ident ( "php_startup" )
55+ {
56+ match Self :: parse_attr ( attr) {
57+ Ok ( attr_args) => {
58+ let ( tokens, func) =
59+ startup_function:: parser ( Some ( attr_args) , func)
60+ . expect ( "Failed to parse startup function" ) ;
61+ self . startup_function = Some ( func. to_string ( ) ) ;
62+ return tokens;
63+ }
64+ Err ( e) => return e,
65+ }
66+ } else {
67+ unparsed_attr. push ( attr. into_token_stream ( ) ) ;
68+ }
69+
70+ unparsed_attr. push ( attr. into_token_stream ( ) ) ;
71+ }
72+ return quote ! { #func } ;
73+ }
74+ _ => quote ! { #item } ,
75+ } ;
76+
77+ tokens
78+ }
79+
80+ fn parse_attr < T > ( attr : & Attribute ) -> Result < T , TokenStream2 >
81+ where
82+ T : FromMeta ,
83+ {
84+ let meta = Self :: parse_metadata ( attr) ;
4185
42- struct StateMutex ( Mutex < State > ) ;
86+ Self :: parse_from_meta ( & meta, Some ( attr. span ( ) ) )
87+ }
4388
44- impl StateMutex {
45- pub fn new ( ) -> Self {
46- Self ( Mutex :: new ( Default :: default ( ) ) )
89+ fn parse_metadata ( attr : & Attribute ) -> Vec < NestedMeta > {
90+ if let Ok ( args) = attr. parse_args :: < TokenStream2 > ( ) . map ( |args| args. into ( ) ) {
91+ syn:: parse_macro_input:: parse :: < AttributeArgs > ( args) . unwrap_or ( vec ! [ ] )
92+ } else {
93+ vec ! [ ]
94+ }
4795 }
4896
49- pub fn lock ( & self ) -> MutexGuard < State > {
50- self . 0 . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) )
97+ fn parse_from_meta < T > (
98+ meta : & Vec < NestedMeta > ,
99+ call_site : Option < Span > ,
100+ ) -> Result < T , TokenStream2 >
101+ where
102+ T : FromMeta ,
103+ {
104+ T :: from_list ( & meta) . map_err ( |e| {
105+ syn:: Error :: new (
106+ call_site. unwrap_or_else ( Span :: call_site) ,
107+ format ! ( "Unable to parse attribute arguments: {:?}" , e) ,
108+ )
109+ . to_compile_error ( )
110+ . into ( )
111+ } )
51112 }
52113}
53114
@@ -67,8 +128,12 @@ pub fn php_class(args: TokenStream, input: TokenStream) -> TokenStream {
67128pub fn php_function ( args : TokenStream , input : TokenStream ) -> TokenStream {
68129 let args = parse_macro_input ! ( args as AttributeArgs ) ;
69130 let input = parse_macro_input ! ( input as ItemFn ) ;
131+ let attr_args = match State :: parse_from_meta ( & args, None ) {
132+ Ok ( attr_args) => attr_args,
133+ Err ( e) => return e. into ( ) ,
134+ } ;
70135
71- match function:: parser ( args , input) {
136+ match function:: parser ( attr_args , & input) {
72137 Ok ( ( parsed, _) ) => parsed,
73138 Err ( e) => syn:: Error :: new ( Span :: call_site ( ) , e) . to_compile_error ( ) ,
74139 }
@@ -77,7 +142,7 @@ pub fn php_function(args: TokenStream, input: TokenStream) -> TokenStream {
77142
78143#[ proc_macro_attribute]
79144pub fn php_module ( _: TokenStream , input : TokenStream ) -> TokenStream {
80- let input = parse_macro_input ! ( input as ItemFn ) ;
145+ let input = parse_macro_input ! ( input as ItemMod ) ;
81146
82147 match module:: parser ( input) {
83148 Ok ( parsed) => parsed,
@@ -90,9 +155,13 @@ pub fn php_module(_: TokenStream, input: TokenStream) -> TokenStream {
90155pub fn php_startup ( args : TokenStream , input : TokenStream ) -> TokenStream {
91156 let args = parse_macro_input ! ( args as AttributeArgs ) ;
92157 let input = parse_macro_input ! ( input as ItemFn ) ;
158+ let attr_args = match State :: parse_from_meta ( & args, None ) {
159+ Ok ( attr_args) => attr_args,
160+ Err ( e) => return e. into ( ) ,
161+ } ;
93162
94- match startup_function:: parser ( Some ( args ) , input) {
95- Ok ( parsed) => parsed,
163+ match startup_function:: parser ( Some ( attr_args ) , & input) {
164+ Ok ( ( parsed, _ ) ) => parsed,
96165 Err ( e) => syn:: Error :: new ( Span :: call_site ( ) , e) . to_compile_error ( ) ,
97166 }
98167 . into ( )
0 commit comments