mxmlextrema_as3parser/tree/
mxml.rs1use std::collections::BTreeMap;
2
3use crate::ns::*;
4use serde::{Serialize, Deserialize};
5
6#[derive(Clone, Serialize, Deserialize)]
7pub struct Mxml {
8 pub location: Location,
9 pub version: XmlVersion,
10 pub encoding: String,
11 pub content: Vec<Rc<MxmlContent>>,
12}
13
14#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
15pub enum XmlVersion {
16 Version10,
18}
19
20#[derive(Clone, Serialize, Deserialize)]
21pub struct MxmlElement {
22 pub location: Location,
23 pub name: MxmlTagName,
24 pub attributes: Vec<Rc<MxmlAttribute>>,
26 #[serde(skip)]
28 pub namespace: Rc<MxmlNamespace>,
29 pub content: Option<Vec<Rc<MxmlContent>>>,
30 pub closing_name: Option<MxmlTagName>,
31}
32
33impl MxmlElement {
34 pub fn inner_text(&self) -> String {
35 let mut j = String::new();
36 if let Some(c) = self.content.as_ref() {
37 for c1 in c.iter() {
38 j.push_str(&c1.inner_text());
39 }
40 }
41 j
42 }
43}
44
45#[derive(Clone, Serialize, Deserialize)]
46pub struct MxmlAttribute {
47 pub location: Location,
48 pub xmlns: bool,
50 pub name: MxmlName,
51 pub value: (String, Location),
53}
54
55#[derive(Clone, Serialize, Deserialize)]
56pub struct MxmlTagName {
57 pub location: Location,
58 pub prefix: Option<String>,
60 pub name: String,
61}
62
63#[derive(Clone, Serialize, Deserialize)]
64pub struct MxmlName {
65 pub location: Location,
66 pub prefix: Option<String>,
68 pub name: String,
69}
70
71impl MxmlTagName {
72 pub fn resolve_prefix(&self, namespace: &Rc<MxmlNamespace>) -> Result<String, MxmlNameError> {
73 let Some(p) = self.prefix.as_ref() else {
74 return if let Some(v) = namespace.get(MxmlNamespace::DEFAULT_NAMESPACE) {
75 Ok(v)
76 } else {
77 Err(MxmlNameError::PrefixNotDefined(MxmlNamespace::DEFAULT_NAMESPACE.into()))
78 };
79 };
80 if let Some(v) = namespace.get(p) {
81 Ok(v)
82 } else {
83 Err(MxmlNameError::PrefixNotDefined(p.clone()))
84 }
85 }
86
87 pub fn resolve_name(&self, namespace: &Rc<MxmlNamespace>) -> Result<(String, String), MxmlNameError> {
88 let p = self.resolve_prefix(namespace)?;
89 Ok((p, self.name.clone()))
90 }
91
92 pub fn equals_name(&self, other: &Self, namespace: &Rc<MxmlNamespace>) -> Result<bool, MxmlNameError> {
93 if self.name != other.name {
94 return Ok(false);
95 }
96 let p1 = self.resolve_prefix(namespace)?;
97 let p2 = other.resolve_prefix(namespace)?;
98 Ok(&p1 == &p2)
99 }
100
101 pub fn to_string(&self, namespace: &Rc<MxmlNamespace>) -> String {
102 self.resolve_name(namespace).map(|(uri, localname)| {
103 if uri.is_empty() {
104 return localname;
105 }
106 format!("{uri}:{localname}")
107 }).unwrap_or("[error]".into())
108 }
109}
110
111impl MxmlName {
112 pub fn resolve_prefix(&self, namespace: &Rc<MxmlNamespace>) -> Result<String, MxmlNameError> {
113 let Some(p) = self.prefix.as_ref() else {
114 return Ok(MxmlNamespace::DEFAULT_NAMESPACE.to_owned());
115 };
116 if let Some(v) = namespace.get(p) {
117 Ok(v)
118 } else {
119 Err(MxmlNameError::PrefixNotDefined(p.clone()))
120 }
121 }
122
123 pub fn resolve_name(&self, namespace: &Rc<MxmlNamespace>) -> Result<(String, String), MxmlNameError> {
124 let p = self.resolve_prefix(namespace)?;
125 Ok((p, self.name.clone()))
126 }
127
128 pub fn equals_name(&self, other: &Self, namespace: &Rc<MxmlNamespace>) -> Result<bool, MxmlNameError> {
129 if self.name != other.name {
130 return Ok(false);
131 }
132 let p1 = self.resolve_prefix(namespace)?;
133 let p2 = other.resolve_prefix(namespace)?;
134 Ok(&p1 == &p2)
135 }
136
137 pub fn to_string(&self, namespace: &Rc<MxmlNamespace>) -> String {
138 self.resolve_name(namespace).map(|(uri, localname)| {
139 if uri.is_empty() {
140 return localname;
141 }
142 format!("{uri}:{localname}")
143 }).unwrap_or("[error]".into())
144 }
145}
146
147#[derive(Clone)]
148pub enum MxmlNameError {
149 PrefixNotDefined(String),
150}
151
152#[derive(Clone, Serialize, Deserialize)]
153pub enum MxmlContent {
154 Characters((String, Location)),
155 CData((String, Location)),
158 Comment((String, Location)),
161 ProcessingInstruction {
162 location: Location,
163 name: String,
164 data: Option<String>,
165 },
166 Element(Rc<MxmlElement>),
167}
168
169impl MxmlContent {
170 pub fn location(&self) -> Location {
171 match self {
172 Self::Characters((_, l)) => l.clone(),
173 Self::CData((_, l)) => l.clone(),
174 Self::Comment((_, l)) => l.clone(),
175 Self::ProcessingInstruction { location: l, .. } => l.clone(),
176 Self::Element(e) => e.location.clone(),
177 }
178 }
179
180 pub fn inner_text(&self) -> String {
181 match self {
182 Self::Characters((data, _)) => data.clone(),
183 Self::CData((data, _)) => data["<![CDATA[".len()..(data.len() - 3)].to_owned(),
184 Self::Comment(_) => String::new(),
185 Self::ProcessingInstruction { .. } => String::new(),
186 Self::Element(e) => e.inner_text(),
187 }
188 }
189}
190
191#[derive(Clone, PartialEq)]
193pub struct MxmlNamespace {
194 parent: Option<Rc<MxmlNamespace>>,
195 mappings: RefCell<BTreeMap<String, String>>,
196}
197
198impl Default for MxmlNamespace {
199 fn default() -> Self {
200 Self::new(None)
201 }
202}
203
204impl MxmlNamespace {
205 pub const DEFAULT_NAMESPACE: &'static str = "";
207
208 pub fn new(parent: Option<&Rc<MxmlNamespace>>) -> Self {
210 let mut ns = Self {
211 parent: parent.map(|p| p.clone()),
212 mappings: RefCell::new(BTreeMap::new()),
213 };
214 if ns.parent.is_none() {
215 ns.mappings.get_mut().insert(Self::DEFAULT_NAMESPACE.into(), "".into());
216 ns.mappings.get_mut().insert("xmlns".into(), "http://www.w3.org/xml/xmlns".into());
217 }
218 ns
219 }
220
221 pub fn includes(&self, prefix: &str) -> bool {
222 self.mappings.borrow().contains_key(prefix) || match &self.parent {
223 Some(p) => p.includes(prefix),
224 None => false,
225 }
226 }
227
228 pub fn get(&self, prefix: &str) -> Option<String> {
231 if let Some(value) = self.mappings.borrow().get(prefix) {
232 return Some(value.clone());
233 }
234 self.parent.as_ref().and_then(|p| p.get(prefix))
235 }
236
237 pub fn set(&self, prefix: &str, value: &str) {
238 self.mappings.borrow_mut().insert(prefix.to_owned(), value.to_owned());
239 }
240
241 pub fn delete(&self, prefix: &str) -> bool {
242 self.mappings.borrow_mut().remove(prefix).is_some()
243 }
244
245 pub fn clear(&self) {
246 self.mappings.borrow_mut().clear();
247 }
248
249 pub fn listing(&self) -> BTreeMap<String, String> {
251 self.mappings.borrow().clone()
252 }
253
254 pub fn full_listing(&self) -> BTreeMap<String, String> {
257 let mut listing = self.parent.as_ref().map_or(BTreeMap::new(), |p| p.full_listing());
258 listing.extend(self.listing());
259 listing
260 }
261}