xml/reader/parser/
inside_opening_tag.rs
1use crate::attribute::OwnedAttribute;
2use crate::common::{is_name_start_char, is_whitespace_char};
3use crate::namespace;
4use crate::reader::error::SyntaxError;
5
6use crate::reader::lexer::Token;
7
8use super::{OpeningTagSubstate, PullParser, QualifiedNameTarget, Result, State};
9
10impl PullParser {
11 pub fn inside_opening_tag(&mut self, t: Token, s: OpeningTagSubstate) -> Option<Result> {
12 let max_attrs = self.config.max_attributes;
13 match s {
14 OpeningTagSubstate::InsideName => self.read_qualified_name(t, QualifiedNameTarget::OpeningTagNameTarget, |this, token, name| {
15 match name.prefix_ref() {
16 Some(prefix) if prefix == namespace::NS_XML_PREFIX ||
17 prefix == namespace::NS_XMLNS_PREFIX =>
18 Some(this.error(SyntaxError::InvalidNamePrefix(prefix.into()))),
19 _ => {
20 this.data.element_name = Some(name.clone());
21 match token {
22 Token::TagEnd => this.emit_start_element(false),
23 Token::EmptyTagEnd => this.emit_start_element(true),
24 Token::Character(c) if is_whitespace_char(c) => this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideTag)),
25 _ => {
26 debug_assert!(false, "unreachable");
27 None
28 },
29 }
30 }
31 }
32 }),
33
34 OpeningTagSubstate::InsideTag => match t {
35 Token::TagEnd => self.emit_start_element(false),
36 Token::EmptyTagEnd => self.emit_start_element(true),
37 Token::Character(c) if is_whitespace_char(c) => None, Token::Character(c) if is_name_start_char(c) => {
39 if self.buf.len() > self.config.max_name_length {
40 return Some(self.error(SyntaxError::ExceededConfiguredLimit));
41 }
42 self.buf.push(c);
43 self.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideAttributeName))
44 },
45 _ => Some(self.error(SyntaxError::UnexpectedTokenInOpeningTag(t))),
46 },
47
48 OpeningTagSubstate::InsideAttributeName => self.read_qualified_name(t, QualifiedNameTarget::AttributeNameTarget, |this, token, name| {
49 if this.data.attributes.contains(&name) {
52 return Some(this.error(SyntaxError::RedefinedAttribute(name.to_string().into())))
53 }
54
55 this.data.attr_name = Some(name);
56 match token {
57 Token::EqualsSign => this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideAttributeValue)),
58 Token::Character(c) if is_whitespace_char(c) => this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeName)),
59 _ => Some(this.error(SyntaxError::UnexpectedTokenInOpeningTag(t))) }
61 }),
62
63 OpeningTagSubstate::AfterAttributeName => match t {
64 Token::EqualsSign => self.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideAttributeValue)),
65 Token::Character(c) if is_whitespace_char(c) => None,
66 _ => Some(self.error(SyntaxError::UnexpectedTokenInOpeningTag(t)))
67 },
68
69 OpeningTagSubstate::InsideAttributeValue => self.read_attribute_value(t, |this, value| {
70 let name = this.data.take_attr_name()?; match name.prefix_ref() {
72 Some(namespace::NS_XMLNS_PREFIX) => {
75 let ln = &*name.local_name;
76 if ln == namespace::NS_XMLNS_PREFIX {
77 Some(this.error(SyntaxError::CannotRedefineXmlnsPrefix))
78 } else if ln == namespace::NS_XML_PREFIX && &*value != namespace::NS_XML_URI {
79 Some(this.error(SyntaxError::CannotRedefineXmlPrefix))
80 } else if value.is_empty() {
81 Some(this.error(SyntaxError::CannotUndefinePrefix(ln.into())))
82 } else {
83 this.nst.put(name.local_name.clone(), value);
84 this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeValue))
85 }
86 },
87
88 None if &*name.local_name == namespace::NS_XMLNS_PREFIX =>
90 match &*value {
91 namespace::NS_XMLNS_PREFIX | namespace::NS_XML_PREFIX | namespace::NS_XML_URI | namespace::NS_XMLNS_URI =>
92 Some(this.error(SyntaxError::InvalidDefaultNamespace(value.into()))),
93 _ => {
94 this.nst.put(namespace::NS_NO_PREFIX, value.clone());
95 this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeValue))
96 }
97 },
98
99 _ => {
101 if this.data.attributes.len() >= max_attrs {
102 return Some(this.error(SyntaxError::ExceededConfiguredLimit));
103 }
104 this.data.attributes.push(OwnedAttribute { name, value });
105 this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeValue))
106 },
107 }
108 }),
109
110 OpeningTagSubstate::AfterAttributeValue => match t {
111 Token::Character(c) if is_whitespace_char(c) => {
112 self.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideTag))
113 },
114 Token::TagEnd => self.emit_start_element(false),
115 Token::EmptyTagEnd => self.emit_start_element(true),
116 _ => Some(self.error(SyntaxError::UnexpectedTokenInOpeningTag(t))),
117 },
118 }
119 }
120}