@@ -107,6 +107,7 @@ pub fn parser(mut input: ItemEnum) -> Result<TokenStream> {
107
107
docs,
108
108
cases,
109
109
None , // TODO: Implement flags support
110
+ discriminant_type,
110
111
) ;
111
112
112
113
Ok ( quote ! {
@@ -121,6 +122,7 @@ pub fn parser(mut input: ItemEnum) -> Result<TokenStream> {
121
122
pub struct Enum < ' a > {
122
123
ident : & ' a Ident ,
123
124
name : String ,
125
+ discriminant_type : DiscriminantType ,
124
126
docs : Vec < String > ,
125
127
cases : Vec < EnumCase > ,
126
128
flags : Option < String > ,
@@ -133,12 +135,14 @@ impl<'a> Enum<'a> {
133
135
docs : Vec < String > ,
134
136
cases : Vec < EnumCase > ,
135
137
flags : Option < String > ,
138
+ discriminant_type : DiscriminantType ,
136
139
) -> Self {
137
140
let name = attrs. rename . rename ( ident. to_string ( ) , RenameRule :: Pascal ) ;
138
141
139
142
Self {
140
143
ident,
141
144
name,
145
+ discriminant_type,
142
146
docs,
143
147
cases,
144
148
flags,
@@ -245,16 +249,93 @@ impl<'a> Enum<'a> {
245
249
}
246
250
}
247
251
}
252
+
253
+ pub fn impl_try_from ( & self ) -> TokenStream {
254
+ if self . discriminant_type == DiscriminantType :: None {
255
+ return quote ! { } ;
256
+ }
257
+ let discriminant_type = match self . discriminant_type {
258
+ DiscriminantType :: Integer => quote ! { i64 } ,
259
+ DiscriminantType :: String => quote ! { & str } ,
260
+ DiscriminantType :: None => unreachable ! ( "Discriminant type should not be None here" ) ,
261
+ } ;
262
+ let ident = & self . ident ;
263
+ let cases = self . cases . iter ( ) . map ( |case| {
264
+ let ident = & case. ident ;
265
+ match case
266
+ . discriminant
267
+ . as_ref ( )
268
+ . expect ( "Discriminant should be set" )
269
+ {
270
+ Discriminant :: String ( s) => quote ! { #s => Ok ( Self :: #ident) } ,
271
+ Discriminant :: Integer ( i) => quote ! { #i => Ok ( Self :: #ident) } ,
272
+ }
273
+ } ) ;
274
+
275
+ quote ! {
276
+ impl TryFrom <#discriminant_type> for #ident {
277
+ type Error = :: ext_php_rs:: error:: Error ;
278
+
279
+ fn try_from( value: #discriminant_type) -> :: ext_php_rs:: error:: Result <Self > {
280
+ match value {
281
+ #(
282
+ #cases,
283
+ ) *
284
+ _ => Err ( :: ext_php_rs:: error:: Error :: InvalidProperty ) ,
285
+ }
286
+ }
287
+ }
288
+ }
289
+ }
290
+
291
+ pub fn impl_into ( & self ) -> TokenStream {
292
+ if self . discriminant_type == DiscriminantType :: None {
293
+ return quote ! { } ;
294
+ }
295
+ let discriminant_type = match self . discriminant_type {
296
+ DiscriminantType :: Integer => quote ! { i64 } ,
297
+ DiscriminantType :: String => quote ! { & ' static str } ,
298
+ DiscriminantType :: None => unreachable ! ( "Discriminant type should not be None here" ) ,
299
+ } ;
300
+ let ident = & self . ident ;
301
+ let cases = self . cases . iter ( ) . map ( |case| {
302
+ let ident = & case. ident ;
303
+ match case
304
+ . discriminant
305
+ . as_ref ( )
306
+ . expect ( "Discriminant should be set" )
307
+ {
308
+ Discriminant :: String ( s) => quote ! { Self :: #ident => #s } ,
309
+ Discriminant :: Integer ( i) => quote ! { Self :: #ident => #i } ,
310
+ }
311
+ } ) ;
312
+
313
+ quote ! {
314
+ impl Into <#discriminant_type> for #ident {
315
+ fn into( self ) -> #discriminant_type {
316
+ match self {
317
+ #(
318
+ #cases,
319
+ ) *
320
+ }
321
+ }
322
+ }
323
+ }
324
+ }
248
325
}
249
326
250
327
impl ToTokens for Enum < ' _ > {
251
328
fn to_tokens ( & self , tokens : & mut TokenStream ) {
252
329
let class = self . registered_class ( ) ;
253
330
let enum_impl = self . registered_enum ( ) ;
331
+ let impl_try_from = self . impl_try_from ( ) ;
332
+ let impl_into = self . impl_into ( ) ;
254
333
255
334
tokens. extend ( quote ! {
256
335
#class
257
336
#enum_impl
337
+ #impl_try_from
338
+ #impl_into
258
339
} ) ;
259
340
}
260
341
}
0 commit comments