1extern crate xml;
2
3use std;
4use std::io::Read;
5use std::str::FromStr;
6use xml::reader::XmlEvent;
7
8use types::*;
9
10type XmlEvents<R> = xml::reader::Events<R>;
11type XmlAttribute = xml::attribute::OwnedAttribute;
12
13struct ParseCtx<R: Read> {
15 events: XmlEvents<R>,
16 xpath: String,
17 errors: Vec<Error>,
18}
19
20impl<R: Read> ParseCtx<R> {
21 fn push_element(&mut self, name: &str) {
22 self.xpath.push('/');
23 self.xpath.push_str(name);
24 }
25
26 fn pop_element(&mut self) {
27 if let Some(separator_pos) = self.xpath.rfind('/') {
28 self.xpath.truncate(separator_pos);
29 } else {
30 self.errors.push(Error::Internal {
31 desc: "ParseCtx push_element/pop_element mismatch.",
32 });
33 }
34 }
35}
36
37fn xpath_attribute(xpath: &str, attribute_name: &str) -> String {
38 let mut xpath = String::from(xpath);
39 xpath.push_str("[@");
40 xpath.push_str(attribute_name);
41 xpath.push(']');
42 xpath
43}
44
45macro_rules! unwrap_attribute (
47 ($ctx:expr, $element:ident, $attribute:ident) => {
48 let $attribute = match $attribute {
49 Some(val) => val,
50 None => {
51 $ctx.errors.push(Error::MissingAttribute {
52 xpath: $ctx.xpath.clone(),
53 name: String::from(stringify!($attribute)),
54 });
55 return None;
56 }
57 };
58 };
59
60 ($ctx:expr, $element:ident, $var:ident, $attribute_str:literal) => {
61 let $var = match $var {
62 Some(val) => val,
63 None => {
64 $ctx.errors.push(Error::MissingAttribute {
65 xpath: $ctx.xpath.clone(),
66 name: String::from($attribute_str),
67 });
68 return None;
69 }
70 };
71 };
72
73);
74
75macro_rules! match_attributes {
76 ($ctx:expr, $a:ident in $attributes:expr, $($p:pat => $e:expr),+ $(,)?) => {
77 for $a in $attributes {
78 let n = $a.name.local_name.as_str();
79 match n {
80 $(
81 $p => $e,
82 )+
83 _ => $ctx.errors.push(Error::UnexpectedAttribute {
84 xpath: $ctx.xpath.clone(),
85 name: String::from(n),
86 })
87 }
88 }
89 };
90}
91
92macro_rules! match_elements {
93 ($ctx:expr, $($p:pat => $e:expr),+ $(,)?) => {
94 while let Some(Ok(e)) = $ctx.events.next() {
95 match e {
96 XmlEvent::StartElement { name, .. } => {
97 let name = name.local_name.as_str();
98 $ctx.push_element(name);
99 match name {
100 $(
101 $p => $e,
102 )+
103 _ => {
104 $ctx.errors.push(Error::UnexpectedElement {
105 xpath: $ctx.xpath.clone(),
106 name: String::from(name),
107 });
108 consume_current_element($ctx);
109 }
110 }
111 }
112 XmlEvent::EndElement { .. } => {
113 $ctx.pop_element();
114 break;
115 }
116 _ => {}
117 }
118 }
119 };
120
121 ( $ctx:expr, $attributes:ident, $($p:pat => $e:expr),+ $(,)?) => {
122 while let Some(Ok(e)) = $ctx.events.next() {
123 match e {
124 XmlEvent::StartElement { name, $attributes, .. } => {
125 let name = name.local_name.as_str();
126 $ctx.push_element(name);
127 match name {
128 $(
129 $p => $e,
130 )+
131 _ => {
132 $ctx.errors.push(Error::UnexpectedElement {
133 xpath: $ctx.xpath.clone(),
134 name: String::from(name),
135 });
136 consume_current_element($ctx);
137 }
138 }
139 }
140 XmlEvent::EndElement { .. } => {
141 $ctx.pop_element();
142 break;
143 }
144 _ => {}
145 }
146 }
147 };
148}
149
150macro_rules! match_elements_combine_text {
151 ( $ctx:expr, $buffer:ident, $($p:pat => $e:expr),+ $(,)?) => {
152 while let Some(Ok(e)) = $ctx.events.next() {
153 match e {
154 XmlEvent::Characters(text) => $buffer.push_str(&text),
155 XmlEvent::Whitespace(text) => $buffer.push_str(&text),
156 XmlEvent::StartElement { name, .. } => {
157 let name = name.local_name.as_str();
158 $ctx.push_element(name);
159 match name {
160 $(
161 $p => $e,
162 )+
163 _ => {
164 $ctx.errors.push(Error::UnexpectedElement {
165 xpath: $ctx.xpath.clone(),
166 name: String::from(name),
167 });
168 consume_current_element($ctx);
169 }
170 }
171 }
172 XmlEvent::EndElement { .. } => {
173 $ctx.pop_element();
174 break;
175 },
176 _ => {}
177 }
178 }
179 };
180
181 ( $ctx:expr, $attributes:ident, $buffer:ident, $($p:pat => $e:expr),+ $(,)?) => {
182 while let Some(Ok(e)) = $ctx.events.next() {
183 match e {
184 XmlEvent::Characters(text) => $buffer.push_str(&text),
185 XmlEvent::Whitespace(text) => $buffer.push_str(&text),
186 XmlEvent::StartElement { name, $attributes, .. } => {
187 let name = name.local_name.as_str();
188 $ctx.push_element(name);
189 match name {
190 $(
191 $p => $e,
192 )+
193 _ => {
194 $ctx.errors.push(Error::UnexpectedElement {
195 xpath: $ctx.xpath.clone(),
196 name: String::from(name),
197 });
198 consume_current_element($ctx);
199 }
200 }
201 }
202 XmlEvent::EndElement { .. } => {
203 $ctx.pop_element();
204 break;
205 }
206 _ => {}
207 }
208 }
209 };
210}
211
212pub fn parse_file(path: &std::path::Path) -> Result<(Registry, Vec<Error>), FatalError> {
215 let file = std::io::BufReader::new(std::fs::File::open(path)?);
216 let parser = xml::reader::ParserConfig::new().create_reader(file);
217 parse_xml(parser.into_iter())
218}
219
220pub fn parse_stream<T: std::io::Read>(stream: T) -> Result<(Registry, Vec<Error>), FatalError> {
222 let parser = xml::reader::ParserConfig::new().create_reader(stream);
223 parse_xml(parser.into_iter())
224}
225
226fn parse_xml<R: Read>(events: XmlEvents<R>) -> Result<(Registry, Vec<Error>), FatalError> {
227 let mut ctx = ParseCtx {
228 events,
229 xpath: String::from(""),
230 errors: Vec::new(),
231 };
232
233 let mut result = Err(FatalError::MissingRegistryElement);
234
235 {
236 let ctx = &mut ctx;
237 match_elements! {ctx,
238 "registry" => result = parse_registry(ctx),
239 }
240 }
241
242 result.map(|r| (r, ctx.errors))
243}
244
245fn parse_registry<R: Read>(ctx: &mut ParseCtx<R>) -> Result<Registry, FatalError> {
246 let mut registry = Registry(Vec::new());
247
248 match_elements! {ctx, attributes,
249 "comment" => registry.0.push(RegistryChild::Comment(parse_text_element(ctx))),
250 "vendorids" => registry.0.push(parse_vendorids(ctx, attributes)),
251 "platforms" => {
252 let mut comment = None;
253 let mut children = Vec::new();
254
255 match_attributes!{ctx, a in attributes,
256 "comment" => comment = Some(a.value),
257 }
258
259 match_elements!{ctx, attributes,
260 "platform" => if let Some(v) = parse_platform(ctx, attributes) {
261 children.push(v);
262 }
263 }
264
265 registry.0.push(RegistryChild::Platforms(Platforms { comment, children }));
266 },
267
268 "tags" => registry.0.push(parse_tags(ctx, attributes)),
269 "types" => {
270 let mut comment = None;
271 let mut children = Vec::new();
272 match_attributes!{ctx, a in attributes,
273 "comment" => comment = Some(a.value),
274 }
275 match_elements!{ctx, attributes,
276 "comment" => children.push(TypesChild::Comment(parse_text_element(ctx))),
277 "type" => children.push(parse_type(ctx, attributes))
278 }
279 registry.0.push(RegistryChild::Types(Types{
280 comment,
281 children
282 }));
283 },
284 "enums" => {
285 let mut name = None;
286 let mut kind = None;
287 let mut start = None;
288 let mut end = None;
289 let mut vendor = None;
290 let mut comment = None;
291 let mut bitwidth = None;
292 let mut children = Vec::new();
293 match_attributes!{ctx, a in attributes,
294 "name" => name = Some(a.value),
295 "type" => kind = Some(a.value),
296 "start" => start = Some(a.value),
297 "end" => end = Some(a.value),
298 "vendor" => vendor = Some(a.value),
299 "comment" => comment = Some(a.value),
300 "bitwidth" => bitwidth = Some(a.value),
301 }
302 match_elements!{ctx, attributes,
303 "enum" => if let Some(v) = parse_enum(ctx, attributes) {
304 children.push(EnumsChild::Enum(v));
305 },
306 "unused" => if let Some(v) = parse_enums_child_unused(ctx, attributes) {
307 children.push(v);
308 },
309 "comment" => children.push(EnumsChild::Comment(parse_text_element(ctx)))
310 }
311
312 let start = start.and_then(|val| parse_integer(ctx, &val));
313 let end = end.and_then(|val| parse_integer(ctx, &val));
314 let bitwidth = bitwidth.and_then(|val| parse_integer(ctx, &val)).map(|val| val as u32);
315
316 registry.0.push(RegistryChild::Enums(Enums{ name, kind, start, end, vendor, comment, children, bitwidth }));
317 },
318 "commands" => {
319 let mut comment = None;
320 let mut children = Vec::new();
321
322 match_attributes!{ctx, a in attributes,
323 "comment" => comment = Some(a.value),
324 }
325
326 match_elements!{ctx, attributes,
327 "command" => if let Some(v) = parse_command(ctx, attributes) {
328 children.push(v);
329 }
330 }
331
332 registry.0.push(RegistryChild::Commands(Commands{comment, children}));
333 },
334 "feature" => if let Some(v) = parse_feature(ctx, attributes) {
335 registry.0.push(v);
336 },
337 "extensions" => registry.0.push(parse_extensions(ctx, attributes)),
338 "formats" => registry.0.push(parse_formats(ctx)),
339 "spirvextensions" => registry.0.push(parse_spirvextensions(ctx, attributes)),
340 "spirvcapabilities" => registry.0.push(parse_spirvcapabilities(ctx, attributes)),
341 "sync" => registry.0.push(parse_sync(ctx, attributes)),
342 "videocodecs" => registry.0.push(parse_videocodecs(ctx, attributes)),
343 }
344
345 Ok(registry)
346}
347
348fn parse_vendorids<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> RegistryChild {
349 let mut comment = None;
350 let mut children = Vec::new();
351
352 match_attributes! {ctx, a in attributes,
353 "comment" => comment = Some(a.value),
354 }
355
356 match_elements! {ctx, attributes,
357 "vendorid" => if let Some(v) = parse_vendorid(ctx, attributes) {
358 children.push(v);
359 },
360 }
361
362 RegistryChild::VendorIds(VendorIds { comment, children })
363}
364
365fn parse_vendorid<R: Read>(
366 ctx: &mut ParseCtx<R>,
367 attributes: Vec<XmlAttribute>,
368) -> Option<VendorId> {
369 let mut name = None;
370 let mut comment = None;
371 let mut id = None;
372
373 match_attributes! {ctx, a in attributes,
374 "name" => name = Some(a.value),
375 "comment" => comment = Some(a.value),
376 "id" => {
377 let mut v = None;
378 if a.value.starts_with("0x") {
379 v = u32::from_str_radix(&a.value.split_at(2).1, 16).ok();
380 }
381
382 if let Some(v) = v {
383 id = Some(v);
384 } else {
385 ctx.errors.push(Error::UnexpectedAttributeValue {
386 xpath: ctx.xpath.clone(),
387 name: String::from("id"),
388 value: a.value.clone(),
389 });
390 }
391 },
392 }
393
394 consume_current_element(ctx);
395
396 unwrap_attribute!(ctx, vendorid, name);
397 unwrap_attribute!(ctx, vendorid, id);
398
399 Some(VendorId { name, comment, id })
400}
401
402fn parse_platform<R: Read>(
403 ctx: &mut ParseCtx<R>,
404 attributes: Vec<XmlAttribute>,
405) -> Option<Platform> {
406 let mut name = None;
407 let mut comment = None;
408 let mut protect = None;
409
410 match_attributes! {ctx, a in attributes,
411 "name" => name = Some(a.value),
412 "comment" => comment = Some(a.value),
413 "protect" => protect = Some(a.value),
414 }
415
416 consume_current_element(ctx);
417
418 unwrap_attribute!(ctx, platform, name);
419 unwrap_attribute!(ctx, platform, protect);
420
421 Some(Platform {
422 name,
423 comment,
424 protect,
425 })
426}
427
428fn parse_tags<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> RegistryChild {
429 let mut comment = None;
430 let mut children = Vec::new();
431
432 match_attributes! {ctx, a in attributes,
433 "comment" => comment = Some(a.value),
434 }
435
436 match_elements! {ctx, attributes,
437 "tag" => if let Some(v) = parse_tag(ctx, attributes) {
438 children.push(v);
439 },
440 }
441
442 RegistryChild::Tags(Tags { comment, children })
443}
444
445fn parse_tag<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> Option<Tag> {
446 let mut name = None;
447 let mut author = None;
448 let mut contact = None;
449
450 match_attributes! {ctx, a in attributes,
451 "name" => name = Some(a.value),
452 "author" => author = Some(a.value),
453 "contact" => contact = Some(a.value),
454 }
455
456 consume_current_element(ctx);
457
458 unwrap_attribute!(ctx, tag, name);
459 unwrap_attribute!(ctx, tag, author);
460 unwrap_attribute!(ctx, tag, contact);
461
462 Some(Tag {
463 name,
464 author,
465 contact,
466 })
467}
468
469fn parse_type<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> TypesChild {
470 let mut api = None;
471 let mut alias = None;
472 let mut requires = None;
473 let mut name = None;
474 let mut category = None;
475 let mut parent = None;
476 let mut returnedonly = None;
477 let mut structextends = None;
478 let mut allowduplicate = None;
479 let mut objtypeenum = None;
480 let mut requiredlimittype = None;
481 let mut bitvalues = None;
482 let mut comment = None;
483 let mut deprecated = None;
484
485 let mut code = String::new();
486 let mut markup = Vec::new();
487 let mut members = Vec::new();
488 let mut proto = None;
489 let mut params = Vec::new();
490
491 match_attributes! {ctx, a in attributes,
492 "api" => api = Some(a.value),
493 "alias" => alias = Some(a.value),
494 "requires" => requires = Some(a.value),
495 "name" => name = Some(a.value),
496 "category" => category = Some(a.value),
497 "parent" => parent = Some(a.value),
498 "returnedonly" => returnedonly = Some(a.value),
499 "structextends" => structextends = Some(a.value),
500 "allowduplicate" => allowduplicate = Some(a.value),
501 "objtypeenum" => objtypeenum = Some(a.value),
502 "requiredlimittype" => requiredlimittype = Some(a.value),
503 "bitvalues" => bitvalues = Some(a.value),
504 "comment" => comment = Some(a.value),
505 "deprecated" => deprecated = Some(a.value),
506 }
507
508 match_elements_combine_text! {ctx, attributes, code,
509 "member" => {
510 let mut len = None;
511 let mut altlen = None;
512 let mut externsync = None;
513 let mut optional = None;
514 let mut selector = None;
515 let mut selection = None;
516 let mut noautovalidity = None;
517 let mut validextensionstructs = None;
518 let mut values = None;
519 let mut limittype = None;
520 let mut objecttype = None;
521 let mut deprecated = None;
522 let mut api = None;
523 let mut code = String::new();
524 let mut markup = Vec::new();
525 let mut featurelink = None;
526 let mut flagsextend = None;
527 let mut flagsextendmember = None;
528 match_attributes!{ctx, a in attributes,
529 "len" => len = Some(a.value),
530 "altlen" => altlen = Some(a.value),
531 "externsync" => externsync = Some(a.value),
532 "optional" => optional = Some(a.value),
533 "selector" => selector = Some(a.value),
534 "selection" => selection = Some(a.value),
535 "noautovalidity" => noautovalidity = Some(a.value),
536 "validextensionstructs" => validextensionstructs = Some(a.value),
537 "values" => values = Some(a.value),
538 "limittype" => limittype = Some(a.value),
539 "objecttype" => objecttype = Some(a.value),
540 "deprecated" => deprecated = Some(a.value),
541 "api" => api = Some(a.value),
542 "featurelink" => featurelink = Some(a.value),
543 "flagsextend" => flagsextend = Some(a.value),
544 "flagsextendmember" => flagsextendmember = Some(a.value),
545 }
546 match_elements_combine_text!{ctx, code,
547 "type" => {
548 let text = parse_text_element(ctx);
549 code.push_str(&text);
550 markup.push(TypeMemberMarkup::Type(text));
551 },
552 "name" => {
553 let text = parse_text_element(ctx);
554 code.push_str(&text);
555 markup.push(TypeMemberMarkup::Name(text));
556 },
557 "enum" => {
558 let text = parse_text_element(ctx);
559 code.push_str(&text);
560 markup.push(TypeMemberMarkup::Enum(text));
561 },
562 "comment" => {
563 let text = parse_text_element(ctx);
564 markup.push(TypeMemberMarkup::Comment(text));
565 },
566 }
567 members.push(TypeMember::Definition(TypeMemberDefinition {
568 len,
569 altlen,
570 externsync,
571 optional,
572 selector,
573 selection,
574 noautovalidity,
575 validextensionstructs,
576 values,
577 limittype,
578 objecttype,
579 deprecated,
580 api,
581 code,
582 markup,
583 featurelink,
584 flagsextend,
585 flagsextendmember,
586 }))
587 },
588 "comment" => members.push(TypeMember::Comment(parse_text_element(ctx))),
589 "name" => {
590 let text = parse_text_element(ctx);
591 code.push_str(&text);
592 markup.push(TypeCodeMarkup::Name(text));
593 },
594 "type" => {
595 let text = parse_text_element(ctx);
596 code.push_str(&text);
597 markup.push(TypeCodeMarkup::Type(text));
598 },
599 "apientry" => {
600 let text = parse_text_element(ctx);
601 code.push_str(&text);
602 markup.push(TypeCodeMarkup::ApiEntry(text));
603 },
604 "proto" => {
605 let mut name = None;
606 let mut type_name = None;
607 let mut code = String::new();
608 match_elements_combine_text! {ctx, code,
609 "type" => {
610 let text = parse_text_element(ctx);
611 code.push_str(&text);
612 type_name = Some(text);
613 },
614 "name" => {
615 let text = parse_text_element(ctx);
616 code.push_str("(VKAPI_PTR *");
617 code.push_str(&text);
618 code.push_str(")");
619 markup.push(TypeCodeMarkup::Name(text.clone())); name = Some(text);
621 },
622 };
623 if let Some(name) = name {
624 proto = Some(FuncpointerProtoMarkup {
625 type_name,
626 name,
627 code,
628 });
629 } else {
630 ctx.errors.push(Error::MissingElement {
631 xpath: ctx.xpath.clone(),
632 name: String::from("name"),
633 });
634 }
635 },
636 "param" => {
637 let mut param = String::new();
638 if let Some(p) = parse_name_with_type(ctx, &mut param) {
639 if let Some(ref t) = p.type_name {
640 markup.push(TypeCodeMarkup::Type(t.clone())); }
642 params.push(p);
643 }
644 }
645 }
646
647 if let Some(ref proto) = proto {
648 code.clear();
650 code.push_str("typedef ");
651 code.push_str(&proto.code);
652 code.push_str("(");
653 if params.is_empty() {
654 code.push_str("void");
655 } else {
656 let mut is_first = true;
657 for param in ¶ms {
658 if is_first {
659 is_first = false;
660 } else {
661 code.push_str(", ");
662 }
663 code.push_str(¶m.code);
664 }
665 }
666 code.push_str(");");
667 }
668
669 TypesChild::Type(Type {
670 api,
671 alias,
672 requires,
673 name,
674 category,
675 parent,
676 returnedonly,
677 structextends,
678 allowduplicate,
679 objtypeenum,
680 requiredlimittype,
681 bitvalues,
682 deprecated,
683 comment,
684 spec: if members.len() > 0 {
685 TypeSpec::Members(members)
686 } else if let Some(proto) = proto {
687 TypeSpec::Funcpointer(FuncpointerCode {
688 code,
689 markup,
690 proto,
691 params,
692 })
693 } else if code.len() > 0 {
694 TypeSpec::Code(TypeCode { code, markup })
695 } else {
696 TypeSpec::None
697 },
698 })
699}
700
701fn parse_command<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> Option<Command> {
702 let mut name = None;
703 let mut alias = None;
704 let mut tasks = None;
705 let mut queues = None;
706 let mut successcodes = None;
707 let mut errorcodes = None;
708 let mut renderpass = None;
709 let mut videocoding = None;
710 let mut conditionalrendering = None;
711 let mut cmdbufferlevel = None;
712 let mut allownoqueues = None;
713 let mut pipeline = None;
714 let mut comment = None;
715 let mut api = None;
716 let mut export = None;
717
718 match_attributes! {ctx, a in attributes,
719 "name" => name = Some(a.value),
720 "alias" => alias = Some(a.value),
721 "tasks" => tasks = Some(a.value),
722 "queues" => queues = Some(a.value),
723 "successcodes" => successcodes = Some(a.value),
724 "errorcodes" => errorcodes = Some(a.value),
725 "renderpass" => renderpass = Some(a.value),
726 "videocoding" => videocoding = Some(a.value),
727 "conditionalrendering" => conditionalrendering = Some(a.value),
728 "cmdbufferlevel" => cmdbufferlevel = Some(a.value),
729 "allownoqueues" => allownoqueues = Some(a.value),
730 "pipeline" => pipeline = Some(a.value),
731 "comment" => comment = Some(a.value),
732 "api" => api = Some(a.value),
733 "export" => export = Some(a.value),
734 }
735
736 if let Some(alias) = alias {
737 unwrap_attribute!(ctx, command, name);
738 consume_current_element(ctx);
739 Some(Command::Alias { alias, name })
740 } else {
741 let mut code = String::new();
742 let mut proto = None;
743 let mut params = Vec::new();
744 let mut description = None;
745 let mut implicitexternsyncparams = Vec::new();
746
747 match_elements! {ctx, attributes,
748 "proto" => {
749 proto = parse_name_with_type(ctx, &mut code);
750 code.push('(');
751 },
752
753 "param" => {
754 let mut len = None;
755 let mut altlen = None;
756 let mut externsync = None;
757 let mut optional = None;
758 let mut noautovalidity = None;
759 let mut objecttype = None;
760 let mut validstructs = None;
761 let mut stride = None;
762 let mut api = None;
763
764 match_attributes!{ctx, a in attributes,
765 "len" => len = Some(a.value),
766 "altlen" => altlen = Some(a.value),
767 "externsync" => externsync = Some(a.value),
768 "optional" => optional = Some(a.value),
769 "noautovalidity" => noautovalidity = Some(a.value),
770 "objecttype" => objecttype = Some(a.value),
771 "validstructs" => validstructs = Some(a.value),
772 "stride" => stride = Some(a.value),
773 "api" => api = Some(a.value),
774 }
775
776 let validstructs = validstructs.map_or(
777 Default::default(),
778 |structs| structs.split(',').map(|s| s.to_owned()).collect()
779 );
780
781 if !params.is_empty() {
782 code.push_str(", ");
783 }
784 if let Some(definition) = parse_name_with_type(ctx, &mut code) {
785 params.push(CommandParam {
786 len,
787 altlen,
788 externsync,
789 optional,
790 noautovalidity,
791 objecttype,
792 definition,
793 validstructs,
794 stride,
795 api,
796 });
797 }
798 },
799
800 "alias" => {
801 match_attributes!{ctx, a in attributes,
802 "name" => alias = Some(a.value),
803 }
804 consume_current_element(ctx);
805 },
806
807 "description" => description = Some(parse_text_element(ctx)),
808 "implicitexternsyncparams" => {
809 match_elements!{ctx,
810 "param" => implicitexternsyncparams.push(parse_text_element(ctx)),
811 }
812 }
813 }
814 code.push_str(");");
815
816 let proto = if let Some(v) = proto {
817 v
818 } else {
819 ctx.errors.push(Error::MissingElement {
820 xpath: ctx.xpath.clone(),
821 name: String::from("proto"),
822 });
823 return None;
824 };
825
826 let conditionalrendering = if let Some(v) = conditionalrendering {
827 match v.as_str() {
828 "true" => Some(true),
829 "false" => Some(false),
830 _ => {
831 ctx.errors.push(Error::UnexpectedAttributeValue {
832 xpath: ctx.xpath.clone(),
833 name: String::from("conditionalrendering"),
834 value: v,
835 });
836 return None;
837 }
838 }
839 } else {
840 None
841 };
842
843 Some(Command::Definition(CommandDefinition {
844 tasks,
845 queues,
846 successcodes,
847 errorcodes,
848 renderpass,
849 videocoding,
850 conditionalrendering,
851 cmdbufferlevel,
852 allownoqueues,
853 pipeline,
854 comment,
855 proto,
856 params,
857 alias,
858 description,
859 implicitexternsyncparams,
860 api,
861 export,
862 code,
863 }))
864 }
865}
866
867fn parse_enum<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> Option<Enum> {
868 let mut name = None;
869 let mut comment = None;
870 let mut type_suffix = None;
871 let mut api = None;
872 let mut extends = None;
873 let mut value = None;
874 let mut bitpos = None;
875 let mut extnumber = None;
876 let mut offset = None;
877 let mut positive = true;
878 let mut protect = None;
879 let mut alias = None;
880 let mut deprecated = None;
881
882 match_attributes! {ctx, a in attributes,
883 "name" => name = Some(a.value),
884 "comment" => comment = Some(a.value),
885 "type" => type_suffix = Some(a.value),
886 "api" => api = Some(a.value),
887 "extends" => extends = Some(a.value),
888 "value" => value = Some(a.value),
889 "offset" => offset = Some(a.value),
890 "dir" => {
891 if a.value.as_str() == "-" {
892 positive = false;
893 } else {
894 ctx.errors.push(Error::UnexpectedAttributeValue {
895 xpath: ctx.xpath.clone(),
896 name: String::from("dir"),
897 value: a.value
898 });
899 }
900 },
901 "bitpos" => bitpos = Some(a.value),
902 "extnumber" => extnumber = Some(a.value),
903 "protect" => protect = Some(a.value),
904 "alias" => alias = Some(a.value),
905 "deprecated" => deprecated = Some(a.value),
906 }
907
908 unwrap_attribute!(ctx, enum, name);
909
910 let mut count = 0;
911 if offset.is_some() {
912 count += 1;
913 }
914 if bitpos.is_some() {
915 count += 1;
916 }
917 if value.is_some() {
918 count += 1;
919 }
920 if alias.is_some() {
921 count += 1;
922 }
923 if count > 1 {
924 ctx.errors.push(Error::SchemaViolation {
925 xpath: ctx.xpath.clone(),
926 desc: format!(
927 "Unable to determine correct specification of enum: offset={:?}, bitpos={:?}, value={:?}, alias={:?}",
928 offset, bitpos, value, alias
929 ),
930 });
931 consume_current_element(ctx);
932 return None;
933 }
934
935 let spec = if let Some(alias) = alias {
936 EnumSpec::Alias { alias, extends }
937 } else if let Some(offset) = offset {
938 let offset = match parse_integer(ctx, &offset) {
939 Some(v) => v,
940 None => {
941 consume_current_element(ctx);
942 return None;
943 }
944 };
945 if let Some(extends) = extends {
946 EnumSpec::Offset {
947 offset,
948 extends,
949 extnumber: match extnumber {
950 Some(extnumber) => parse_integer(ctx, &extnumber),
951 None => None,
952 },
953 dir: positive,
954 }
955 } else {
956 ctx.errors.push(Error::SchemaViolation {
957 xpath: ctx.xpath.clone(),
958 desc: String::from("Missing extends on enum with offset spec."),
959 });
960 consume_current_element(ctx);
961 return None;
962 }
963 } else if let Some(bitpos) = bitpos {
964 let bitpos = match parse_integer(ctx, &bitpos) {
965 Some(v) => v,
966 None => {
967 consume_current_element(ctx);
968 return None;
969 }
970 };
971 EnumSpec::Bitpos { bitpos, extends }
972 } else if let Some(value) = value {
973 EnumSpec::Value { value, extends }
974 } else {
975 EnumSpec::None
976 };
977
978 consume_current_element(ctx);
979
980 Some(Enum {
981 name,
982 comment,
983 type_suffix,
984 api,
985 protect,
986 deprecated,
987 spec,
988 })
989}
990
991fn parse_enums_child_unused<R: Read>(
992 ctx: &mut ParseCtx<R>,
993 attributes: Vec<XmlAttribute>,
994) -> Option<EnumsChild> {
995 let mut start = None;
996 let mut end = None;
997 let mut vendor = None;
998 let mut comment = None;
999 match_attributes! {ctx, a in attributes,
1000 "start" => start = Some(a.value),
1001 "end" => end = Some(a.value),
1002 "vendor" => vendor = Some(a.value),
1003 "comment" => comment = Some(a.value),
1004 }
1005 consume_current_element(ctx);
1006 unwrap_attribute!(ctx, unused, start);
1007 let start = match parse_integer(ctx, &start) {
1008 Some(v) => v,
1009 None => return None,
1010 };
1011 let end = end.and_then(|val| parse_integer(ctx, &val));
1012 Some(EnumsChild::Unused(Unused {
1013 start,
1014 end,
1015 vendor,
1016 comment,
1017 }))
1018}
1019
1020fn parse_feature<R: Read>(
1021 ctx: &mut ParseCtx<R>,
1022 attributes: Vec<XmlAttribute>,
1023) -> Option<RegistryChild> {
1024 let mut api = None;
1025 let mut apitype = None;
1026 let mut name = None;
1027 let mut number = None;
1028 let mut depends = None;
1029 let mut protect = None;
1030 let mut comment = None;
1031 let mut children = Vec::new();
1032
1033 match_attributes! {ctx, a in attributes,
1034 "api" => api = Some(a.value),
1035 "apitype" => apitype = Some(a.value),
1036 "name" => name = Some(a.value),
1037 "number" => number = Some(a.value),
1038 "depends" => depends = Some(a.value),
1039 "protect" => protect = Some(a.value),
1040 "comment" => comment = Some(a.value),
1041 }
1042
1043 match_elements! {ctx, attributes,
1044 "require" => children.push(parse_extension_item_require(ctx, attributes)),
1045 "deprecate" => if let Some(child) = parse_extension_item_deprecate(ctx, attributes) { children.push(child) },
1046 "remove" => children.push(parse_extension_item_remove(ctx, attributes)),
1047 }
1048
1049 unwrap_attribute!(ctx, feature, api);
1050 unwrap_attribute!(ctx, feature, name);
1051
1052 Some(RegistryChild::Feature(Feature {
1053 api,
1054 apitype,
1055 name,
1056 number,
1057 depends,
1058 protect,
1059 comment,
1060 children,
1061 }))
1062}
1063
1064fn parse_extensions<R: Read>(
1065 ctx: &mut ParseCtx<R>,
1066 attributes: Vec<XmlAttribute>,
1067) -> RegistryChild {
1068 let mut comment = None;
1069 let mut children = Vec::new();
1070
1071 match_attributes! {ctx, a in attributes,
1072 "comment" => comment = Some(a.value),
1073 }
1074
1075 match_elements! {ctx, attributes,
1076 "extension" => if let Some(v) = parse_extension(ctx, attributes) {
1077 children.push(v);
1078 },
1079 }
1080
1081 RegistryChild::Extensions(Extensions { comment, children })
1082}
1083
1084fn parse_extension<R: Read>(
1085 ctx: &mut ParseCtx<R>,
1086 attributes: Vec<XmlAttribute>,
1087) -> Option<Extension> {
1088 let mut name = None;
1089 let mut comment = None;
1090 let mut number = None;
1091 let mut protect = None;
1092 let mut platform = None;
1093 let mut author = None;
1094 let mut contact = None;
1095 let mut ext_type = None;
1096 let mut requires = None;
1097 let mut requires_core = None;
1098 let mut supported = None;
1099 let mut ratified = None;
1100 let mut deprecatedby = None;
1101 let mut promotedto = None;
1102 let mut obsoletedby = None;
1103 let mut provisional = None;
1104 let mut specialuse = None;
1105 let mut sortorder = None;
1106 let mut depends = None;
1107 let mut nofeatures = None;
1108 let mut children = Vec::new();
1109
1110 match_attributes! {ctx, a in attributes,
1111 "name" => name = Some(a.value),
1112 "comment" => comment = Some(a.value),
1113 "number" => number = Some(a.value),
1114 "protect" => protect = Some(a.value),
1115 "platform" => platform = Some(a.value),
1116 "author" => author = Some(a.value),
1117 "contact" => contact = Some(a.value),
1118 "type" => ext_type = Some(a.value),
1119 "requires" => requires = Some(a.value),
1120 "requiresCore" => requires_core = Some(a.value),
1121 "supported" => supported = Some(a.value),
1122 "ratified" => ratified = Some(a.value),
1123 "deprecatedby" => deprecatedby = Some(a.value),
1124 "promotedto" => promotedto = Some(a.value),
1125 "provisional" => provisional = Some(a.value),
1126 "obsoletedby" => obsoletedby = Some(a.value),
1127 "specialuse" => specialuse = Some(a.value),
1128 "sortorder" => sortorder = Some(a.value),
1129 "depends" => depends = Some(a.value),
1130 "nofeatures" => nofeatures = Some(a.value),
1131 }
1132
1133 let number = match number {
1134 Some(text) => parse_integer(ctx, &text),
1135 None => None,
1136 };
1137
1138 let provisional = match provisional.as_deref() {
1139 Some("true") => true,
1140 Some("false") => false,
1141 Some(value) => {
1142 ctx.errors.push(Error::SchemaViolation {
1143 xpath: ctx.xpath.clone(),
1144 desc: format!("Unexpected value of 'provisional' attribute: {}", value),
1145 });
1146 false
1147 }
1148 None => false,
1149 };
1150 let nofeatures = match nofeatures.as_deref() {
1151 Some("true") => true,
1152 Some("false") => false,
1153 Some(value) => {
1154 ctx.errors.push(Error::SchemaViolation {
1155 xpath: ctx.xpath.clone(),
1156 desc: format!("Unexpected value of 'nofeatures' attribute: {}", value),
1157 });
1158 false
1159 }
1160 None => false,
1161 };
1162
1163 let sortorder = match sortorder {
1164 Some(text) => parse_integer(ctx, &text),
1165 None => None,
1166 };
1167
1168 unwrap_attribute!(ctx, extension, name);
1169
1170 match_elements! {ctx, attributes,
1171 "require" => children.push(parse_extension_item_require(ctx, attributes)),
1172 "deprecate" => if let Some(child) = parse_extension_item_deprecate(ctx, attributes) { children.push(child) },
1173 "remove" => children.push(parse_extension_item_remove(ctx, attributes)),
1174 }
1175
1176 Some(Extension {
1177 name,
1178 comment,
1179 number,
1180 protect,
1181 platform,
1182 author,
1183 contact,
1184 ext_type,
1185 requires,
1186 requires_core,
1187 supported,
1188 ratified,
1189 deprecatedby,
1190 promotedto,
1191 obsoletedby,
1192 provisional,
1193 specialuse,
1194 sortorder,
1195 depends,
1196 nofeatures,
1197 children,
1198 })
1199}
1200
1201fn parse_extension_item_require<R: Read>(
1202 ctx: &mut ParseCtx<R>,
1203 attributes: Vec<XmlAttribute>,
1204) -> ExtensionChild {
1205 let mut api = None;
1206 let mut profile = None;
1207 let mut extension = None;
1208 let mut feature = None;
1209 let mut comment = None;
1210 let mut depends = None;
1211 let mut items = Vec::new();
1212
1213 match_attributes! {ctx, a in attributes,
1214 "api" => api = Some(a.value),
1215 "profile" => profile = Some(a.value),
1216 "extension" => extension = Some(a.value),
1217 "feature" => feature = Some(a.value),
1218 "comment" => comment = Some(a.value),
1219 "depends" => depends = Some(a.value),
1220 }
1221
1222 while let Some(Ok(e)) = ctx.events.next() {
1223 match e {
1224 XmlEvent::StartElement {
1225 name, attributes, ..
1226 } => {
1227 let name = name.local_name.as_str();
1228 ctx.push_element(name);
1229 if let Some(v) = parse_interface_item(ctx, name, attributes) {
1230 items.push(v);
1231 }
1232 }
1233 XmlEvent::EndElement { .. } => {
1234 ctx.pop_element();
1235 break;
1236 }
1237 _ => {}
1238 }
1239 }
1240
1241 ExtensionChild::Require {
1242 api,
1243 profile,
1244 extension,
1245 feature,
1246 comment,
1247 depends,
1248 items,
1249 }
1250}
1251
1252fn parse_extension_item_deprecate<R: Read>(
1253 ctx: &mut ParseCtx<R>,
1254 attributes: Vec<XmlAttribute>,
1255) -> Option<ExtensionChild> {
1256 let mut api = None;
1257 let mut profile = None;
1258 let mut comment = None;
1259 let mut explanationlink = None;
1260 let mut items = Vec::new();
1261
1262 match_attributes! {ctx, a in attributes,
1263 "api" => api = Some(a.value),
1264 "profile" => profile = Some(a.value),
1265 "comment" => comment = Some(a.value),
1266 "explanationlink" => explanationlink = Some(a.value),
1267 }
1268
1269 unwrap_attribute!(ctx, deprecate, explanationlink);
1270
1271 while let Some(Ok(e)) = ctx.events.next() {
1272 match e {
1273 XmlEvent::StartElement {
1274 name, attributes, ..
1275 } => {
1276 let name = name.local_name.as_str();
1277 ctx.push_element(name);
1278 if let Some(v) = parse_interface_item(ctx, name, attributes) {
1279 items.push(v);
1280 }
1281 }
1282 XmlEvent::EndElement { .. } => {
1283 ctx.pop_element();
1284 break;
1285 }
1286 _ => {}
1287 }
1288 }
1289
1290 Some(ExtensionChild::Deprecate {
1291 api,
1292 profile,
1293 comment,
1294 explanationlink,
1295 items,
1296 })
1297}
1298
1299fn parse_extension_item_remove<R: Read>(
1300 ctx: &mut ParseCtx<R>,
1301 attributes: Vec<XmlAttribute>,
1302) -> ExtensionChild {
1303 let mut api = None;
1304 let mut profile = None;
1305 let mut comment = None;
1306 let mut reasonlink = None;
1307 let mut items = Vec::new();
1308
1309 match_attributes! {ctx, a in attributes,
1310 "api" => api = Some(a.value),
1311 "profile" => profile = Some(a.value),
1312 "comment" => comment = Some(a.value),
1313 "reasonlink" => reasonlink = Some(a.value),
1314 }
1315
1316 while let Some(Ok(e)) = ctx.events.next() {
1317 match e {
1318 XmlEvent::StartElement {
1319 name, attributes, ..
1320 } => {
1321 let name = name.local_name.as_str();
1322 ctx.push_element(name);
1323 if let Some(v) = parse_interface_item(ctx, name, attributes) {
1324 items.push(v);
1325 }
1326 }
1327 XmlEvent::EndElement { .. } => {
1328 ctx.pop_element();
1329 break;
1330 }
1331 _ => {}
1332 }
1333 }
1334
1335 ExtensionChild::Remove {
1336 api,
1337 profile,
1338 comment,
1339 reasonlink,
1340 items,
1341 }
1342}
1343
1344fn parse_interface_item<R: Read>(
1345 ctx: &mut ParseCtx<R>,
1346 name: &str,
1347 attributes: Vec<XmlAttribute>,
1348) -> Option<InterfaceItem> {
1349 match name {
1350 "comment" => Some(InterfaceItem::Comment(parse_text_element(ctx))),
1351 "type" => {
1352 let mut name = None;
1353 let mut comment = None;
1354 let mut supersededby = None;
1355 match_attributes! {ctx, a in attributes,
1356 "name" => name = Some(a.value),
1357 "comment" => comment = Some(a.value),
1358 "supersededby" => supersededby = Some(a.value),
1359 }
1360 unwrap_attribute!(ctx, type, name);
1361 consume_current_element(ctx);
1362 Some(InterfaceItem::Type {
1363 name,
1364 comment,
1365 supersededby,
1366 })
1367 }
1368 "enum" => parse_enum(ctx, attributes).map(|v| InterfaceItem::Enum(v)),
1369 "command" => {
1370 let mut name = None;
1371 let mut comment = None;
1372 let mut supersededby = None;
1373 match_attributes! {ctx, a in attributes,
1374 "name" => name = Some(a.value),
1375 "comment" => comment = Some(a.value),
1376 "supersededby" => supersededby = Some(a.value),
1377 }
1378 unwrap_attribute!(ctx, type, name);
1379 consume_current_element(ctx);
1380 Some(InterfaceItem::Command {
1381 name,
1382 comment,
1383 supersededby,
1384 })
1385 }
1386 "feature" => {
1387 let mut name = None;
1388 let mut struct_ = None;
1389 let mut comment = None;
1390 match_attributes! {ctx, a in attributes,
1391 "name" => name = Some(a.value),
1392 "struct" => struct_ = Some(a.value),
1393 "comment" => comment = Some(a.value),
1394 }
1395 unwrap_attribute!(ctx, type, name);
1396 unwrap_attribute!(ctx, type, struct_);
1397 consume_current_element(ctx);
1398 Some(InterfaceItem::Feature {
1399 name,
1400 struct_,
1401 comment,
1402 })
1403 }
1404 _ => {
1405 ctx.errors.push(Error::UnexpectedElement {
1406 xpath: ctx.xpath.clone(),
1407 name: String::from(name),
1408 });
1409 return None;
1410 }
1411 }
1412}
1413
1414fn parse_formats<R: Read>(ctx: &mut ParseCtx<R>) -> RegistryChild {
1415 let mut children = Vec::new();
1416
1417 match_elements! {ctx, attributes,
1418 "format" => if let Some(v) = parse_format(ctx, attributes) {
1419 children.push(v);
1420 },
1421 }
1422
1423 RegistryChild::Formats(Formats {
1424 comment: None,
1425 children,
1426 })
1427}
1428
1429#[allow(non_snake_case)]
1430fn parse_format<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> Option<Format> {
1431 let mut name = None;
1432 let mut class = None;
1433 let mut blockSize = None;
1434 let mut texelsPerBlock = None;
1435 let mut blockExtent = None;
1436 let mut packed = None;
1437 let mut compressed = None;
1438 let mut chroma = None;
1439 let mut children = Vec::new();
1440
1441 match_attributes! {ctx, a in attributes,
1442 "name" => name = Some(a.value),
1443 "class" => class = Some(a.value),
1444 "blockSize" => blockSize = Some(a.value),
1445 "texelsPerBlock" => texelsPerBlock = Some(a.value),
1446 "blockExtent" => blockExtent = Some(a.value),
1447 "packed" => packed = Some(a.value),
1448 "compressed" => compressed = Some(a.value),
1449 "chroma" => chroma = Some(a.value),
1450 }
1451
1452 unwrap_attribute!(ctx, extension, name);
1453 unwrap_attribute!(ctx, extension, class);
1454 unwrap_attribute!(ctx, extension, blockSize);
1455 unwrap_attribute!(ctx, extension, texelsPerBlock);
1456
1457 match_elements! {ctx, attributes,
1458 "component" => if let Some(v) = parse_format_component(ctx, attributes) { children.push(v); },
1459 "plane" => if let Some(v) = parse_format_plane(ctx, attributes) { children.push(v); },
1460 "spirvimageformat" => if let Some(v) = parse_format_spirvimageformat(ctx, attributes) { children.push(v); },
1461 }
1462
1463 let blockSize: Option<u8> = parse_int_attribute(ctx, blockSize, "blockSize");
1464 let texelsPerBlock: Option<u8> = parse_int_attribute(ctx, texelsPerBlock, "texelsPerBlock");
1465 let packed = packed.map(|v| -> Option<u8> { parse_int_attribute(ctx, v, "packed") });
1466
1467 let blockSize = match blockSize {
1468 Some(v) => v,
1469 None => return None,
1470 };
1471
1472 let texelsPerBlock = match texelsPerBlock {
1473 Some(v) => v,
1474 None => return None,
1475 };
1476
1477 let packed = match packed {
1478 Some(Some(v)) => Some(v),
1479 Some(None) => return None, None => None,
1481 };
1482
1483 Some(Format {
1484 name,
1485 class,
1486 blockSize,
1487 texelsPerBlock,
1488 blockExtent,
1489 packed,
1490 compressed,
1491 chroma,
1492 children,
1493 })
1494}
1495
1496#[allow(non_snake_case)]
1497fn parse_format_component<R: Read>(
1498 ctx: &mut ParseCtx<R>,
1499 attributes: Vec<XmlAttribute>,
1500) -> Option<FormatChild> {
1501 let mut name = None;
1502 let mut bits = None;
1503 let mut numericFormat = None;
1504 let mut planeIndex = None;
1505
1506 match_attributes! {ctx, a in attributes,
1507 "name" => name = Some(a.value),
1508 "bits" => bits = Some(a.value),
1509 "numericFormat" => numericFormat = Some(a.value),
1510 "planeIndex" => planeIndex = Some(a.value),
1511 }
1512
1513 unwrap_attribute!(ctx, extension, name);
1514 unwrap_attribute!(ctx, extension, bits);
1515 unwrap_attribute!(ctx, extension, numericFormat);
1516
1517 consume_current_element(ctx);
1518
1519 let planeIndex =
1520 planeIndex.map(|v| -> Option<u8> { parse_int_attribute(ctx, v, "planeIndex") });
1521
1522 let planeIndex = match planeIndex {
1523 Some(Some(v)) => Some(v),
1524 Some(None) => return None, None => None,
1526 };
1527
1528 Some(FormatChild::Component {
1529 name,
1530 bits,
1531 numericFormat,
1532 planeIndex,
1533 })
1534}
1535
1536#[allow(non_snake_case)]
1537fn parse_format_plane<R: Read>(
1538 ctx: &mut ParseCtx<R>,
1539 attributes: Vec<XmlAttribute>,
1540) -> Option<FormatChild> {
1541 let mut index = None;
1542 let mut widthDivisor = None;
1543 let mut heightDivisor = None;
1544 let mut compatible = None;
1545
1546 match_attributes! {ctx, a in attributes,
1547 "index" => index = Some(a.value),
1548 "widthDivisor" => widthDivisor = Some(a.value),
1549 "heightDivisor" => heightDivisor = Some(a.value),
1550 "compatible" => compatible = Some(a.value),
1551 }
1552
1553 unwrap_attribute!(ctx, extension, index);
1554 unwrap_attribute!(ctx, extension, widthDivisor);
1555 unwrap_attribute!(ctx, extension, heightDivisor);
1556 unwrap_attribute!(ctx, extension, compatible);
1557
1558 consume_current_element(ctx);
1559
1560 let index: Option<u8> = parse_int_attribute(ctx, index, "index");
1561 let widthDivisor: Option<u8> = parse_int_attribute(ctx, widthDivisor, "widthDivisor");
1562 let heightDivisor: Option<u8> = parse_int_attribute(ctx, heightDivisor, "heightDivisor");
1563
1564 let index = match index {
1565 Some(v) => v,
1566 None => return None,
1567 };
1568
1569 let widthDivisor = match widthDivisor {
1570 Some(v) => v,
1571 None => return None,
1572 };
1573
1574 let heightDivisor = match heightDivisor {
1575 Some(v) => v,
1576 None => return None,
1577 };
1578
1579 Some(FormatChild::Plane {
1580 index,
1581 widthDivisor,
1582 heightDivisor,
1583 compatible,
1584 })
1585}
1586
1587fn parse_format_spirvimageformat<R: Read>(
1588 ctx: &mut ParseCtx<R>,
1589 attributes: Vec<XmlAttribute>,
1590) -> Option<FormatChild> {
1591 let mut name = None;
1592
1593 match_attributes! {ctx, a in attributes,
1594 "name" => name = Some(a.value),
1595 }
1596
1597 unwrap_attribute!(ctx, extension, name);
1598
1599 consume_current_element(ctx);
1600
1601 Some(FormatChild::SpirvImageFormat { name })
1602}
1603
1604fn parse_spirvextensions<R: Read>(
1605 ctx: &mut ParseCtx<R>,
1606 attributes: Vec<XmlAttribute>,
1607) -> RegistryChild {
1608 let mut comment = None;
1609 let mut children = Vec::new();
1610
1611 match_attributes! {ctx, a in attributes,
1612 "comment" => comment = Some(a.value),
1613 }
1614
1615 match_elements! {ctx, attributes,
1616 "spirvextension" => if let Some(v) = parse_spirvextension(ctx, attributes) {
1617 children.push(v);
1618 },
1619 }
1620
1621 RegistryChild::SpirvExtensions(SpirvExtensions { comment, children })
1622}
1623
1624fn parse_spirvextension<R: Read>(
1625 ctx: &mut ParseCtx<R>,
1626 attributes: Vec<XmlAttribute>,
1627) -> Option<SpirvExtension> {
1628 let mut name = None;
1629 let mut enables = Vec::new();
1630
1631 match_attributes! {ctx, a in attributes,
1632 "name" => name = Some(a.value),
1633 }
1634
1635 match_elements! {ctx, attributes,
1636 "enable" => if let Some(v) = parse_enable(ctx, attributes) {
1637 enables.push(v);
1638 },
1639 }
1640
1641 unwrap_attribute!(ctx, spirvextension, name);
1642
1643 Some(SpirvExtension { name, enables })
1644}
1645
1646fn parse_spirvcapabilities<R: Read>(
1647 ctx: &mut ParseCtx<R>,
1648 attributes: Vec<XmlAttribute>,
1649) -> RegistryChild {
1650 let mut comment = None;
1651 let mut children = Vec::new();
1652
1653 match_attributes! {ctx, a in attributes,
1654 "comment" => comment = Some(a.value),
1655 }
1656
1657 match_elements! {ctx, attributes,
1658 "spirvcapability" => if let Some(v) = parse_spirvcapability(ctx, attributes) {
1659 children.push(v);
1660 },
1661 }
1662
1663 RegistryChild::SpirvCapabilities(SpirvCapabilities { comment, children })
1664}
1665
1666fn parse_spirvcapability<R: Read>(
1667 ctx: &mut ParseCtx<R>,
1668 attributes: Vec<XmlAttribute>,
1669) -> Option<SpirvCapability> {
1670 let mut name = None;
1671 let mut enables = Vec::new();
1672
1673 match_attributes! {ctx, a in attributes,
1674 "name" => name = Some(a.value),
1675 }
1676
1677 match_elements! {ctx, attributes,
1678 "enable" => if let Some(v) = parse_enable(ctx, attributes) {
1679 enables.push(v);
1680 },
1681 }
1682
1683 unwrap_attribute!(ctx, spirvcapability, name);
1684
1685 Some(SpirvCapability { name, enables })
1686}
1687
1688fn parse_enable<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> Option<Enable> {
1689 let mut version = None;
1690 let mut extension = None;
1691 let mut struct_ = None;
1692 let mut feature = None;
1693 let mut requires = None;
1694 let mut alias = None;
1695 let mut property = None;
1696 let mut member = None;
1697 let mut value = None;
1698
1699 match_attributes! {ctx, a in attributes,
1700 "version" => version = Some(a.value),
1701 "extension" => extension = Some(a.value),
1702 "struct" => struct_ = Some(a.value),
1703 "feature" => feature = Some(a.value),
1704 "requires" => requires = Some(a.value),
1705 "alias" => alias = Some(a.value),
1706 "property" => property = Some(a.value),
1707 "member" => member = Some(a.value),
1708 "value" => value = Some(a.value),
1709 }
1710
1711 consume_current_element(ctx);
1712
1713 if let Some(version) = version {
1714 Some(Enable::Version(version))
1715 } else if let Some(extension) = extension {
1716 Some(Enable::Extension(extension))
1717 } else if let Some(struct_) = struct_ {
1718 unwrap_attribute!(ctx, enable, feature);
1719 Some(Enable::Feature(FeatureEnable {
1720 struct_,
1721 feature,
1722 requires,
1723 alias,
1724 }))
1725 } else if let Some(property) = property {
1726 unwrap_attribute!(ctx, enable, member);
1727 unwrap_attribute!(ctx, enable, value);
1728 Some(Enable::Property(PropertyEnable {
1729 property,
1730 member,
1731 value,
1732 requires,
1733 }))
1734 } else {
1735 unimplemented!();
1736 }
1737}
1738
1739fn parse_sync<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> RegistryChild {
1740 let mut comment = None;
1741 let mut children = Vec::new();
1742
1743 match_attributes! {ctx, a in attributes,
1744 "comment" => comment = Some(a.value),
1745 }
1746
1747 match_elements! {ctx, attributes,
1748 "syncstage" => if let Some(v) = parse_syncstage(ctx, attributes) {
1749 children.push(v);
1750 },
1751 "syncaccess" => if let Some(v) = parse_syncaccess(ctx, attributes) {
1752 children.push(v);
1753 },
1754 "syncpipeline" => if let Some(v) = parse_syncpipeline(ctx, attributes) {
1755 children.push(v);
1756 },
1757 }
1758
1759 RegistryChild::Sync(Sync { comment, children })
1760}
1761
1762fn parse_syncsupport<R: Read>(
1763 ctx: &mut ParseCtx<R>,
1764 attributes: Vec<XmlAttribute>,
1765) -> Option<SyncSupport> {
1766 let mut queues = None;
1767 let mut stage = None;
1768 match_attributes! { ctx, a in attributes,
1769 "queues" => queues = Some(a.value),
1770 "stage" => stage = Some(a.value),
1771 }
1772 consume_current_element(ctx);
1773 Some(SyncSupport { queues, stage })
1774}
1775
1776fn parse_syncequivalent<R: Read>(
1777 ctx: &mut ParseCtx<R>,
1778 attributes: Vec<XmlAttribute>,
1779) -> Option<SyncEquivalent> {
1780 let mut stage = None;
1781 let mut access = None;
1782 match_attributes! { ctx, a in attributes,
1783 "stage" => stage = Some(a.value),
1784 "access" => access = Some(a.value),
1785 }
1786 consume_current_element(ctx);
1787 Some(SyncEquivalent { stage, access })
1788}
1789
1790fn parse_syncstage<R: Read>(
1791 ctx: &mut ParseCtx<R>,
1792 attributes: Vec<XmlAttribute>,
1793) -> Option<SyncChild> {
1794 let mut name = None;
1795 let mut alias = None;
1796 let mut syncsupport = None;
1797 let mut syncequivalent = None;
1798
1799 match_attributes! { ctx, a in attributes,
1800 "name" => name = Some(a.value),
1801 "alias" => alias = Some(a.value),
1802 }
1803
1804 match_elements! {ctx, attributes,
1805 "syncsupport" => syncsupport = parse_syncsupport(ctx, attributes),
1806 "syncequivalent" => syncequivalent = parse_syncequivalent(ctx, attributes),
1807 }
1808
1809 unwrap_attribute!(ctx, syncstage, name);
1810
1811 Some(SyncChild::Stage(SyncStage {
1812 name,
1813 alias,
1814 syncsupport,
1815 syncequivalent,
1816 }))
1817}
1818
1819fn parse_syncaccess<R: Read>(
1820 ctx: &mut ParseCtx<R>,
1821 attributes: Vec<XmlAttribute>,
1822) -> Option<SyncChild> {
1823 let mut name = None;
1824 let mut alias = None;
1825 let mut comment = None;
1826 let mut syncsupport = None;
1827 let mut syncequivalent = None;
1828
1829 match_attributes! { ctx, a in attributes,
1830 "name" => name = Some(a.value),
1831 "alias" => alias = Some(a.value),
1832 }
1833
1834 match_elements! { ctx, attributes,
1835 "comment" => comment = Some(parse_text_element(ctx)),
1836 "syncsupport" => syncsupport = parse_syncsupport(ctx, attributes),
1837 "syncequivalent" => syncequivalent = parse_syncequivalent(ctx, attributes),
1838 }
1839
1840 unwrap_attribute!(ctx, syncaccess, name);
1841
1842 Some(SyncChild::Access(SyncAccess {
1843 name,
1844 alias,
1845 comment,
1846 syncsupport,
1847 syncequivalent,
1848 }))
1849}
1850
1851fn parse_syncpipeline<R: Read>(
1852 ctx: &mut ParseCtx<R>,
1853 attributes: Vec<XmlAttribute>,
1854) -> Option<SyncChild> {
1855 let mut name = None;
1856 let mut depends = None;
1857 let mut children = Vec::new();
1858
1859 match_attributes! {ctx, a in attributes,
1860 "name" => name = Some(a.value),
1861 "depends" => depends = Some(a.value),
1862 }
1863
1864 match_elements! { ctx, attributes,
1865 "syncpipelinestage" => if let Some(v) = parse_syncpipelinestage(ctx, attributes) {
1866 children.push(v);
1867 },
1868 }
1869
1870 unwrap_attribute!(ctx, syncpipeline, name);
1871
1872 Some(SyncChild::Pipeline(SyncPipeline {
1873 name,
1874 depends,
1875 children,
1876 }))
1877}
1878
1879fn parse_syncpipelinestage<R: Read>(
1880 ctx: &mut ParseCtx<R>,
1881 attributes: Vec<XmlAttribute>,
1882) -> Option<SyncPipelineStage> {
1883 let mut order = None;
1884 let mut before = None;
1885 let mut after = None;
1886 match_attributes! {ctx, a in attributes,
1887 "order" => order = Some(a.value),
1888 "before" => before = Some(a.value),
1889 "after" => after = Some(a.value),
1890 }
1891
1892 let text = parse_text_element(ctx);
1893
1894 Some(SyncPipelineStage {
1895 order,
1896 before,
1897 after,
1898 text,
1899 })
1900}
1901
1902fn parse_videocodecs<R: Read>(
1903 ctx: &mut ParseCtx<R>,
1904 attributes: Vec<XmlAttribute>,
1905) -> RegistryChild {
1906 let mut comment = None;
1907 let mut children = Vec::new();
1908
1909 match_attributes! {ctx, a in attributes,
1910 "comment" => comment = Some(a.value),
1911 }
1912
1913 match_elements! {ctx, attributes,
1914 "videocodec" => if let Some(v) = parse_videocodec(ctx, attributes) {
1915 children.push(v);
1916 },
1917 }
1918
1919 RegistryChild::VideoCodecs(VideoCodecs { comment, children })
1920}
1921
1922fn parse_videocodec<R: Read>(
1923 ctx: &mut ParseCtx<R>,
1924 attributes: Vec<XmlAttribute>,
1925) -> Option<VideoCodec> {
1926 let mut comment = None;
1927 let mut name = None;
1928 let mut extend = None;
1929 let mut value = None;
1930 let mut children = Vec::new();
1931
1932 match_attributes! {ctx, a in attributes,
1933 "comment" => comment = Some(a.value),
1934 "name" => name = Some(a.value),
1935 "extend" => extend = Some(a.value),
1936 "value" => value = Some(a.value),
1937 }
1938
1939 match_elements! {ctx, attributes,
1940 "videoprofiles" => if let Some(v) = parse_videoprofiles(ctx, attributes) {
1941 children.push(VideoCodecChild::Profiles(v));
1942 },
1943 "videocapabilities" => if let Some(v) = parse_videocapabilities(ctx, attributes) {
1944 children.push(VideoCodecChild::Capabilities(v));
1945 },
1946 "videoformat" => if let Some(v) = parse_videoformat(ctx, attributes) {
1947 children.push(VideoCodecChild::Format(v));
1948 },
1949 }
1950
1951 unwrap_attribute!(ctx, videocodec, name);
1952
1953 Some(VideoCodec {
1954 comment,
1955 name,
1956 extend,
1957 value,
1958 children,
1959 })
1960}
1961
1962fn parse_videoprofiles<R: Read>(
1963 ctx: &mut ParseCtx<R>,
1964 attributes: Vec<XmlAttribute>,
1965) -> Option<VideoProfiles> {
1966 let mut comment = None;
1967 let mut struct_ = None;
1968 let mut children = Vec::new();
1969
1970 match_attributes! {ctx, a in attributes,
1971 "comment" => comment = Some(a.value),
1972 "struct" => struct_ = Some(a.value),
1973 }
1974
1975 match_elements! {ctx, attributes,
1976 "videoprofilemember" => if let Some(v) = parse_videoprofilemember(ctx, attributes) {
1977 children.push(v);
1978 },
1979 }
1980
1981 unwrap_attribute!(ctx, videoprofiles, struct_, "struct");
1982
1983 Some(VideoProfiles {
1984 comment,
1985 struct_,
1986 children,
1987 })
1988}
1989
1990fn parse_videoprofilemember<R: Read>(
1991 ctx: &mut ParseCtx<R>,
1992 attributes: Vec<XmlAttribute>,
1993) -> Option<VideoProfileMember> {
1994 let mut comment = None;
1995 let mut name = None;
1996 let mut children = Vec::new();
1997
1998 match_attributes! {ctx, a in attributes,
1999 "comment" => comment = Some(a.value),
2000 "name" => name = Some(a.value),
2001 }
2002
2003 match_elements! {ctx, attributes,
2004 "videoprofile" => if let Some(v) = parse_videoprofile(ctx, attributes) {
2005 children.push(v);
2006 },
2007 }
2008
2009 unwrap_attribute!(ctx, videoprofilemember, name);
2010
2011 Some(VideoProfileMember {
2012 comment,
2013 name,
2014 children,
2015 })
2016}
2017
2018fn parse_videoprofile<R: Read>(
2019 ctx: &mut ParseCtx<R>,
2020 attributes: Vec<XmlAttribute>,
2021) -> Option<VideoProfile> {
2022 let mut comment = None;
2023 let mut name = None;
2024 let mut value = None;
2025
2026 match_attributes! {ctx, a in attributes,
2027 "comment" => comment = Some(a.value),
2028 "name" => name = Some(a.value),
2029 "value" => value = Some(a.value),
2030 }
2031
2032 consume_current_element(ctx);
2033
2034 unwrap_attribute!(ctx, videoprofile, name);
2035 unwrap_attribute!(ctx, videoprofile, value);
2036
2037 Some(VideoProfile {
2038 comment,
2039 name,
2040 value,
2041 })
2042}
2043
2044fn parse_videocapabilities<R: Read>(
2045 ctx: &mut ParseCtx<R>,
2046 attributes: Vec<XmlAttribute>,
2047) -> Option<VideoCapabilities> {
2048 let mut comment = None;
2049 let mut struct_ = None;
2050
2051 match_attributes! {ctx, a in attributes,
2052 "comment" => comment = Some(a.value),
2053 "struct" => struct_ = Some(a.value),
2054 }
2055
2056 consume_current_element(ctx);
2057
2058 unwrap_attribute!(ctx, videocapabilities, struct_, "struct");
2059
2060 Some(VideoCapabilities { comment, struct_ })
2061}
2062
2063fn parse_videoformat<R: Read>(
2064 ctx: &mut ParseCtx<R>,
2065 attributes: Vec<XmlAttribute>,
2066) -> Option<VideoFormat> {
2067 let mut comment = None;
2068 let mut name = None;
2069 let mut usage = None;
2070 let mut extend = None;
2071 let mut children = Vec::new();
2072
2073 match_attributes! {ctx, a in attributes,
2074 "comment" => comment = Some(a.value),
2075 "name" => name = Some(a.value),
2076 "usage" => usage = Some(a.value),
2077 "extend" => extend = Some(a.value),
2078 }
2079
2080 match_elements! {ctx, attributes,
2081 "videorequirecapabilities" => if let Some(v) = parse_videorequirecapabilities(ctx, attributes) {
2082 children.push(VideoFormatChild::RequireCapabilities(v));
2083 },
2084 "videoformatproperties" => if let Some(v) = parse_videoformatproperties(ctx, attributes) {
2085 children.push(VideoFormatChild::FormatProperties(v));
2086 },
2087 }
2088
2089 Some(VideoFormat {
2090 comment,
2091 name,
2092 usage,
2093 extend,
2094 children,
2095 })
2096}
2097
2098fn parse_videoformatproperties<R: Read>(
2099 ctx: &mut ParseCtx<R>,
2100 attributes: Vec<XmlAttribute>,
2101) -> Option<VideoFormatProperties> {
2102 let mut comment = None;
2103 let mut struct_ = None;
2104
2105 match_attributes! {ctx, a in attributes,
2106 "comment" => comment = Some(a.value),
2107 "struct" => struct_ = Some(a.value),
2108 }
2109
2110 consume_current_element(ctx);
2111
2112 unwrap_attribute!(ctx, videoformatproperties, struct_, "struct");
2113
2114 Some(VideoFormatProperties { comment, struct_ })
2115}
2116
2117fn parse_videorequirecapabilities<R: Read>(
2118 ctx: &mut ParseCtx<R>,
2119 attributes: Vec<XmlAttribute>,
2120) -> Option<VideoRequireCapabilities> {
2121 let mut comment = None;
2122 let mut struct_ = None;
2123 let mut member = None;
2124 let mut value = None;
2125
2126 match_attributes! {ctx, a in attributes,
2127 "comment" => comment = Some(a.value),
2128 "struct" => struct_ = Some(a.value),
2129 "member" => member = Some(a.value),
2130 "value" => value = Some(a.value),
2131 }
2132
2133 consume_current_element(ctx);
2134
2135 unwrap_attribute!(ctx, videorequirecapabilities, struct_, "struct");
2136 unwrap_attribute!(ctx, videorequirecapabilities, member);
2137 unwrap_attribute!(ctx, videorequirecapabilities, value);
2138
2139 Some(VideoRequireCapabilities {
2140 comment,
2141 struct_,
2142 member,
2143 value,
2144 })
2145}
2146
2147fn parse_name_with_type<R: Read>(
2148 ctx: &mut ParseCtx<R>,
2149 buffer: &mut String,
2150) -> Option<NameWithType> {
2151 let mut name = None;
2152 let mut type_name = None;
2153 let mut code = String::new();
2154 match_elements_combine_text! {ctx, code,
2155 "type" => {
2156 let text = parse_text_element(ctx);
2157 code.push_str(&text);
2158 type_name = Some(text);
2159 },
2160 "name" => {
2161 let text = parse_text_element(ctx);
2162 code.push_str(&text);
2163 name = Some(text);
2164 }
2165 }
2166 let name = if let Some(v) = name {
2167 v
2168 } else {
2169 ctx.errors.push(Error::MissingElement {
2170 xpath: ctx.xpath.clone(),
2171 name: String::from("name"),
2172 });
2173 return None;
2174 };
2175
2176 buffer.push_str(&code);
2177 Some(NameWithType {
2178 name,
2179 type_name,
2180 code,
2181 })
2182}
2183
2184fn parse_integer<R: Read>(ctx: &mut ParseCtx<R>, text: &str) -> Option<i64> {
2185 let parse_res = if text.starts_with("0x") {
2186 i64::from_str_radix(text.split_at(2).1, 16)
2187 } else {
2188 i64::from_str_radix(text, 10)
2189 };
2190
2191 if let Ok(v) = parse_res {
2192 Some(v)
2193 } else {
2194 ctx.errors.push(Error::SchemaViolation {
2195 xpath: ctx.xpath.clone(),
2196 desc: format!("Value '{}' is not valid base 10 or 16 integer.", text),
2197 });
2198 None
2199 }
2200}
2201
2202fn parse_int_attribute<I: FromStr<Err = std::num::ParseIntError>, R: Read>(
2203 ctx: &mut ParseCtx<R>,
2204 text: String,
2205 attribute_name: &str,
2206) -> Option<I> {
2207 match I::from_str(&text) {
2208 Ok(v) => Some(v),
2209 Err(e) => {
2210 ctx.errors.push(Error::ParseIntError {
2211 xpath: xpath_attribute(&ctx.xpath, attribute_name),
2212 text: text,
2213 error: e,
2214 });
2215 None
2216 }
2217 }
2218}
2219
2220fn consume_current_element<R: Read>(ctx: &mut ParseCtx<R>) {
2221 let mut depth = 1;
2222 while let Some(Ok(e)) = ctx.events.next() {
2223 match e {
2224 XmlEvent::StartElement { name, .. } => {
2225 ctx.push_element(name.local_name.as_str());
2226 depth += 1;
2227 }
2228 XmlEvent::EndElement { .. } => {
2229 depth -= 1;
2230 ctx.pop_element();
2231 if depth == 0 {
2232 break;
2233 }
2234 }
2235 _ => (),
2236 }
2237 }
2238}
2239
2240fn parse_text_element<R: Read>(ctx: &mut ParseCtx<R>) -> String {
2241 let mut result = String::new();
2242 let mut depth = 1;
2243 while let Some(Ok(e)) = ctx.events.next() {
2244 match e {
2245 XmlEvent::StartElement { name, .. } => {
2246 ctx.push_element(name.local_name.as_str());
2247 depth += 1;
2248 }
2249 XmlEvent::Characters(text) => result.push_str(&text),
2250 XmlEvent::EndElement { .. } => {
2251 depth -= 1;
2252 ctx.pop_element();
2253 if depth == 0 {
2254 break;
2255 }
2256 }
2257 _ => (),
2258 }
2259 }
2260 result
2261}