1111use heck:: { ToShoutySnakeCase , ToSnakeCase , ToUpperCamelCase } ;
1212use itertools:: Itertools ;
1313use nom:: {
14+ IResult , Parser ,
1415 branch:: alt,
1516 bytes:: complete:: { tag, take_until, take_while1} ,
1617 character:: complete:: {
@@ -19,7 +20,6 @@ use nom::{
1920 combinator:: { map, map_res, opt, value} ,
2021 multi:: { many1, separated_list1} ,
2122 sequence:: { delimited, pair, preceded, separated_pair, terminated} ,
22- IResult , Parser ,
2323} ;
2424use proc_macro2:: { Delimiter , Group , Literal , Span , TokenStream , TokenTree } ;
2525use quote:: * ;
@@ -84,15 +84,20 @@ impl quote::ToTokens for CType {
8484}
8585
8686fn parse_ctype ( i : & str ) -> IResult < & str , CType > {
87- ( alt ( ( value ( CType :: U64 , tag ( "ULL" ) ) , value ( CType :: U32 , tag ( "U" ) ) ) ) ) . parse ( i)
87+ ( alt ( (
88+ value ( CType :: U64 , tag ( "ULL" ) ) ,
89+ value ( CType :: U32 , tag ( "U" ) ) ,
90+ // success(CType::U32), // Only for `0x1234` hexadecimals without type-suffix
91+ ) ) )
92+ . parse ( i)
8893}
8994
9095fn parse_cexpr ( i : & str ) -> IResult < & str , ( CType , String ) > {
9196 ( alt ( (
9297 map ( parse_cfloat, |f| ( CType :: Float , format ! ( "{f:.2}" ) ) ) ,
98+ parse_hexadecimal_number,
9399 parse_inverse_number,
94100 parse_decimal_number,
95- parse_hexadecimal_number,
96101 ) ) )
97102 . parse ( i)
98103}
@@ -398,7 +403,10 @@ pub enum Constant {
398403 Number ( i32 ) ,
399404 Hex ( String ) ,
400405 BitPos ( u32 ) ,
401- CExpr ( vkxml:: CExpression ) ,
406+ /// A C expression, also used for floating point (`1000.0F`) and some integer representations (`(~0ULL)`).
407+ ///
408+ /// Hexadecimals could use this path, but are currently handled separately.
409+ CExpr ( String ) ,
402410 Text ( String ) ,
403411 Alias ( Ident ) ,
404412}
@@ -417,7 +425,7 @@ impl quote::ToTokens for Constant {
417425 Self :: Text ( ref text) => text. to_tokens ( tokens) ,
418426 Self :: CExpr ( ref expr) => {
419427 let ( rem, ( _, rexpr) ) = parse_cexpr ( expr) . expect ( "Unable to parse cexpr" ) ;
420- assert ! ( rem. is_empty( ) ) ;
428+ assert ! ( rem. is_empty( ) , "{rem}" ) ;
421429 tokens. extend ( rexpr. parse :: < TokenStream > ( ) ) ;
422430 }
423431 Self :: BitPos ( pos) => {
@@ -471,10 +479,10 @@ impl Constant {
471479 Self :: Number ( _) | Self :: Hex ( _) => CType :: USize ,
472480 Self :: CExpr ( expr) => {
473481 let ( rem, ( ty, _) ) = parse_cexpr ( expr) . expect ( "Unable to parse cexpr" ) ;
474- assert ! ( rem. is_empty( ) ) ;
482+ assert ! ( rem. is_empty( ) , "{rem}" ) ;
475483 ty
476484 }
477- _ => unimplemented ! ( ) ,
485+ x => unimplemented ! ( "{x:?}" ) ,
478486 }
479487 }
480488
@@ -528,19 +536,25 @@ impl Constant {
528536 Some ( ( Self :: Number ( value as i32 ) , Some ( extends. clone ( ) ) , false ) )
529537 }
530538 EnumSpec :: Value { value, extends } => {
531- let value = value
532- . strip_prefix ( "0x" )
533- . map ( |hex| Self :: Hex ( hex. to_owned ( ) ) )
534- . or_else ( || value. parse :: < i32 > ( ) . ok ( ) . map ( Self :: Number ) ) ?;
539+ let value = if let Ok ( value) = value. parse :: < i32 > ( ) {
540+ Self :: Number ( value)
541+ } else if let Some ( hex) = value. strip_prefix ( "0x" ) {
542+ Self :: Hex ( hex. to_owned ( ) )
543+ } else {
544+ Self :: CExpr ( value. to_owned ( ) )
545+ } ;
546+
535547 Some ( ( value, extends. clone ( ) , false ) )
536548 }
537549 EnumSpec :: Alias { alias, extends } => {
538- let base_type = extends. as_deref ( ) . or ( enum_name) ?;
539- let key = variant_ident ( base_type, alias) ;
550+ let base_type = extends. as_deref ( ) . or ( enum_name) ;
551+ let key = base_type. map_or ( format_ident ! ( "{}" , alias) , |base_type| {
552+ variant_ident ( base_type, alias)
553+ } ) ;
540554 if key == "DISPATCH_BASE" {
541555 None
542556 } else {
543- Some ( ( Self :: Alias ( key) , Some ( base_type. to_owned ( ) ) , true ) )
557+ Some ( ( Self :: Alias ( key) , base_type. map ( str :: to_owned ) , true ) )
544558 }
545559 }
546560 _ => None ,
@@ -2804,12 +2818,13 @@ pub fn constant_name(name: &str) -> &str {
28042818 name. strip_prefix ( "VK_" ) . unwrap_or ( name)
28052819}
28062820
2807- pub fn generate_constant < ' a > (
2808- constant : & ' a vkxml:: Constant ,
2809- cache : & mut HashSet < & ' a str > ,
2810- ) -> TokenStream {
2811- cache. insert ( constant. name . as_str ( ) ) ;
2812- let c = Constant :: from_constant ( constant) ;
2821+ pub fn generate_constant ( constant : & vk_parse:: Enum ) -> TokenStream {
2822+ let ( c, _, is_alias) = Constant :: from_vk_parse_enum ( constant, None , None ) . unwrap ( ) ;
2823+ // This requires knowing the type of the alias, that is unavailable here. Besides
2824+ // backwards-compatibility, stabilization aliases serve no purpose.
2825+ if is_alias {
2826+ return quote ! ( ) ;
2827+ }
28132828 let name = constant_name ( & constant. name ) ;
28142829 let ident = format_ident ! ( "{}" , name) ;
28152830 let notation = constant. doc_attribute ( ) ;
@@ -3064,11 +3079,13 @@ pub fn write_source_code<P: AsRef<Path>>(vk_headers_dir: &Path, src_dir: P) {
30643079 . flat_map ( |definitions| & definitions. elements )
30653080 . collect ( ) ;
30663081
3067- let constants: Vec < & vkxml :: Constant > = spec
3068- . elements
3082+ let constants: Vec < _ > = spec2
3083+ . 0
30693084 . iter ( )
3070- . filter_map ( get_variant ! ( vkxml:: RegistryElement :: Constants ) )
3071- . flat_map ( |constants| & constants. elements )
3085+ . filter_map ( get_variant ! ( vk_parse:: RegistryChild :: Enums ) )
3086+ . filter ( |enums| enums. kind . as_deref ( ) == Some ( "constants" ) )
3087+ . flat_map ( |enums| & enums. children )
3088+ . filter_map ( get_variant ! ( vk_parse:: EnumsChild :: Enum ) )
30723089 . collect ( ) ;
30733090
30743091 let features_children = spec2
@@ -3080,23 +3097,29 @@ pub fn write_source_code<P: AsRef<Path>>(vk_headers_dir: &Path, src_dir: P) {
30803097
30813098 let extension_children = extensions. iter ( ) . flat_map ( |extension| & extension. children ) ;
30823099
3083- let ( required_types, required_commands) = features_children
3100+ let ( required_types, required_commands, required_enums ) = features_children
30843101 . chain ( extension_children)
30853102 . filter_map ( get_variant ! ( vk_parse:: FeatureChild :: Require { api, items } ) )
30863103 . filter ( |( api, _items) | matches ! ( api. as_deref( ) , None | Some ( DESIRED_API ) ) )
30873104 . flat_map ( |( _api, items) | items)
3088- . fold ( ( HashSet :: new ( ) , HashSet :: new ( ) ) , |mut acc, elem| {
3089- match elem {
3090- vk_parse:: InterfaceItem :: Type { name, .. } => {
3091- acc. 0 . insert ( name. as_str ( ) ) ;
3092- }
3093- vk_parse:: InterfaceItem :: Command { name, .. } => {
3094- acc. 1 . insert ( name. as_str ( ) ) ;
3095- }
3096- _ => { }
3097- } ;
3098- acc
3099- } ) ;
3105+ . fold (
3106+ ( HashSet :: new ( ) , HashSet :: new ( ) , HashSet :: new ( ) ) ,
3107+ |mut acc, elem| {
3108+ match elem {
3109+ vk_parse:: InterfaceItem :: Type { name, .. } => {
3110+ acc. 0 . insert ( name. as_str ( ) ) ;
3111+ }
3112+ vk_parse:: InterfaceItem :: Command { name, .. } => {
3113+ acc. 1 . insert ( name. as_str ( ) ) ;
3114+ }
3115+ vk_parse:: InterfaceItem :: Enum ( vk_parse:: Enum { name, spec, .. } ) => {
3116+ acc. 2 . insert ( name. as_str ( ) ) ;
3117+ }
3118+ _ => { }
3119+ } ;
3120+ acc
3121+ } ,
3122+ ) ;
31003123
31013124 let commands: CommandMap < ' _ > = spec2
31023125 . 0
@@ -3144,13 +3167,11 @@ pub fn write_source_code<P: AsRef<Path>>(vk_headers_dir: &Path, src_dir: P) {
31443167 acc
31453168 } ) ;
31463169
3147- let mut constants_code: Vec < _ > = constants
3170+ let constants_code: Vec < _ > = constants
31483171 . iter ( )
3149- . map ( |constant| generate_constant ( constant, & mut const_cache ) )
3172+ . map ( |constant| generate_constant ( constant) )
31503173 . collect ( ) ;
31513174
3152- constants_code. push ( quote ! { pub const SHADER_UNUSED_NV : u32 = SHADER_UNUSED_KHR ; } ) ;
3153-
31543175 let union_types = definitions
31553176 . iter ( )
31563177 . filter_map ( get_variant ! ( vkxml:: DefinitionsElement :: Union ) )
0 commit comments