@@ -2,6 +2,7 @@ use super::guid;
22use super :: * ;
33
44syn:: custom_keyword!( interface) ;
5+ syn:: custom_keyword!( event) ;
56
67#[ derive( Debug ) ]
78pub struct Interface {
@@ -10,10 +11,76 @@ pub struct Interface {
1011 pub name : syn:: Ident ,
1112 pub generics : syn:: Generics ,
1213 pub requires : Vec < syn:: Path > ,
13- pub methods : Vec < Method > ,
14+ pub members : Vec < InterfaceMember > ,
1415 pub winrt : bool ,
1516}
1617
18+ /// A property shorthand inside an interface body.
19+ ///
20+ /// Syntax: `[#[get] | #[set]] Name: Type;`
21+ ///
22+ /// - No attribute → generates both `get_Name` and `put_Name` methods.
23+ /// - `#[get]` → generates only `get_Name`.
24+ /// - `#[set]` → generates only `put_Name`.
25+ #[ derive( Debug ) ]
26+ pub struct Property {
27+ pub attrs : Vec < syn:: Attribute > ,
28+ pub name : syn:: Ident ,
29+ pub ty : syn:: Type ,
30+ }
31+
32+ /// An event shorthand inside an interface body.
33+ ///
34+ /// Syntax: `event Name: HandlerType;`
35+ ///
36+ /// Generates `add_Name` and `remove_Name` methods with the `SpecialName` flag.
37+ #[ derive( Debug ) ]
38+ pub struct Event {
39+ pub name : syn:: Ident ,
40+ pub handler_ty : syn:: Type ,
41+ }
42+
43+ /// A member of an interface body: either a regular method, a property shorthand,
44+ /// or an event shorthand.
45+ #[ derive( Debug ) ]
46+ pub enum InterfaceMember {
47+ Method ( Method ) ,
48+ Property ( Property ) ,
49+ Event ( Event ) ,
50+ }
51+
52+ impl syn:: parse:: Parse for InterfaceMember {
53+ fn parse ( input : syn:: parse:: ParseStream ) -> syn:: Result < Self > {
54+ // Peek past any outer attributes to determine which member kind follows.
55+ let fork = input. fork ( ) ;
56+ fork. call ( syn:: Attribute :: parse_outer) ?;
57+
58+ if fork. peek ( syn:: Token ![ fn ] ) {
59+ return input. parse ( ) . map ( Self :: Method ) ;
60+ }
61+
62+ if fork. peek ( event) {
63+ // Consume (and discard) any attributes before `event` — the event
64+ // shorthand does not support per-member attributes.
65+ input. call ( syn:: Attribute :: parse_outer) ?;
66+ let _event_token: event = input. parse ( ) ?;
67+ let name: syn:: Ident = input. parse ( ) ?;
68+ input. parse :: < syn:: Token ![ : ] > ( ) ?;
69+ let handler_ty: syn:: Type = input. parse ( ) ?;
70+ input. parse :: < syn:: Token ![ ; ] > ( ) ?;
71+ return Ok ( Self :: Event ( Event { name, handler_ty } ) ) ;
72+ }
73+
74+ // Property shorthand: `[#[get] | #[set]] Name: Type;`
75+ let attrs = input. call ( syn:: Attribute :: parse_outer) ?;
76+ let name: syn:: Ident = input. parse ( ) ?;
77+ input. parse :: < syn:: Token ![ : ] > ( ) ?;
78+ let ty: syn:: Type = input. parse ( ) ?;
79+ input. parse :: < syn:: Token ![ ; ] > ( ) ?;
80+ Ok ( Self :: Property ( Property { attrs, name, ty } ) )
81+ }
82+ }
83+
1784impl syn:: parse:: Parse for Interface {
1885 fn parse ( input : syn:: parse:: ParseStream ) -> syn:: Result < Self > {
1986 let attrs = input. call ( syn:: Attribute :: parse_outer) ?;
@@ -33,10 +100,10 @@ impl syn::parse::Parse for Interface {
33100
34101 let content;
35102 syn:: braced!( content in input) ;
36- let mut methods = vec ! [ ] ;
103+ let mut members = vec ! [ ] ;
37104
38105 while !content. is_empty ( ) {
39- methods . push ( content. parse ( ) ?) ;
106+ members . push ( content. parse ( ) ?) ;
40107 }
41108
42109 Ok ( Self {
@@ -45,7 +112,7 @@ impl syn::parse::Parse for Interface {
45112 name,
46113 generics,
47114 requires,
48- methods ,
115+ members ,
49116 winrt : false ,
50117 } )
51118 }
@@ -123,86 +190,211 @@ impl Encoder<'_> {
123190
124191 let mut method_signatures: Vec < ( String , Vec < metadata:: Type > , metadata:: Type ) > = Vec :: new ( ) ;
125192
126- for method in & item. methods {
127- let mut params = vec ! [ ] ;
193+ for member in & item. members {
194+ match member {
195+ InterfaceMember :: Method ( method) => {
196+ let mut params = vec ! [ ] ;
128197
129- if method. sig . inputs . is_empty ( ) {
130- return self . err ( & method. sig . ident , "`&self` parameter not found" ) ;
131- }
198+ if method. sig . inputs . is_empty ( ) {
199+ return self . err ( & method. sig . ident , "`&self` parameter not found" ) ;
200+ }
132201
133- for ( sequence, arg) in method. sig . inputs . iter ( ) . enumerate ( ) {
134- match arg {
135- syn:: FnArg :: Receiver ( receiver) => {
136- if * receiver != syn:: parse_quote! { & self } {
137- return self . err ( receiver, "`&self` parameter not found" ) ;
202+ for ( sequence, arg) in method. sig . inputs . iter ( ) . enumerate ( ) {
203+ match arg {
204+ syn:: FnArg :: Receiver ( receiver) => {
205+ if * receiver != syn:: parse_quote! { & self } {
206+ return self . err ( receiver, "`&self` parameter not found" ) ;
207+ }
208+ }
209+ syn:: FnArg :: Typed ( pt) => {
210+ if sequence == 0 {
211+ return self . err ( arg, "`&self` parameter not found" ) ;
212+ }
213+ let p = self . param ( pt) ?;
214+ if item. winrt {
215+ self . validate_type_is_winrt ( & pt. ty , & p. ty ) ?;
216+ }
217+ params. push ( p) ;
218+ }
138219 }
139220 }
140- syn:: FnArg :: Typed ( pt) => {
141- if sequence == 0 {
142- return self . err ( arg, "`&self` parameter not found" ) ;
221+
222+ let types: Vec < metadata:: Type > =
223+ params. iter ( ) . map ( |param| param. ty . clone ( ) ) . collect ( ) ;
224+ let return_type = self . encode_return_type ( & method. sig . output ) ?;
225+
226+ if item. winrt {
227+ if let syn:: ReturnType :: Type ( _, return_syn_ty) = & method. sig . output {
228+ self . validate_type_is_winrt ( return_syn_ty. as_ref ( ) , & return_type) ?;
143229 }
144- let p = self . param ( pt) ?;
145- if item. winrt {
146- self . validate_type_is_winrt ( & pt. ty , & p. ty ) ?;
230+ }
231+
232+ if !already_has_guid {
233+ method_signatures. push ( (
234+ method. sig . ident . to_string ( ) ,
235+ types. clone ( ) ,
236+ return_type. clone ( ) ,
237+ ) ) ;
238+ }
239+
240+ let signature = metadata:: Signature {
241+ flags : metadata:: MethodCallAttributes :: HASTHIS ,
242+ return_type,
243+ types,
244+ } ;
245+
246+ let mut is_special = false ;
247+ for attr in & method. attrs {
248+ if attr. path ( ) . is_ident ( "special" ) {
249+ if !matches ! ( attr. meta, syn:: Meta :: Path ( _) ) {
250+ return self
251+ . err ( attr, "`special` attribute does not accept arguments" ) ;
252+ }
253+ is_special = true ;
147254 }
148- params. push ( p) ;
149255 }
150- }
151- }
152256
153- let types: Vec < metadata:: Type > = params. iter ( ) . map ( |param| param. ty . clone ( ) ) . collect ( ) ;
154- let return_type = self . encode_return_type ( & method. sig . output ) ?;
257+ let mut flags = base_flags;
258+ if is_special {
259+ flags |= metadata:: MethodAttributes :: SpecialName ;
260+ }
155261
156- if item. winrt {
157- if let syn:: ReturnType :: Type ( _, return_syn_ty) = & method. sig . output {
158- self . validate_type_is_winrt ( return_syn_ty. as_ref ( ) , & return_type) ?;
262+ let method_def = self . output . MethodDef (
263+ & method. sig . ident . to_string ( ) ,
264+ & signature,
265+ flags,
266+ Default :: default ( ) ,
267+ ) ;
268+
269+ self . encode_attrs (
270+ metadata:: writer:: HasAttribute :: MethodDef ( method_def) ,
271+ & method. attrs ,
272+ & [ "special" ] ,
273+ ) ?;
274+
275+ self . encode_return_attrs ( & method. return_attrs ) ?;
276+ self . encode_params ( & params) ?;
159277 }
160- }
161278
162- if !already_has_guid {
163- method_signatures. push ( (
164- method. sig . ident . to_string ( ) ,
165- types. clone ( ) ,
166- return_type. clone ( ) ,
167- ) ) ;
168- }
169-
170- let signature = metadata:: Signature {
171- flags : metadata:: MethodCallAttributes :: HASTHIS ,
172- return_type,
173- types,
174- } ;
279+ InterfaceMember :: Property ( prop) => {
280+ let is_get_only = prop. attrs . iter ( ) . any ( |a| a. path ( ) . is_ident ( "get" ) ) ;
281+ let is_set_only = prop. attrs . iter ( ) . any ( |a| a. path ( ) . is_ident ( "set" ) ) ;
175282
176- let mut is_special = false ;
177- for attr in & method . attrs {
178- if attr . path ( ) . is_ident ( "special" ) {
179- if ! matches ! ( attr . meta , syn :: Meta :: Path ( _ ) ) {
180- return self . err ( attr , "`special` attribute does not accept arguments" ) ;
283+ if is_get_only && is_set_only {
284+ return self . err (
285+ & prop . name ,
286+ "property cannot have both `#[get]` and `#[set]` attributes" ,
287+ ) ;
181288 }
182- is_special = true ;
183- }
184- }
185289
186- let mut flags = base_flags;
187- if is_special {
188- flags |= metadata:: MethodAttributes :: SpecialName ;
189- }
290+ for attr in & prop. attrs {
291+ if !attr. path ( ) . is_ident ( "get" ) && !attr. path ( ) . is_ident ( "set" ) {
292+ return self . err (
293+ attr,
294+ "only `#[get]` and `#[set]` attributes are supported on properties" ,
295+ ) ;
296+ }
297+ if !matches ! ( attr. meta, syn:: Meta :: Path ( _) ) {
298+ return self
299+ . err ( attr, "`get`/`set` attribute does not accept arguments" ) ;
300+ }
301+ }
190302
191- let method_def = self . output . MethodDef (
192- & method. sig . ident . to_string ( ) ,
193- & signature,
194- flags,
195- Default :: default ( ) ,
196- ) ;
303+ let ty = self . encode_type ( & prop. ty ) ?;
304+ let method_flags = base_flags | metadata:: MethodAttributes :: SpecialName ;
305+
306+ if !is_set_only {
307+ let get_name = format ! ( "get_{}" , prop. name) ;
308+ let signature = metadata:: Signature {
309+ flags : metadata:: MethodCallAttributes :: HASTHIS ,
310+ return_type : ty. clone ( ) ,
311+ types : vec ! [ ] ,
312+ } ;
313+ if !already_has_guid {
314+ method_signatures. push ( ( get_name. clone ( ) , vec ! [ ] , ty. clone ( ) ) ) ;
315+ }
316+ self . output . MethodDef (
317+ & get_name,
318+ & signature,
319+ method_flags,
320+ Default :: default ( ) ,
321+ ) ;
322+ self . encode_simple_params ( & [ ] ) ?;
323+ }
197324
198- self . encode_attrs (
199- metadata:: writer:: HasAttribute :: MethodDef ( method_def) ,
200- & method. attrs ,
201- & [ "special" ] ,
202- ) ?;
325+ if !is_get_only {
326+ let put_name = format ! ( "put_{}" , prop. name) ;
327+ let signature = metadata:: Signature {
328+ flags : metadata:: MethodCallAttributes :: HASTHIS ,
329+ return_type : metadata:: Type :: Void ,
330+ types : vec ! [ ty. clone( ) ] ,
331+ } ;
332+ if !already_has_guid {
333+ method_signatures. push ( (
334+ put_name. clone ( ) ,
335+ vec ! [ ty. clone( ) ] ,
336+ metadata:: Type :: Void ,
337+ ) ) ;
338+ }
339+ self . output . MethodDef (
340+ & put_name,
341+ & signature,
342+ method_flags,
343+ Default :: default ( ) ,
344+ ) ;
345+ self . encode_simple_params ( & [ ( "value" , & ty) ] ) ?;
346+ }
347+ }
203348
204- self . encode_return_attrs ( & method. return_attrs ) ?;
205- self . encode_params ( & params) ?;
349+ InterfaceMember :: Event ( evt) => {
350+ let handler_ty = self . encode_type ( & evt. handler_ty ) ?;
351+ let token_ty =
352+ metadata:: Type :: value_named ( "Windows.Foundation" , "EventRegistrationToken" ) ;
353+ let method_flags = base_flags | metadata:: MethodAttributes :: SpecialName ;
354+
355+ let add_name = format ! ( "add_{}" , evt. name) ;
356+ let add_signature = metadata:: Signature {
357+ flags : metadata:: MethodCallAttributes :: HASTHIS ,
358+ return_type : token_ty. clone ( ) ,
359+ types : vec ! [ handler_ty. clone( ) ] ,
360+ } ;
361+ if !already_has_guid {
362+ method_signatures. push ( (
363+ add_name. clone ( ) ,
364+ vec ! [ handler_ty. clone( ) ] ,
365+ token_ty. clone ( ) ,
366+ ) ) ;
367+ }
368+ self . output . MethodDef (
369+ & add_name,
370+ & add_signature,
371+ method_flags,
372+ Default :: default ( ) ,
373+ ) ;
374+ self . encode_simple_params ( & [ ( "handler" , & handler_ty) ] ) ?;
375+
376+ let remove_name = format ! ( "remove_{}" , evt. name) ;
377+ let remove_signature = metadata:: Signature {
378+ flags : metadata:: MethodCallAttributes :: HASTHIS ,
379+ return_type : metadata:: Type :: Void ,
380+ types : vec ! [ token_ty. clone( ) ] ,
381+ } ;
382+ if !already_has_guid {
383+ method_signatures. push ( (
384+ remove_name. clone ( ) ,
385+ vec ! [ token_ty. clone( ) ] ,
386+ metadata:: Type :: Void ,
387+ ) ) ;
388+ }
389+ self . output . MethodDef (
390+ & remove_name,
391+ & remove_signature,
392+ method_flags,
393+ Default :: default ( ) ,
394+ ) ;
395+ self . encode_simple_params ( & [ ( "token" , & token_ty) ] ) ?;
396+ }
397+ }
206398 }
207399
208400 if !already_has_guid {
0 commit comments