1use 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: MxmlName,
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<MxmlName>,
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 MxmlName {
57 pub location: Location,
58 pub prefix: Option<String>,
60 pub name: String,
61}
62
63impl MxmlName {
64 pub fn resolve_prefix(&self, namespace: &Rc<MxmlNamespace>) -> Result<String, MxmlNameError> {
65 let Some(p) = self.prefix.as_ref() else {
66 return if let Some(v) = namespace.get(MxmlNamespace::DEFAULT_NAMESPACE) {
67 Ok(v)
68 } else {
69 Err(MxmlNameError::PrefixNotDefined(MxmlNamespace::DEFAULT_NAMESPACE.into()))
70 };
71 };
72 if let Some(v) = namespace.get(p) {
73 Ok(v)
74 } else {
75 Err(MxmlNameError::PrefixNotDefined(p.clone()))
76 }
77 }
78
79 pub fn resolve_name(&self, namespace: &Rc<MxmlNamespace>) -> Result<(String, String), MxmlNameError> {
80 let p = self.resolve_prefix(namespace)?;
81 Ok((p, self.name.clone()))
82 }
83
84 pub fn equals_name(&self, other: &Self, namespace: &Rc<MxmlNamespace>) -> Result<bool, MxmlNameError> {
85 if self.name != other.name {
86 return Ok(false);
87 }
88 let p1 = self.resolve_prefix(namespace)?;
89 let p2 = other.resolve_prefix(namespace)?;
90 Ok(&p1 == &p2)
91 }
92
93 pub fn to_string(&self, namespace: &Rc<MxmlNamespace>) -> String {
94 self.resolve_name(namespace).map(|(uri, localname)| {
95 if uri.is_empty() {
96 return localname;
97 }
98 format!("{uri}:{localname}")
99 }).unwrap_or("[error]".into())
100 }
101}
102
103#[derive(Clone)]
104pub enum MxmlNameError {
105 PrefixNotDefined(String),
106}
107
108#[derive(Clone, Serialize, Deserialize)]
109pub enum MxmlContent {
110 Characters((String, Location)),
111 CData((String, Location)),
114 Comment((String, Location)),
117 ProcessingInstruction {
118 location: Location,
119 name: String,
120 data: Option<String>,
121 },
122 Element(Rc<MxmlElement>),
123}
124
125impl MxmlContent {
126 pub fn location(&self) -> Location {
127 match self {
128 Self::Characters((_, l)) => l.clone(),
129 Self::CData((_, l)) => l.clone(),
130 Self::Comment((_, l)) => l.clone(),
131 Self::ProcessingInstruction { location: l, .. } => l.clone(),
132 Self::Element(e) => e.location.clone(),
133 }
134 }
135
136 pub fn inner_text(&self) -> String {
137 match self {
138 Self::Characters((data, _)) => data.clone(),
139 Self::CData((data, _)) => data["<![CDATA[".len()..(data.len() - 3)].to_owned(),
140 Self::Comment(_) => String::new(),
141 Self::ProcessingInstruction { .. } => String::new(),
142 Self::Element(e) => e.inner_text(),
143 }
144 }
145}
146
147#[derive(Clone, PartialEq)]
149pub struct MxmlNamespace {
150 parent: Option<Rc<MxmlNamespace>>,
151 mappings: RefCell<BTreeMap<String, String>>,
152}
153
154impl Default for MxmlNamespace {
155 fn default() -> Self {
156 Self::new(None)
157 }
158}
159
160impl MxmlNamespace {
161 pub const DEFAULT_NAMESPACE: &'static str = "";
163
164 pub fn new(parent: Option<&Rc<MxmlNamespace>>) -> Self {
166 let mut ns = Self {
167 parent: parent.map(|p| p.clone()),
168 mappings: RefCell::new(BTreeMap::new()),
169 };
170 if ns.parent.is_none() {
171 ns.mappings.get_mut().insert(Self::DEFAULT_NAMESPACE.into(), "".into());
172 ns.mappings.get_mut().insert("xmlns".into(), "http://www.w3.org/xml/xmlns".into());
173 }
174 ns
175 }
176
177 pub fn includes(&self, prefix: &str) -> bool {
178 self.mappings.borrow().contains_key(prefix) || match &self.parent {
179 Some(p) => p.includes(prefix),
180 None => false,
181 }
182 }
183
184 pub fn get(&self, prefix: &str) -> Option<String> {
187 if let Some(value) = self.mappings.borrow().get(prefix) {
188 return Some(value.clone());
189 }
190 self.parent.as_ref().and_then(|p| p.get(prefix))
191 }
192
193 pub fn set(&self, prefix: &str, value: &str) {
194 self.mappings.borrow_mut().insert(prefix.to_owned(), value.to_owned());
195 }
196
197 pub fn delete(&self, prefix: &str) -> bool {
198 self.mappings.borrow_mut().remove(prefix).is_some()
199 }
200
201 pub fn clear(&self) {
202 self.mappings.borrow_mut().clear();
203 }
204
205 pub fn listing(&self) -> BTreeMap<String, String> {
207 self.mappings.borrow().clone()
208 }
209
210 pub fn full_listing(&self) -> BTreeMap<String, String> {
213 let mut listing = self.parent.as_ref().map_or(BTreeMap::new(), |p| p.full_listing());
214 listing.extend(self.listing());
215 listing
216 }
217}