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 match_attributes!{ctx, a in attributes,
527 "len" => len = Some(a.value),
528 "altlen" => altlen = Some(a.value),
529 "externsync" => externsync = Some(a.value),
530 "optional" => optional = Some(a.value),
531 "selector" => selector = Some(a.value),
532 "selection" => selection = Some(a.value),
533 "noautovalidity" => noautovalidity = Some(a.value),
534 "validextensionstructs" => validextensionstructs = Some(a.value),
535 "values" => values = Some(a.value),
536 "limittype" => limittype = Some(a.value),
537 "objecttype" => objecttype = Some(a.value),
538 "deprecated" => deprecated = Some(a.value),
539 "api" => api = Some(a.value),
540 "featurelink" => featurelink = Some(a.value),
541 }
542 match_elements_combine_text!{ctx, code,
543 "type" => {
544 let text = parse_text_element(ctx);
545 code.push_str(&text);
546 markup.push(TypeMemberMarkup::Type(text));
547 },
548 "name" => {
549 let text = parse_text_element(ctx);
550 code.push_str(&text);
551 markup.push(TypeMemberMarkup::Name(text));
552 },
553 "enum" => {
554 let text = parse_text_element(ctx);
555 code.push_str(&text);
556 markup.push(TypeMemberMarkup::Enum(text));
557 },
558 "comment" => {
559 let text = parse_text_element(ctx);
560 markup.push(TypeMemberMarkup::Comment(text));
561 },
562 }
563 members.push(TypeMember::Definition(TypeMemberDefinition {
564 len,
565 altlen,
566 externsync,
567 optional,
568 selector,
569 selection,
570 noautovalidity,
571 validextensionstructs,
572 values,
573 limittype,
574 objecttype,
575 deprecated,
576 api,
577 code,
578 markup,
579 featurelink,
580 }))
581 },
582 "comment" => members.push(TypeMember::Comment(parse_text_element(ctx))),
583 "name" => {
584 let text = parse_text_element(ctx);
585 code.push_str(&text);
586 markup.push(TypeCodeMarkup::Name(text));
587 },
588 "type" => {
589 let text = parse_text_element(ctx);
590 code.push_str(&text);
591 markup.push(TypeCodeMarkup::Type(text));
592 },
593 "apientry" => {
594 let text = parse_text_element(ctx);
595 code.push_str(&text);
596 markup.push(TypeCodeMarkup::ApiEntry(text));
597 },
598 "proto" => {
599 let mut name = None;
600 let mut type_name = None;
601 let mut code = String::new();
602 match_elements_combine_text! {ctx, code,
603 "type" => {
604 let text = parse_text_element(ctx);
605 code.push_str(&text);
606 type_name = Some(text);
607 },
608 "name" => {
609 let text = parse_text_element(ctx);
610 code.push_str("(VKAPI_PTR *");
611 code.push_str(&text);
612 code.push_str(")");
613 markup.push(TypeCodeMarkup::Name(text.clone())); name = Some(text);
615 },
616 };
617 if let Some(name) = name {
618 proto = Some(FuncpointerProtoMarkup {
619 type_name,
620 name,
621 code,
622 });
623 } else {
624 ctx.errors.push(Error::MissingElement {
625 xpath: ctx.xpath.clone(),
626 name: String::from("name"),
627 });
628 }
629 },
630 "param" => {
631 let mut param = String::new();
632 if let Some(p) = parse_name_with_type(ctx, &mut param) {
633 if let Some(ref t) = p.type_name {
634 markup.push(TypeCodeMarkup::Type(t.clone())); }
636 params.push(p);
637 }
638 }
639 }
640
641 if let Some(ref proto) = proto {
642 code.clear();
644 code.push_str("typedef ");
645 code.push_str(&proto.code);
646 code.push_str("(");
647 if params.is_empty() {
648 code.push_str("void");
649 } else {
650 let mut is_first = true;
651 for param in ¶ms {
652 if is_first {
653 is_first = false;
654 } else {
655 code.push_str(", ");
656 }
657 code.push_str(¶m.code);
658 }
659 }
660 code.push_str(");");
661 }
662
663 TypesChild::Type(Type {
664 api,
665 alias,
666 requires,
667 name,
668 category,
669 parent,
670 returnedonly,
671 structextends,
672 allowduplicate,
673 objtypeenum,
674 requiredlimittype,
675 bitvalues,
676 deprecated,
677 comment,
678 spec: if members.len() > 0 {
679 TypeSpec::Members(members)
680 } else if let Some(proto) = proto {
681 TypeSpec::Funcpointer(FuncpointerCode {
682 code,
683 markup,
684 proto,
685 params,
686 })
687 } else if code.len() > 0 {
688 TypeSpec::Code(TypeCode { code, markup })
689 } else {
690 TypeSpec::None
691 },
692 })
693}
694
695fn parse_command<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> Option<Command> {
696 let mut name = None;
697 let mut alias = None;
698 let mut tasks = None;
699 let mut queues = None;
700 let mut successcodes = None;
701 let mut errorcodes = None;
702 let mut renderpass = None;
703 let mut videocoding = None;
704 let mut conditionalrendering = None;
705 let mut cmdbufferlevel = None;
706 let mut allownoqueues = None;
707 let mut pipeline = None;
708 let mut comment = None;
709 let mut api = None;
710 let mut export = None;
711
712 match_attributes! {ctx, a in attributes,
713 "name" => name = Some(a.value),
714 "alias" => alias = Some(a.value),
715 "tasks" => tasks = Some(a.value),
716 "queues" => queues = Some(a.value),
717 "successcodes" => successcodes = Some(a.value),
718 "errorcodes" => errorcodes = Some(a.value),
719 "renderpass" => renderpass = Some(a.value),
720 "videocoding" => videocoding = Some(a.value),
721 "conditionalrendering" => conditionalrendering = Some(a.value),
722 "cmdbufferlevel" => cmdbufferlevel = Some(a.value),
723 "allownoqueues" => allownoqueues = Some(a.value),
724 "pipeline" => pipeline = Some(a.value),
725 "comment" => comment = Some(a.value),
726 "api" => api = Some(a.value),
727 "export" => export = Some(a.value),
728 }
729
730 if let Some(alias) = alias {
731 unwrap_attribute!(ctx, command, name);
732 consume_current_element(ctx);
733 Some(Command::Alias { alias, name })
734 } else {
735 let mut code = String::new();
736 let mut proto = None;
737 let mut params = Vec::new();
738 let mut description = None;
739 let mut implicitexternsyncparams = Vec::new();
740
741 match_elements! {ctx, attributes,
742 "proto" => {
743 proto = parse_name_with_type(ctx, &mut code);
744 code.push('(');
745 },
746
747 "param" => {
748 let mut len = None;
749 let mut altlen = None;
750 let mut externsync = None;
751 let mut optional = None;
752 let mut noautovalidity = None;
753 let mut objecttype = None;
754 let mut validstructs = None;
755 let mut stride = None;
756 let mut api = None;
757
758 match_attributes!{ctx, a in attributes,
759 "len" => len = Some(a.value),
760 "altlen" => altlen = Some(a.value),
761 "externsync" => externsync = Some(a.value),
762 "optional" => optional = Some(a.value),
763 "noautovalidity" => noautovalidity = Some(a.value),
764 "objecttype" => objecttype = Some(a.value),
765 "validstructs" => validstructs = Some(a.value),
766 "stride" => stride = Some(a.value),
767 "api" => api = Some(a.value),
768 }
769
770 let validstructs = validstructs.map_or(
771 Default::default(),
772 |structs| structs.split(',').map(|s| s.to_owned()).collect()
773 );
774
775 if !params.is_empty() {
776 code.push_str(", ");
777 }
778 if let Some(definition) = parse_name_with_type(ctx, &mut code) {
779 params.push(CommandParam {
780 len,
781 altlen,
782 externsync,
783 optional,
784 noautovalidity,
785 objecttype,
786 definition,
787 validstructs,
788 stride,
789 api,
790 });
791 }
792 },
793
794 "alias" => {
795 match_attributes!{ctx, a in attributes,
796 "name" => alias = Some(a.value),
797 }
798 consume_current_element(ctx);
799 },
800
801 "description" => description = Some(parse_text_element(ctx)),
802 "implicitexternsyncparams" => {
803 match_elements!{ctx,
804 "param" => implicitexternsyncparams.push(parse_text_element(ctx)),
805 }
806 }
807 }
808 code.push_str(");");
809
810 let proto = if let Some(v) = proto {
811 v
812 } else {
813 ctx.errors.push(Error::MissingElement {
814 xpath: ctx.xpath.clone(),
815 name: String::from("proto"),
816 });
817 return None;
818 };
819
820 let conditionalrendering = if let Some(v) = conditionalrendering {
821 match v.as_str() {
822 "true" => Some(true),
823 "false" => Some(false),
824 _ => {
825 ctx.errors.push(Error::UnexpectedAttributeValue {
826 xpath: ctx.xpath.clone(),
827 name: String::from("conditionalrendering"),
828 value: v,
829 });
830 return None;
831 }
832 }
833 } else {
834 None
835 };
836
837 Some(Command::Definition(CommandDefinition {
838 tasks,
839 queues,
840 successcodes,
841 errorcodes,
842 renderpass,
843 videocoding,
844 conditionalrendering,
845 cmdbufferlevel,
846 allownoqueues,
847 pipeline,
848 comment,
849 proto,
850 params,
851 alias,
852 description,
853 implicitexternsyncparams,
854 api,
855 export,
856 code,
857 }))
858 }
859}
860
861fn parse_enum<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> Option<Enum> {
862 let mut name = None;
863 let mut comment = None;
864 let mut type_suffix = None;
865 let mut api = None;
866 let mut extends = None;
867 let mut value = None;
868 let mut bitpos = None;
869 let mut extnumber = None;
870 let mut offset = None;
871 let mut positive = true;
872 let mut protect = None;
873 let mut alias = None;
874 let mut deprecated = None;
875
876 match_attributes! {ctx, a in attributes,
877 "name" => name = Some(a.value),
878 "comment" => comment = Some(a.value),
879 "type" => type_suffix = Some(a.value),
880 "api" => api = Some(a.value),
881 "extends" => extends = Some(a.value),
882 "value" => value = Some(a.value),
883 "offset" => offset = Some(a.value),
884 "dir" => {
885 if a.value.as_str() == "-" {
886 positive = false;
887 } else {
888 ctx.errors.push(Error::UnexpectedAttributeValue {
889 xpath: ctx.xpath.clone(),
890 name: String::from("dir"),
891 value: a.value
892 });
893 }
894 },
895 "bitpos" => bitpos = Some(a.value),
896 "extnumber" => extnumber = Some(a.value),
897 "protect" => protect = Some(a.value),
898 "alias" => alias = Some(a.value),
899 "deprecated" => deprecated = Some(a.value),
900 }
901
902 unwrap_attribute!(ctx, enum, name);
903
904 let mut count = 0;
905 if offset.is_some() {
906 count += 1;
907 }
908 if bitpos.is_some() {
909 count += 1;
910 }
911 if value.is_some() {
912 count += 1;
913 }
914 if alias.is_some() {
915 count += 1;
916 }
917 if count > 1 {
918 ctx.errors.push(Error::SchemaViolation {
919 xpath: ctx.xpath.clone(),
920 desc: format!(
921 "Unable to determine correct specification of enum: offset={:?}, bitpos={:?}, value={:?}, alias={:?}",
922 offset, bitpos, value, alias
923 ),
924 });
925 consume_current_element(ctx);
926 return None;
927 }
928
929 let spec = if let Some(alias) = alias {
930 EnumSpec::Alias { alias, extends }
931 } else if let Some(offset) = offset {
932 let offset = match parse_integer(ctx, &offset) {
933 Some(v) => v,
934 None => {
935 consume_current_element(ctx);
936 return None;
937 }
938 };
939 if let Some(extends) = extends {
940 EnumSpec::Offset {
941 offset,
942 extends,
943 extnumber: match extnumber {
944 Some(extnumber) => parse_integer(ctx, &extnumber),
945 None => None,
946 },
947 dir: positive,
948 }
949 } else {
950 ctx.errors.push(Error::SchemaViolation {
951 xpath: ctx.xpath.clone(),
952 desc: String::from("Missing extends on enum with offset spec."),
953 });
954 consume_current_element(ctx);
955 return None;
956 }
957 } else if let Some(bitpos) = bitpos {
958 let bitpos = match parse_integer(ctx, &bitpos) {
959 Some(v) => v,
960 None => {
961 consume_current_element(ctx);
962 return None;
963 }
964 };
965 EnumSpec::Bitpos { bitpos, extends }
966 } else if let Some(value) = value {
967 EnumSpec::Value { value, extends }
968 } else {
969 EnumSpec::None
970 };
971
972 consume_current_element(ctx);
973
974 Some(Enum {
975 name,
976 comment,
977 type_suffix,
978 api,
979 protect,
980 deprecated,
981 spec,
982 })
983}
984
985fn parse_enums_child_unused<R: Read>(
986 ctx: &mut ParseCtx<R>,
987 attributes: Vec<XmlAttribute>,
988) -> Option<EnumsChild> {
989 let mut start = None;
990 let mut end = None;
991 let mut vendor = None;
992 let mut comment = None;
993 match_attributes! {ctx, a in attributes,
994 "start" => start = Some(a.value),
995 "end" => end = Some(a.value),
996 "vendor" => vendor = Some(a.value),
997 "comment" => comment = Some(a.value),
998 }
999 consume_current_element(ctx);
1000 unwrap_attribute!(ctx, unused, start);
1001 let start = match parse_integer(ctx, &start) {
1002 Some(v) => v,
1003 None => return None,
1004 };
1005 let end = end.and_then(|val| parse_integer(ctx, &val));
1006 Some(EnumsChild::Unused(Unused {
1007 start,
1008 end,
1009 vendor,
1010 comment,
1011 }))
1012}
1013
1014fn parse_feature<R: Read>(
1015 ctx: &mut ParseCtx<R>,
1016 attributes: Vec<XmlAttribute>,
1017) -> Option<RegistryChild> {
1018 let mut api = None;
1019 let mut apitype = None;
1020 let mut name = None;
1021 let mut number = None;
1022 let mut depends = None;
1023 let mut protect = None;
1024 let mut comment = None;
1025 let mut children = Vec::new();
1026
1027 match_attributes! {ctx, a in attributes,
1028 "api" => api = Some(a.value),
1029 "apitype" => apitype = Some(a.value),
1030 "name" => name = Some(a.value),
1031 "number" => number = Some(a.value),
1032 "depends" => depends = Some(a.value),
1033 "protect" => protect = Some(a.value),
1034 "comment" => comment = Some(a.value),
1035 }
1036
1037 match_elements! {ctx, attributes,
1038 "require" => children.push(parse_extension_item_require(ctx, attributes)),
1039 "deprecate" => if let Some(child) = parse_extension_item_deprecate(ctx, attributes) { children.push(child) },
1040 "remove" => children.push(parse_extension_item_remove(ctx, attributes)),
1041 }
1042
1043 unwrap_attribute!(ctx, feature, api);
1044 unwrap_attribute!(ctx, feature, name);
1045
1046 Some(RegistryChild::Feature(Feature {
1047 api,
1048 apitype,
1049 name,
1050 number,
1051 depends,
1052 protect,
1053 comment,
1054 children,
1055 }))
1056}
1057
1058fn parse_extensions<R: Read>(
1059 ctx: &mut ParseCtx<R>,
1060 attributes: Vec<XmlAttribute>,
1061) -> RegistryChild {
1062 let mut comment = None;
1063 let mut children = Vec::new();
1064
1065 match_attributes! {ctx, a in attributes,
1066 "comment" => comment = Some(a.value),
1067 }
1068
1069 match_elements! {ctx, attributes,
1070 "extension" => if let Some(v) = parse_extension(ctx, attributes) {
1071 children.push(v);
1072 },
1073 }
1074
1075 RegistryChild::Extensions(Extensions { comment, children })
1076}
1077
1078fn parse_extension<R: Read>(
1079 ctx: &mut ParseCtx<R>,
1080 attributes: Vec<XmlAttribute>,
1081) -> Option<Extension> {
1082 let mut name = None;
1083 let mut comment = None;
1084 let mut number = None;
1085 let mut protect = None;
1086 let mut platform = None;
1087 let mut author = None;
1088 let mut contact = None;
1089 let mut ext_type = None;
1090 let mut requires = None;
1091 let mut requires_core = None;
1092 let mut supported = None;
1093 let mut ratified = None;
1094 let mut deprecatedby = None;
1095 let mut promotedto = None;
1096 let mut obsoletedby = None;
1097 let mut provisional = None;
1098 let mut specialuse = None;
1099 let mut sortorder = None;
1100 let mut depends = None;
1101 let mut nofeatures = None;
1102 let mut children = Vec::new();
1103
1104 match_attributes! {ctx, a in attributes,
1105 "name" => name = Some(a.value),
1106 "comment" => comment = Some(a.value),
1107 "number" => number = Some(a.value),
1108 "protect" => protect = Some(a.value),
1109 "platform" => platform = Some(a.value),
1110 "author" => author = Some(a.value),
1111 "contact" => contact = Some(a.value),
1112 "type" => ext_type = Some(a.value),
1113 "requires" => requires = Some(a.value),
1114 "requiresCore" => requires_core = Some(a.value),
1115 "supported" => supported = Some(a.value),
1116 "ratified" => ratified = Some(a.value),
1117 "deprecatedby" => deprecatedby = Some(a.value),
1118 "promotedto" => promotedto = Some(a.value),
1119 "provisional" => provisional = Some(a.value),
1120 "obsoletedby" => obsoletedby = Some(a.value),
1121 "specialuse" => specialuse = Some(a.value),
1122 "sortorder" => sortorder = Some(a.value),
1123 "depends" => depends = Some(a.value),
1124 "nofeatures" => nofeatures = Some(a.value),
1125 }
1126
1127 let number = match number {
1128 Some(text) => parse_integer(ctx, &text),
1129 None => None,
1130 };
1131
1132 let provisional = match provisional.as_deref() {
1133 Some("true") => true,
1134 Some("false") => false,
1135 Some(value) => {
1136 ctx.errors.push(Error::SchemaViolation {
1137 xpath: ctx.xpath.clone(),
1138 desc: format!("Unexpected value of 'provisional' attribute: {}", value),
1139 });
1140 false
1141 }
1142 None => false,
1143 };
1144 let nofeatures = match nofeatures.as_deref() {
1145 Some("true") => true,
1146 Some("false") => false,
1147 Some(value) => {
1148 ctx.errors.push(Error::SchemaViolation {
1149 xpath: ctx.xpath.clone(),
1150 desc: format!("Unexpected value of 'nofeatures' attribute: {}", value),
1151 });
1152 false
1153 }
1154 None => false,
1155 };
1156
1157 let sortorder = match sortorder {
1158 Some(text) => parse_integer(ctx, &text),
1159 None => None,
1160 };
1161
1162 unwrap_attribute!(ctx, extension, name);
1163
1164 match_elements! {ctx, attributes,
1165 "require" => children.push(parse_extension_item_require(ctx, attributes)),
1166 "deprecate" => if let Some(child) = parse_extension_item_deprecate(ctx, attributes) { children.push(child) },
1167 "remove" => children.push(parse_extension_item_remove(ctx, attributes)),
1168 }
1169
1170 Some(Extension {
1171 name,
1172 comment,
1173 number,
1174 protect,
1175 platform,
1176 author,
1177 contact,
1178 ext_type,
1179 requires,
1180 requires_core,
1181 supported,
1182 ratified,
1183 deprecatedby,
1184 promotedto,
1185 obsoletedby,
1186 provisional,
1187 specialuse,
1188 sortorder,
1189 depends,
1190 nofeatures,
1191 children,
1192 })
1193}
1194
1195fn parse_extension_item_require<R: Read>(
1196 ctx: &mut ParseCtx<R>,
1197 attributes: Vec<XmlAttribute>,
1198) -> ExtensionChild {
1199 let mut api = None;
1200 let mut profile = None;
1201 let mut extension = None;
1202 let mut feature = None;
1203 let mut comment = None;
1204 let mut depends = None;
1205 let mut items = Vec::new();
1206
1207 match_attributes! {ctx, a in attributes,
1208 "api" => api = Some(a.value),
1209 "profile" => profile = Some(a.value),
1210 "extension" => extension = Some(a.value),
1211 "feature" => feature = Some(a.value),
1212 "comment" => comment = Some(a.value),
1213 "depends" => depends = Some(a.value),
1214 }
1215
1216 while let Some(Ok(e)) = ctx.events.next() {
1217 match e {
1218 XmlEvent::StartElement {
1219 name, attributes, ..
1220 } => {
1221 let name = name.local_name.as_str();
1222 ctx.push_element(name);
1223 if let Some(v) = parse_interface_item(ctx, name, attributes) {
1224 items.push(v);
1225 }
1226 }
1227 XmlEvent::EndElement { .. } => {
1228 ctx.pop_element();
1229 break;
1230 }
1231 _ => {}
1232 }
1233 }
1234
1235 ExtensionChild::Require {
1236 api,
1237 profile,
1238 extension,
1239 feature,
1240 comment,
1241 depends,
1242 items,
1243 }
1244}
1245
1246fn parse_extension_item_deprecate<R: Read>(
1247 ctx: &mut ParseCtx<R>,
1248 attributes: Vec<XmlAttribute>,
1249) -> Option<ExtensionChild> {
1250 let mut api = None;
1251 let mut profile = None;
1252 let mut comment = None;
1253 let mut explanationlink = None;
1254 let mut items = Vec::new();
1255
1256 match_attributes! {ctx, a in attributes,
1257 "api" => api = Some(a.value),
1258 "profile" => profile = Some(a.value),
1259 "comment" => comment = Some(a.value),
1260 "explanationlink" => explanationlink = Some(a.value),
1261 }
1262
1263 unwrap_attribute!(ctx, deprecate, explanationlink);
1264
1265 while let Some(Ok(e)) = ctx.events.next() {
1266 match e {
1267 XmlEvent::StartElement {
1268 name, attributes, ..
1269 } => {
1270 let name = name.local_name.as_str();
1271 ctx.push_element(name);
1272 if let Some(v) = parse_interface_item(ctx, name, attributes) {
1273 items.push(v);
1274 }
1275 }
1276 XmlEvent::EndElement { .. } => {
1277 ctx.pop_element();
1278 break;
1279 }
1280 _ => {}
1281 }
1282 }
1283
1284 Some(ExtensionChild::Deprecate {
1285 api,
1286 profile,
1287 comment,
1288 explanationlink,
1289 items,
1290 })
1291}
1292
1293fn parse_extension_item_remove<R: Read>(
1294 ctx: &mut ParseCtx<R>,
1295 attributes: Vec<XmlAttribute>,
1296) -> ExtensionChild {
1297 let mut api = None;
1298 let mut profile = None;
1299 let mut comment = None;
1300 let mut reasonlink = None;
1301 let mut items = Vec::new();
1302
1303 match_attributes! {ctx, a in attributes,
1304 "api" => api = Some(a.value),
1305 "profile" => profile = Some(a.value),
1306 "comment" => comment = Some(a.value),
1307 "reasonlink" => reasonlink = Some(a.value),
1308 }
1309
1310 while let Some(Ok(e)) = ctx.events.next() {
1311 match e {
1312 XmlEvent::StartElement {
1313 name, attributes, ..
1314 } => {
1315 let name = name.local_name.as_str();
1316 ctx.push_element(name);
1317 if let Some(v) = parse_interface_item(ctx, name, attributes) {
1318 items.push(v);
1319 }
1320 }
1321 XmlEvent::EndElement { .. } => {
1322 ctx.pop_element();
1323 break;
1324 }
1325 _ => {}
1326 }
1327 }
1328
1329 ExtensionChild::Remove {
1330 api,
1331 profile,
1332 comment,
1333 reasonlink,
1334 items,
1335 }
1336}
1337
1338fn parse_interface_item<R: Read>(
1339 ctx: &mut ParseCtx<R>,
1340 name: &str,
1341 attributes: Vec<XmlAttribute>,
1342) -> Option<InterfaceItem> {
1343 match name {
1344 "comment" => Some(InterfaceItem::Comment(parse_text_element(ctx))),
1345 "type" => {
1346 let mut name = None;
1347 let mut comment = None;
1348 let mut supersededby = None;
1349 match_attributes! {ctx, a in attributes,
1350 "name" => name = Some(a.value),
1351 "comment" => comment = Some(a.value),
1352 "supersededby" => supersededby = Some(a.value),
1353 }
1354 unwrap_attribute!(ctx, type, name);
1355 consume_current_element(ctx);
1356 Some(InterfaceItem::Type {
1357 name,
1358 comment,
1359 supersededby,
1360 })
1361 }
1362 "enum" => parse_enum(ctx, attributes).map(|v| InterfaceItem::Enum(v)),
1363 "command" => {
1364 let mut name = None;
1365 let mut comment = None;
1366 let mut supersededby = None;
1367 match_attributes! {ctx, a in attributes,
1368 "name" => name = Some(a.value),
1369 "comment" => comment = Some(a.value),
1370 "supersededby" => supersededby = Some(a.value),
1371 }
1372 unwrap_attribute!(ctx, type, name);
1373 consume_current_element(ctx);
1374 Some(InterfaceItem::Command {
1375 name,
1376 comment,
1377 supersededby,
1378 })
1379 }
1380 "feature" => {
1381 let mut name = None;
1382 let mut struct_ = None;
1383 let mut comment = None;
1384 match_attributes! {ctx, a in attributes,
1385 "name" => name = Some(a.value),
1386 "struct" => struct_ = Some(a.value),
1387 "comment" => comment = Some(a.value),
1388 }
1389 unwrap_attribute!(ctx, type, name);
1390 unwrap_attribute!(ctx, type, struct_);
1391 consume_current_element(ctx);
1392 Some(InterfaceItem::Feature {
1393 name,
1394 struct_,
1395 comment,
1396 })
1397 }
1398 _ => {
1399 ctx.errors.push(Error::UnexpectedElement {
1400 xpath: ctx.xpath.clone(),
1401 name: String::from(name),
1402 });
1403 return None;
1404 }
1405 }
1406}
1407
1408fn parse_formats<R: Read>(ctx: &mut ParseCtx<R>) -> RegistryChild {
1409 let mut children = Vec::new();
1410
1411 match_elements! {ctx, attributes,
1412 "format" => if let Some(v) = parse_format(ctx, attributes) {
1413 children.push(v);
1414 },
1415 }
1416
1417 RegistryChild::Formats(Formats {
1418 comment: None,
1419 children,
1420 })
1421}
1422
1423#[allow(non_snake_case)]
1424fn parse_format<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> Option<Format> {
1425 let mut name = None;
1426 let mut class = None;
1427 let mut blockSize = None;
1428 let mut texelsPerBlock = None;
1429 let mut blockExtent = None;
1430 let mut packed = None;
1431 let mut compressed = None;
1432 let mut chroma = None;
1433 let mut children = Vec::new();
1434
1435 match_attributes! {ctx, a in attributes,
1436 "name" => name = Some(a.value),
1437 "class" => class = Some(a.value),
1438 "blockSize" => blockSize = Some(a.value),
1439 "texelsPerBlock" => texelsPerBlock = Some(a.value),
1440 "blockExtent" => blockExtent = Some(a.value),
1441 "packed" => packed = Some(a.value),
1442 "compressed" => compressed = Some(a.value),
1443 "chroma" => chroma = Some(a.value),
1444 }
1445
1446 unwrap_attribute!(ctx, extension, name);
1447 unwrap_attribute!(ctx, extension, class);
1448 unwrap_attribute!(ctx, extension, blockSize);
1449 unwrap_attribute!(ctx, extension, texelsPerBlock);
1450
1451 match_elements! {ctx, attributes,
1452 "component" => if let Some(v) = parse_format_component(ctx, attributes) { children.push(v); },
1453 "plane" => if let Some(v) = parse_format_plane(ctx, attributes) { children.push(v); },
1454 "spirvimageformat" => if let Some(v) = parse_format_spirvimageformat(ctx, attributes) { children.push(v); },
1455 }
1456
1457 let blockSize: Option<u8> = parse_int_attribute(ctx, blockSize, "blockSize");
1458 let texelsPerBlock: Option<u8> = parse_int_attribute(ctx, texelsPerBlock, "texelsPerBlock");
1459 let packed = packed.map(|v| -> Option<u8> { parse_int_attribute(ctx, v, "packed") });
1460
1461 let blockSize = match blockSize {
1462 Some(v) => v,
1463 None => return None,
1464 };
1465
1466 let texelsPerBlock = match texelsPerBlock {
1467 Some(v) => v,
1468 None => return None,
1469 };
1470
1471 let packed = match packed {
1472 Some(Some(v)) => Some(v),
1473 Some(None) => return None, None => None,
1475 };
1476
1477 Some(Format {
1478 name,
1479 class,
1480 blockSize,
1481 texelsPerBlock,
1482 blockExtent,
1483 packed,
1484 compressed,
1485 chroma,
1486 children,
1487 })
1488}
1489
1490#[allow(non_snake_case)]
1491fn parse_format_component<R: Read>(
1492 ctx: &mut ParseCtx<R>,
1493 attributes: Vec<XmlAttribute>,
1494) -> Option<FormatChild> {
1495 let mut name = None;
1496 let mut bits = None;
1497 let mut numericFormat = None;
1498 let mut planeIndex = None;
1499
1500 match_attributes! {ctx, a in attributes,
1501 "name" => name = Some(a.value),
1502 "bits" => bits = Some(a.value),
1503 "numericFormat" => numericFormat = Some(a.value),
1504 "planeIndex" => planeIndex = Some(a.value),
1505 }
1506
1507 unwrap_attribute!(ctx, extension, name);
1508 unwrap_attribute!(ctx, extension, bits);
1509 unwrap_attribute!(ctx, extension, numericFormat);
1510
1511 consume_current_element(ctx);
1512
1513 let planeIndex =
1514 planeIndex.map(|v| -> Option<u8> { parse_int_attribute(ctx, v, "planeIndex") });
1515
1516 let planeIndex = match planeIndex {
1517 Some(Some(v)) => Some(v),
1518 Some(None) => return None, None => None,
1520 };
1521
1522 Some(FormatChild::Component {
1523 name,
1524 bits,
1525 numericFormat,
1526 planeIndex,
1527 })
1528}
1529
1530#[allow(non_snake_case)]
1531fn parse_format_plane<R: Read>(
1532 ctx: &mut ParseCtx<R>,
1533 attributes: Vec<XmlAttribute>,
1534) -> Option<FormatChild> {
1535 let mut index = None;
1536 let mut widthDivisor = None;
1537 let mut heightDivisor = None;
1538 let mut compatible = None;
1539
1540 match_attributes! {ctx, a in attributes,
1541 "index" => index = Some(a.value),
1542 "widthDivisor" => widthDivisor = Some(a.value),
1543 "heightDivisor" => heightDivisor = Some(a.value),
1544 "compatible" => compatible = Some(a.value),
1545 }
1546
1547 unwrap_attribute!(ctx, extension, index);
1548 unwrap_attribute!(ctx, extension, widthDivisor);
1549 unwrap_attribute!(ctx, extension, heightDivisor);
1550 unwrap_attribute!(ctx, extension, compatible);
1551
1552 consume_current_element(ctx);
1553
1554 let index: Option<u8> = parse_int_attribute(ctx, index, "index");
1555 let widthDivisor: Option<u8> = parse_int_attribute(ctx, widthDivisor, "widthDivisor");
1556 let heightDivisor: Option<u8> = parse_int_attribute(ctx, heightDivisor, "heightDivisor");
1557
1558 let index = match index {
1559 Some(v) => v,
1560 None => return None,
1561 };
1562
1563 let widthDivisor = match widthDivisor {
1564 Some(v) => v,
1565 None => return None,
1566 };
1567
1568 let heightDivisor = match heightDivisor {
1569 Some(v) => v,
1570 None => return None,
1571 };
1572
1573 Some(FormatChild::Plane {
1574 index,
1575 widthDivisor,
1576 heightDivisor,
1577 compatible,
1578 })
1579}
1580
1581fn parse_format_spirvimageformat<R: Read>(
1582 ctx: &mut ParseCtx<R>,
1583 attributes: Vec<XmlAttribute>,
1584) -> Option<FormatChild> {
1585 let mut name = None;
1586
1587 match_attributes! {ctx, a in attributes,
1588 "name" => name = Some(a.value),
1589 }
1590
1591 unwrap_attribute!(ctx, extension, name);
1592
1593 consume_current_element(ctx);
1594
1595 Some(FormatChild::SpirvImageFormat { name })
1596}
1597
1598fn parse_spirvextensions<R: Read>(
1599 ctx: &mut ParseCtx<R>,
1600 attributes: Vec<XmlAttribute>,
1601) -> RegistryChild {
1602 let mut comment = None;
1603 let mut children = Vec::new();
1604
1605 match_attributes! {ctx, a in attributes,
1606 "comment" => comment = Some(a.value),
1607 }
1608
1609 match_elements! {ctx, attributes,
1610 "spirvextension" => if let Some(v) = parse_spirvextension(ctx, attributes) {
1611 children.push(v);
1612 },
1613 }
1614
1615 RegistryChild::SpirvExtensions(SpirvExtensions { comment, children })
1616}
1617
1618fn parse_spirvextension<R: Read>(
1619 ctx: &mut ParseCtx<R>,
1620 attributes: Vec<XmlAttribute>,
1621) -> Option<SpirvExtension> {
1622 let mut name = None;
1623 let mut enables = Vec::new();
1624
1625 match_attributes! {ctx, a in attributes,
1626 "name" => name = Some(a.value),
1627 }
1628
1629 match_elements! {ctx, attributes,
1630 "enable" => if let Some(v) = parse_enable(ctx, attributes) {
1631 enables.push(v);
1632 },
1633 }
1634
1635 unwrap_attribute!(ctx, spirvextension, name);
1636
1637 Some(SpirvExtension { name, enables })
1638}
1639
1640fn parse_spirvcapabilities<R: Read>(
1641 ctx: &mut ParseCtx<R>,
1642 attributes: Vec<XmlAttribute>,
1643) -> RegistryChild {
1644 let mut comment = None;
1645 let mut children = Vec::new();
1646
1647 match_attributes! {ctx, a in attributes,
1648 "comment" => comment = Some(a.value),
1649 }
1650
1651 match_elements! {ctx, attributes,
1652 "spirvcapability" => if let Some(v) = parse_spirvcapability(ctx, attributes) {
1653 children.push(v);
1654 },
1655 }
1656
1657 RegistryChild::SpirvCapabilities(SpirvCapabilities { comment, children })
1658}
1659
1660fn parse_spirvcapability<R: Read>(
1661 ctx: &mut ParseCtx<R>,
1662 attributes: Vec<XmlAttribute>,
1663) -> Option<SpirvCapability> {
1664 let mut name = None;
1665 let mut enables = Vec::new();
1666
1667 match_attributes! {ctx, a in attributes,
1668 "name" => name = Some(a.value),
1669 }
1670
1671 match_elements! {ctx, attributes,
1672 "enable" => if let Some(v) = parse_enable(ctx, attributes) {
1673 enables.push(v);
1674 },
1675 }
1676
1677 unwrap_attribute!(ctx, spirvcapability, name);
1678
1679 Some(SpirvCapability { name, enables })
1680}
1681
1682fn parse_enable<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> Option<Enable> {
1683 let mut version = None;
1684 let mut extension = None;
1685 let mut struct_ = None;
1686 let mut feature = None;
1687 let mut requires = None;
1688 let mut alias = None;
1689 let mut property = None;
1690 let mut member = None;
1691 let mut value = None;
1692
1693 match_attributes! {ctx, a in attributes,
1694 "version" => version = Some(a.value),
1695 "extension" => extension = Some(a.value),
1696 "struct" => struct_ = Some(a.value),
1697 "feature" => feature = Some(a.value),
1698 "requires" => requires = Some(a.value),
1699 "alias" => alias = Some(a.value),
1700 "property" => property = Some(a.value),
1701 "member" => member = Some(a.value),
1702 "value" => value = Some(a.value),
1703 }
1704
1705 consume_current_element(ctx);
1706
1707 if let Some(version) = version {
1708 Some(Enable::Version(version))
1709 } else if let Some(extension) = extension {
1710 Some(Enable::Extension(extension))
1711 } else if let Some(struct_) = struct_ {
1712 unwrap_attribute!(ctx, enable, feature);
1713 Some(Enable::Feature(FeatureEnable {
1714 struct_,
1715 feature,
1716 requires,
1717 alias,
1718 }))
1719 } else if let Some(property) = property {
1720 unwrap_attribute!(ctx, enable, member);
1721 unwrap_attribute!(ctx, enable, value);
1722 Some(Enable::Property(PropertyEnable {
1723 property,
1724 member,
1725 value,
1726 requires,
1727 }))
1728 } else {
1729 unimplemented!();
1730 }
1731}
1732
1733fn parse_sync<R: Read>(ctx: &mut ParseCtx<R>, attributes: Vec<XmlAttribute>) -> RegistryChild {
1734 let mut comment = None;
1735 let mut children = Vec::new();
1736
1737 match_attributes! {ctx, a in attributes,
1738 "comment" => comment = Some(a.value),
1739 }
1740
1741 match_elements! {ctx, attributes,
1742 "syncstage" => if let Some(v) = parse_syncstage(ctx, attributes) {
1743 children.push(v);
1744 },
1745 "syncaccess" => if let Some(v) = parse_syncaccess(ctx, attributes) {
1746 children.push(v);
1747 },
1748 "syncpipeline" => if let Some(v) = parse_syncpipeline(ctx, attributes) {
1749 children.push(v);
1750 },
1751 }
1752
1753 RegistryChild::Sync(Sync { comment, children })
1754}
1755
1756fn parse_syncsupport<R: Read>(
1757 ctx: &mut ParseCtx<R>,
1758 attributes: Vec<XmlAttribute>,
1759) -> Option<SyncSupport> {
1760 let mut queues = None;
1761 let mut stage = None;
1762 match_attributes! { ctx, a in attributes,
1763 "queues" => queues = Some(a.value),
1764 "stage" => stage = Some(a.value),
1765 }
1766 consume_current_element(ctx);
1767 Some(SyncSupport { queues, stage })
1768}
1769
1770fn parse_syncequivalent<R: Read>(
1771 ctx: &mut ParseCtx<R>,
1772 attributes: Vec<XmlAttribute>,
1773) -> Option<SyncEquivalent> {
1774 let mut stage = None;
1775 let mut access = None;
1776 match_attributes! { ctx, a in attributes,
1777 "stage" => stage = Some(a.value),
1778 "access" => access = Some(a.value),
1779 }
1780 consume_current_element(ctx);
1781 Some(SyncEquivalent { stage, access })
1782}
1783
1784fn parse_syncstage<R: Read>(
1785 ctx: &mut ParseCtx<R>,
1786 attributes: Vec<XmlAttribute>,
1787) -> Option<SyncChild> {
1788 let mut name = None;
1789 let mut alias = None;
1790 let mut syncsupport = None;
1791 let mut syncequivalent = None;
1792
1793 match_attributes! { ctx, a in attributes,
1794 "name" => name = Some(a.value),
1795 "alias" => alias = Some(a.value),
1796 }
1797
1798 match_elements! {ctx, attributes,
1799 "syncsupport" => syncsupport = parse_syncsupport(ctx, attributes),
1800 "syncequivalent" => syncequivalent = parse_syncequivalent(ctx, attributes),
1801 }
1802
1803 unwrap_attribute!(ctx, syncstage, name);
1804
1805 Some(SyncChild::Stage(SyncStage {
1806 name,
1807 alias,
1808 syncsupport,
1809 syncequivalent,
1810 }))
1811}
1812
1813fn parse_syncaccess<R: Read>(
1814 ctx: &mut ParseCtx<R>,
1815 attributes: Vec<XmlAttribute>,
1816) -> Option<SyncChild> {
1817 let mut name = None;
1818 let mut alias = None;
1819 let mut comment = None;
1820 let mut syncsupport = None;
1821 let mut syncequivalent = None;
1822
1823 match_attributes! { ctx, a in attributes,
1824 "name" => name = Some(a.value),
1825 "alias" => alias = Some(a.value),
1826 }
1827
1828 match_elements! { ctx, attributes,
1829 "comment" => comment = Some(parse_text_element(ctx)),
1830 "syncsupport" => syncsupport = parse_syncsupport(ctx, attributes),
1831 "syncequivalent" => syncequivalent = parse_syncequivalent(ctx, attributes),
1832 }
1833
1834 unwrap_attribute!(ctx, syncaccess, name);
1835
1836 Some(SyncChild::Access(SyncAccess {
1837 name,
1838 alias,
1839 comment,
1840 syncsupport,
1841 syncequivalent,
1842 }))
1843}
1844
1845fn parse_syncpipeline<R: Read>(
1846 ctx: &mut ParseCtx<R>,
1847 attributes: Vec<XmlAttribute>,
1848) -> Option<SyncChild> {
1849 let mut name = None;
1850 let mut depends = None;
1851 let mut children = Vec::new();
1852
1853 match_attributes! {ctx, a in attributes,
1854 "name" => name = Some(a.value),
1855 "depends" => depends = Some(a.value),
1856 }
1857
1858 match_elements! { ctx, attributes,
1859 "syncpipelinestage" => if let Some(v) = parse_syncpipelinestage(ctx, attributes) {
1860 children.push(v);
1861 },
1862 }
1863
1864 unwrap_attribute!(ctx, syncpipeline, name);
1865
1866 Some(SyncChild::Pipeline(SyncPipeline {
1867 name,
1868 depends,
1869 children,
1870 }))
1871}
1872
1873fn parse_syncpipelinestage<R: Read>(
1874 ctx: &mut ParseCtx<R>,
1875 attributes: Vec<XmlAttribute>,
1876) -> Option<SyncPipelineStage> {
1877 let mut order = None;
1878 let mut before = None;
1879 let mut after = None;
1880 match_attributes! {ctx, a in attributes,
1881 "order" => order = Some(a.value),
1882 "before" => before = Some(a.value),
1883 "after" => after = Some(a.value),
1884 }
1885
1886 let text = parse_text_element(ctx);
1887
1888 Some(SyncPipelineStage {
1889 order,
1890 before,
1891 after,
1892 text,
1893 })
1894}
1895
1896fn parse_videocodecs<R: Read>(
1897 ctx: &mut ParseCtx<R>,
1898 attributes: Vec<XmlAttribute>,
1899) -> RegistryChild {
1900 let mut comment = None;
1901 let mut children = Vec::new();
1902
1903 match_attributes! {ctx, a in attributes,
1904 "comment" => comment = Some(a.value),
1905 }
1906
1907 match_elements! {ctx, attributes,
1908 "videocodec" => if let Some(v) = parse_videocodec(ctx, attributes) {
1909 children.push(v);
1910 },
1911 }
1912
1913 RegistryChild::VideoCodecs(VideoCodecs { comment, children })
1914}
1915
1916fn parse_videocodec<R: Read>(
1917 ctx: &mut ParseCtx<R>,
1918 attributes: Vec<XmlAttribute>,
1919) -> Option<VideoCodec> {
1920 let mut comment = None;
1921 let mut name = None;
1922 let mut extend = None;
1923 let mut value = None;
1924 let mut children = Vec::new();
1925
1926 match_attributes! {ctx, a in attributes,
1927 "comment" => comment = Some(a.value),
1928 "name" => name = Some(a.value),
1929 "extend" => extend = Some(a.value),
1930 "value" => value = Some(a.value),
1931 }
1932
1933 match_elements! {ctx, attributes,
1934 "videoprofiles" => if let Some(v) = parse_videoprofiles(ctx, attributes) {
1935 children.push(VideoCodecChild::Profiles(v));
1936 },
1937 "videocapabilities" => if let Some(v) = parse_videocapabilities(ctx, attributes) {
1938 children.push(VideoCodecChild::Capabilities(v));
1939 },
1940 "videoformat" => if let Some(v) = parse_videoformat(ctx, attributes) {
1941 children.push(VideoCodecChild::Format(v));
1942 },
1943 }
1944
1945 unwrap_attribute!(ctx, videocodec, name);
1946
1947 Some(VideoCodec {
1948 comment,
1949 name,
1950 extend,
1951 value,
1952 children,
1953 })
1954}
1955
1956fn parse_videoprofiles<R: Read>(
1957 ctx: &mut ParseCtx<R>,
1958 attributes: Vec<XmlAttribute>,
1959) -> Option<VideoProfiles> {
1960 let mut comment = None;
1961 let mut struct_ = None;
1962 let mut children = Vec::new();
1963
1964 match_attributes! {ctx, a in attributes,
1965 "comment" => comment = Some(a.value),
1966 "struct" => struct_ = Some(a.value),
1967 }
1968
1969 match_elements! {ctx, attributes,
1970 "videoprofilemember" => if let Some(v) = parse_videoprofilemember(ctx, attributes) {
1971 children.push(v);
1972 },
1973 }
1974
1975 unwrap_attribute!(ctx, videoprofiles, struct_, "struct");
1976
1977 Some(VideoProfiles {
1978 comment,
1979 struct_,
1980 children,
1981 })
1982}
1983
1984fn parse_videoprofilemember<R: Read>(
1985 ctx: &mut ParseCtx<R>,
1986 attributes: Vec<XmlAttribute>,
1987) -> Option<VideoProfileMember> {
1988 let mut comment = None;
1989 let mut name = None;
1990 let mut children = Vec::new();
1991
1992 match_attributes! {ctx, a in attributes,
1993 "comment" => comment = Some(a.value),
1994 "name" => name = Some(a.value),
1995 }
1996
1997 match_elements! {ctx, attributes,
1998 "videoprofile" => if let Some(v) = parse_videoprofile(ctx, attributes) {
1999 children.push(v);
2000 },
2001 }
2002
2003 unwrap_attribute!(ctx, videoprofilemember, name);
2004
2005 Some(VideoProfileMember {
2006 comment,
2007 name,
2008 children,
2009 })
2010}
2011
2012fn parse_videoprofile<R: Read>(
2013 ctx: &mut ParseCtx<R>,
2014 attributes: Vec<XmlAttribute>,
2015) -> Option<VideoProfile> {
2016 let mut comment = None;
2017 let mut name = None;
2018 let mut value = None;
2019
2020 match_attributes! {ctx, a in attributes,
2021 "comment" => comment = Some(a.value),
2022 "name" => name = Some(a.value),
2023 "value" => value = Some(a.value),
2024 }
2025
2026 consume_current_element(ctx);
2027
2028 unwrap_attribute!(ctx, videoprofile, name);
2029 unwrap_attribute!(ctx, videoprofile, value);
2030
2031 Some(VideoProfile {
2032 comment,
2033 name,
2034 value,
2035 })
2036}
2037
2038fn parse_videocapabilities<R: Read>(
2039 ctx: &mut ParseCtx<R>,
2040 attributes: Vec<XmlAttribute>,
2041) -> Option<VideoCapabilities> {
2042 let mut comment = None;
2043 let mut struct_ = None;
2044
2045 match_attributes! {ctx, a in attributes,
2046 "comment" => comment = Some(a.value),
2047 "struct" => struct_ = Some(a.value),
2048 }
2049
2050 consume_current_element(ctx);
2051
2052 unwrap_attribute!(ctx, videocapabilities, struct_, "struct");
2053
2054 Some(VideoCapabilities { comment, struct_ })
2055}
2056
2057fn parse_videoformat<R: Read>(
2058 ctx: &mut ParseCtx<R>,
2059 attributes: Vec<XmlAttribute>,
2060) -> Option<VideoFormat> {
2061 let mut comment = None;
2062 let mut name = None;
2063 let mut usage = None;
2064 let mut extend = None;
2065 let mut children = Vec::new();
2066
2067 match_attributes! {ctx, a in attributes,
2068 "comment" => comment = Some(a.value),
2069 "name" => name = Some(a.value),
2070 "usage" => usage = Some(a.value),
2071 "extend" => extend = Some(a.value),
2072 }
2073
2074 match_elements! {ctx, attributes,
2075 "videorequirecapabilities" => if let Some(v) = parse_videorequirecapabilities(ctx, attributes) {
2076 children.push(VideoFormatChild::RequireCapabilities(v));
2077 },
2078 "videoformatproperties" => if let Some(v) = parse_videoformatproperties(ctx, attributes) {
2079 children.push(VideoFormatChild::FormatProperties(v));
2080 },
2081 }
2082
2083 Some(VideoFormat {
2084 comment,
2085 name,
2086 usage,
2087 extend,
2088 children,
2089 })
2090}
2091
2092fn parse_videoformatproperties<R: Read>(
2093 ctx: &mut ParseCtx<R>,
2094 attributes: Vec<XmlAttribute>,
2095) -> Option<VideoFormatProperties> {
2096 let mut comment = None;
2097 let mut struct_ = None;
2098
2099 match_attributes! {ctx, a in attributes,
2100 "comment" => comment = Some(a.value),
2101 "struct" => struct_ = Some(a.value),
2102 }
2103
2104 consume_current_element(ctx);
2105
2106 unwrap_attribute!(ctx, videoformatproperties, struct_, "struct");
2107
2108 Some(VideoFormatProperties { comment, struct_ })
2109}
2110
2111fn parse_videorequirecapabilities<R: Read>(
2112 ctx: &mut ParseCtx<R>,
2113 attributes: Vec<XmlAttribute>,
2114) -> Option<VideoRequireCapabilities> {
2115 let mut comment = None;
2116 let mut struct_ = None;
2117 let mut member = None;
2118 let mut value = None;
2119
2120 match_attributes! {ctx, a in attributes,
2121 "comment" => comment = Some(a.value),
2122 "struct" => struct_ = Some(a.value),
2123 "member" => member = Some(a.value),
2124 "value" => value = Some(a.value),
2125 }
2126
2127 consume_current_element(ctx);
2128
2129 unwrap_attribute!(ctx, videorequirecapabilities, struct_, "struct");
2130 unwrap_attribute!(ctx, videorequirecapabilities, member);
2131 unwrap_attribute!(ctx, videorequirecapabilities, value);
2132
2133 Some(VideoRequireCapabilities {
2134 comment,
2135 struct_,
2136 member,
2137 value,
2138 })
2139}
2140
2141fn parse_name_with_type<R: Read>(
2142 ctx: &mut ParseCtx<R>,
2143 buffer: &mut String,
2144) -> Option<NameWithType> {
2145 let mut name = None;
2146 let mut type_name = None;
2147 let mut code = String::new();
2148 match_elements_combine_text! {ctx, code,
2149 "type" => {
2150 let text = parse_text_element(ctx);
2151 code.push_str(&text);
2152 type_name = Some(text);
2153 },
2154 "name" => {
2155 let text = parse_text_element(ctx);
2156 code.push_str(&text);
2157 name = Some(text);
2158 }
2159 }
2160 let name = if let Some(v) = name {
2161 v
2162 } else {
2163 ctx.errors.push(Error::MissingElement {
2164 xpath: ctx.xpath.clone(),
2165 name: String::from("name"),
2166 });
2167 return None;
2168 };
2169
2170 buffer.push_str(&code);
2171 Some(NameWithType {
2172 name,
2173 type_name,
2174 code,
2175 })
2176}
2177
2178fn parse_integer<R: Read>(ctx: &mut ParseCtx<R>, text: &str) -> Option<i64> {
2179 let parse_res = if text.starts_with("0x") {
2180 i64::from_str_radix(text.split_at(2).1, 16)
2181 } else {
2182 i64::from_str_radix(text, 10)
2183 };
2184
2185 if let Ok(v) = parse_res {
2186 Some(v)
2187 } else {
2188 ctx.errors.push(Error::SchemaViolation {
2189 xpath: ctx.xpath.clone(),
2190 desc: format!("Value '{}' is not valid base 10 or 16 integer.", text),
2191 });
2192 None
2193 }
2194}
2195
2196fn parse_int_attribute<I: FromStr<Err = std::num::ParseIntError>, R: Read>(
2197 ctx: &mut ParseCtx<R>,
2198 text: String,
2199 attribute_name: &str,
2200) -> Option<I> {
2201 match I::from_str(&text) {
2202 Ok(v) => Some(v),
2203 Err(e) => {
2204 ctx.errors.push(Error::ParseIntError {
2205 xpath: xpath_attribute(&ctx.xpath, attribute_name),
2206 text: text,
2207 error: e,
2208 });
2209 None
2210 }
2211 }
2212}
2213
2214fn consume_current_element<R: Read>(ctx: &mut ParseCtx<R>) {
2215 let mut depth = 1;
2216 while let Some(Ok(e)) = ctx.events.next() {
2217 match e {
2218 XmlEvent::StartElement { name, .. } => {
2219 ctx.push_element(name.local_name.as_str());
2220 depth += 1;
2221 }
2222 XmlEvent::EndElement { .. } => {
2223 depth -= 1;
2224 ctx.pop_element();
2225 if depth == 0 {
2226 break;
2227 }
2228 }
2229 _ => (),
2230 }
2231 }
2232}
2233
2234fn parse_text_element<R: Read>(ctx: &mut ParseCtx<R>) -> String {
2235 let mut result = String::new();
2236 let mut depth = 1;
2237 while let Some(Ok(e)) = ctx.events.next() {
2238 match e {
2239 XmlEvent::StartElement { name, .. } => {
2240 ctx.push_element(name.local_name.as_str());
2241 depth += 1;
2242 }
2243 XmlEvent::Characters(text) => result.push_str(&text),
2244 XmlEvent::EndElement { .. } => {
2245 depth -= 1;
2246 ctx.pop_element();
2247 if depth == 0 {
2248 break;
2249 }
2250 }
2251 _ => (),
2252 }
2253 }
2254 result
2255}