1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use common::XmlVersion;
use reader::events::XmlEvent;
use reader::lexer::Token;
use super::{
Result, PullParser, State, DeclarationSubstate, QualifiedNameTarget,
DEFAULT_VERSION, DEFAULT_ENCODING
};
impl PullParser {
pub fn inside_declaration(&mut self, t: Token, s: DeclarationSubstate) -> Option<Result> {
macro_rules! unexpected_token(
($this:expr; $t:expr) => (Some($this.error(format!("Unexpected token inside XML declaration: {}", $t))));
($t:expr) => (unexpected_token!(self; $t));
);
#[inline]
fn emit_start_document(this: &mut PullParser) -> Option<Result> {
this.parsed_declaration = true;
let version = this.data.take_version();
let encoding = this.data.take_encoding();
let standalone = this.data.take_standalone();
this.into_state_emit(State::OutsideTag, Ok(XmlEvent::StartDocument {
version: version.unwrap_or(DEFAULT_VERSION),
encoding: encoding.unwrap_or(DEFAULT_ENCODING.into()),
standalone: standalone
}))
}
match s {
DeclarationSubstate::BeforeVersion => match t {
Token::Whitespace(_) => None,
Token::Character('v') => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideVersion)),
_ => unexpected_token!(t)
},
DeclarationSubstate::InsideVersion => self.read_qualified_name(t, QualifiedNameTarget::AttributeNameTarget, |this, token, name| {
match &name.local_name[..] {
"ersion" if name.namespace.is_none() =>
this.into_state_continue(State::InsideDeclaration(
if token == Token::EqualsSign {
DeclarationSubstate::InsideVersionValue
} else {
DeclarationSubstate::AfterVersion
}
)),
_ => unexpected_token!(this; name)
}
}),
DeclarationSubstate::AfterVersion => match t {
Token::Whitespace(_) => None,
Token::EqualsSign => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideVersionValue)),
_ => unexpected_token!(t)
},
DeclarationSubstate::InsideVersionValue => self.read_attribute_value(t, |this, value| {
this.data.version = match &value[..] {
"1.0" => Some(XmlVersion::Version10),
"1.1" => Some(XmlVersion::Version11),
_ => None
};
if this.data.version.is_some() {
this.into_state_continue(State::InsideDeclaration(DeclarationSubstate::AfterVersionValue))
} else {
Some(self_error!(this; "Unexpected XML version value: {}", value))
}
}),
DeclarationSubstate::AfterVersionValue => match t {
Token::Whitespace(_) => None,
Token::Character('e') => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideEncoding)),
Token::Character('s') => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideStandaloneDecl)),
Token::ProcessingInstructionEnd => emit_start_document(self),
_ => unexpected_token!(t)
},
DeclarationSubstate::InsideEncoding => self.read_qualified_name(t, QualifiedNameTarget::AttributeNameTarget, |this, token, name| {
match &name.local_name[..] {
"ncoding" if name.namespace.is_none() =>
this.into_state_continue(State::InsideDeclaration(
if token == Token::EqualsSign { DeclarationSubstate::InsideEncodingValue } else { DeclarationSubstate::AfterEncoding }
)),
_ => unexpected_token!(this; name)
}
}),
DeclarationSubstate::AfterEncoding => match t {
Token::Whitespace(_) => None,
Token::EqualsSign => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideEncodingValue)),
_ => unexpected_token!(t)
},
DeclarationSubstate::InsideEncodingValue => self.read_attribute_value(t, |this, value| {
this.data.encoding = Some(value);
this.into_state_continue(State::InsideDeclaration(DeclarationSubstate::BeforeStandaloneDecl))
}),
DeclarationSubstate::BeforeStandaloneDecl => match t {
Token::Whitespace(_) => None,
Token::Character('s') => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideStandaloneDecl)),
Token::ProcessingInstructionEnd => emit_start_document(self),
_ => unexpected_token!(t)
},
DeclarationSubstate::InsideStandaloneDecl => self.read_qualified_name(t, QualifiedNameTarget::AttributeNameTarget, |this, token, name| {
match &name.local_name[..] {
"tandalone" if name.namespace.is_none() =>
this.into_state_continue(State::InsideDeclaration(
if token == Token::EqualsSign {
DeclarationSubstate::InsideStandaloneDeclValue
} else {
DeclarationSubstate::AfterStandaloneDecl
}
)),
_ => unexpected_token!(this; name)
}
}),
DeclarationSubstate::AfterStandaloneDecl => match t {
Token::Whitespace(_) => None,
Token::EqualsSign => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideStandaloneDeclValue)),
_ => unexpected_token!(t)
},
DeclarationSubstate::InsideStandaloneDeclValue => self.read_attribute_value(t, |this, value| {
let standalone = match &value[..] {
"yes" => Some(true),
"no" => Some(false),
_ => None
};
if standalone.is_some() {
this.data.standalone = standalone;
this.into_state_continue(State::InsideDeclaration(DeclarationSubstate::AfterStandaloneDeclValue))
} else {
Some(self_error!(this; "Invalid standalone declaration value: {}", value))
}
}),
DeclarationSubstate::AfterStandaloneDeclValue => match t {
Token::Whitespace(_) => None,
Token::ProcessingInstructionEnd => emit_start_document(self),
_ => unexpected_token!(t)
}
}
}
}