22//!
33//! The focal point of this module is the [`LanguageExtension`] API.
44
5+ #[ cfg( test) ]
6+ use strum:: IntoEnumIterator ;
7+
58/// A language extension recognized by Naga, but not guaranteed to be present in all environments.
69///
710/// WGSL spec.: <https://www.w3.org/TR/WGSL/#language-extensions-sec>
@@ -49,11 +52,18 @@ impl LanguageExtension {
4952 } ,
5053 }
5154 }
55+
56+ #[ cfg( test) ]
57+ fn iter ( ) -> impl Iterator < Item = Self > {
58+ let implemented = ImplementedLanguageExtension :: iter ( ) . map ( Self :: Implemented ) ;
59+ let unimplemented = UnimplementedLanguageExtension :: iter ( ) . map ( Self :: Unimplemented ) ;
60+ implemented. chain ( unimplemented)
61+ }
5262}
5363
5464/// A variant of [`LanguageExtension::Implemented`].
5565#[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq ) ]
56- #[ cfg_attr( test, derive( strum:: VariantArray ) ) ]
66+ #[ cfg_attr( test, derive( strum:: EnumIter , strum :: VariantArray ) ) ]
5767pub enum ImplementedLanguageExtension {
5868 ReadOnlyAndReadWriteStorageTextures ,
5969 Packed4x8IntegerDotProduct ,
@@ -101,6 +111,7 @@ fn test_manual_variants_array_is_correct() {
101111
102112/// A variant of [`LanguageExtension::Unimplemented`].
103113#[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq ) ]
114+ #[ cfg_attr( test, derive( strum:: EnumIter ) ) ]
104115pub enum UnimplementedLanguageExtension {
105116 UnrestrictedPointerParameters ,
106117}
@@ -112,3 +123,94 @@ impl UnimplementedLanguageExtension {
112123 }
113124 }
114125}
126+
127+ #[ cfg( test) ]
128+ mod test {
129+ use itertools:: Itertools ;
130+ use strum:: IntoEnumIterator ;
131+
132+ use crate :: front:: wgsl:: assert_parse_err;
133+
134+ use super :: { ImplementedLanguageExtension , LanguageExtension } ;
135+
136+ #[ test]
137+ fn implemented ( ) {
138+ #[ derive( Clone , Debug , strum:: EnumIter ) ]
139+ enum Count {
140+ ByItself ,
141+ WithOther ,
142+ }
143+
144+ #[ derive( Clone , Debug , strum:: EnumIter ) ]
145+ enum Separation {
146+ SameLineNoSpace ,
147+ SameLine ,
148+ MultiLine ,
149+ }
150+
151+ #[ derive( Clone , Debug , strum:: EnumIter ) ]
152+ enum TrailingComma {
153+ Yes ,
154+ No ,
155+ }
156+
157+ #[ track_caller]
158+ fn test_requires ( before : & str , idents : & [ & str ] , ident_sep : & str , after : & str ) {
159+ let ident_list = idents. join ( ident_sep) ;
160+ let shader = format ! ( "requires{before}{ident_list}{after};" ) ;
161+ let expected_msg = "" . to_string ( ) ;
162+ assert_parse_err ( & shader, & expected_msg) ;
163+ }
164+
165+ let implemented_extensions =
166+ ImplementedLanguageExtension :: iter ( ) . map ( LanguageExtension :: Implemented ) ;
167+
168+ let iter = implemented_extensions
169+ . clone ( )
170+ . cartesian_product ( Count :: iter ( ) )
171+ . cartesian_product ( Separation :: iter ( ) )
172+ . cartesian_product ( TrailingComma :: iter ( ) ) ;
173+ for ( ( ( extension, count) , separation) , trailing_comma) in iter {
174+ let before;
175+ let ident_sep;
176+ match separation {
177+ Separation :: SameLine => {
178+ before = " " ;
179+ ident_sep = ", " ;
180+ }
181+ Separation :: SameLineNoSpace => {
182+ before = " " ;
183+ ident_sep = "," ;
184+ }
185+ Separation :: MultiLine => {
186+ before = "\n " ;
187+ ident_sep = ",\n " ;
188+ }
189+ }
190+ let after = match trailing_comma {
191+ TrailingComma :: Yes => ident_sep,
192+ TrailingComma :: No => before,
193+ } ;
194+ match count {
195+ Count :: ByItself => test_requires ( before, & [ extension. to_ident ( ) ] , ident_sep, after) ,
196+ Count :: WithOther => {
197+ for other_extension in implemented_extensions. clone ( ) {
198+ for list in [ [ extension, other_extension] , [ other_extension, extension] ] {
199+ let list = list. map ( |e| e. to_ident ( ) ) ;
200+ test_requires ( before, & list, ident_sep, after) ;
201+ }
202+ }
203+ }
204+ }
205+ }
206+ }
207+
208+ #[ test]
209+ fn unimplemented ( ) { }
210+
211+ #[ test]
212+ fn unknown ( ) { }
213+
214+ #[ test]
215+ fn malformed ( ) { }
216+ }
0 commit comments