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