@@ -107,6 +107,7 @@ pub fn parser(mut input: ItemEnum) -> Result<TokenStream> {
107107 docs,
108108 cases,
109109 None , // TODO: Implement flags support
110+ discriminant_type,
110111 ) ;
111112
112113 Ok ( quote ! {
@@ -121,6 +122,7 @@ pub fn parser(mut input: ItemEnum) -> Result<TokenStream> {
121122pub struct Enum < ' a > {
122123 ident : & ' a Ident ,
123124 name : String ,
125+ discriminant_type : DiscriminantType ,
124126 docs : Vec < String > ,
125127 cases : Vec < EnumCase > ,
126128 flags : Option < String > ,
@@ -133,12 +135,14 @@ impl<'a> Enum<'a> {
133135 docs : Vec < String > ,
134136 cases : Vec < EnumCase > ,
135137 flags : Option < String > ,
138+ discriminant_type : DiscriminantType ,
136139 ) -> Self {
137140 let name = attrs. rename . rename ( ident. to_string ( ) , RenameRule :: Pascal ) ;
138141
139142 Self {
140143 ident,
141144 name,
145+ discriminant_type,
142146 docs,
143147 cases,
144148 flags,
@@ -245,16 +249,93 @@ impl<'a> Enum<'a> {
245249 }
246250 }
247251 }
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+ }
248325}
249326
250327impl ToTokens for Enum < ' _ > {
251328 fn to_tokens ( & self , tokens : & mut TokenStream ) {
252329 let class = self . registered_class ( ) ;
253330 let enum_impl = self . registered_enum ( ) ;
331+ let impl_try_from = self . impl_try_from ( ) ;
332+ let impl_into = self . impl_into ( ) ;
254333
255334 tokens. extend ( quote ! {
256335 #class
257336 #enum_impl
337+ #impl_try_from
338+ #impl_into
258339 } ) ;
259340 }
260341}
0 commit comments