xee_interpreter/sequence/
item.rs1use xot::Xot;
2
3use crate::atomic;
4use crate::context;
5use crate::error;
6use crate::function;
7
8#[derive(Debug, Clone, PartialEq)]
10pub enum Item {
11 Atomic(atomic::Atomic),
16 Node(xot::Node),
20 Function(function::Function),
22}
23
24#[cfg(target_arch = "x86_64")]
26static_assertions::assert_eq_size!(Item, [u8; 24]);
27
28impl Item {
29 pub fn to_atomic(&self) -> error::Result<atomic::Atomic> {
31 match self {
32 Item::Atomic(a) => Ok(a.clone()),
33 _ => Err(error::Error::XPTY0004),
34 }
35 }
36
37 pub fn to_node(&self) -> error::Result<xot::Node> {
39 match self {
40 Item::Node(n) => Ok(*n),
41 _ => Err(error::Error::XPTY0004),
42 }
43 }
44
45 pub fn to_function(&self) -> error::Result<function::Function> {
47 match self {
48 Item::Function(f) => Ok(f.clone()),
49 _ => Err(error::Error::XPTY0004),
50 }
51 }
52
53 pub fn to_map(&self) -> error::Result<function::Map> {
55 if let Item::Function(function::Function::Map(map)) = self {
56 Ok(map.clone())
57 } else {
58 Err(error::Error::XPTY0004)
59 }
60 }
61
62 pub fn to_array(&self) -> error::Result<function::Array> {
64 if let Item::Function(function::Function::Array(array)) = self {
65 Ok(array.clone())
66 } else {
67 Err(error::Error::XPTY0004)
68 }
69 }
70
71 pub fn effective_boolean_value(&self) -> error::Result<bool> {
85 match self {
86 Item::Atomic(a) => a.effective_boolean_value(),
87 Item::Node(_) => Ok(true),
91 Item::Function(_) => Err(error::Error::FORG0006),
92 }
93 }
94
95 pub fn try_into_value<V>(&self) -> error::Result<V>
97 where
98 V: TryFrom<atomic::Atomic, Error = error::Error>,
99 {
100 match self {
101 Item::Atomic(a) => a.clone().try_into(),
102 _ => Err(error::Error::XPTY0004),
104 }
105 }
106
107 pub fn string_value(&self, xot: &Xot) -> error::Result<String> {
117 match self {
118 Item::Atomic(atomic) => Ok(atomic.string_value()),
119 Item::Node(node) => Ok(xot.string_value(*node)),
120 Item::Function(_) => Err(error::Error::FOTY0014),
121 }
122 }
123
124 pub fn display_representation(
129 &self,
130 xot: &Xot,
131 context: &context::DynamicContext,
132 ) -> error::Result<String> {
133 match self {
134 Item::Atomic(atomic) => Ok(atomic.xpath_representation()),
135 Item::Node(node) => node_display_representation(*node, xot),
136 Item::Function(function) => Ok(function.display_representation(xot, context)),
137 }
138 }
139
140 pub(crate) fn is_map(&self) -> bool {
142 match self {
143 Item::Function(function) => matches!(function, function::Function::Map(_)),
144 _ => false,
145 }
146 }
147
148 pub(crate) fn is_array(&self) -> bool {
150 match self {
151 Item::Function(function) => matches!(function, function::Function::Array(_)),
152 _ => false,
153 }
154 }
155}
156
157fn node_display_representation(node: xot::Node, xot: &Xot) -> error::Result<String> {
158 match xot.value(node) {
159 xot::Value::Attribute(attribute) => {
160 let value = attribute.value();
161 let (name, namespace) = xot.name_ns_str(attribute.name());
162 let name = if !namespace.is_empty() {
163 format!("Q{{{}}}{}", namespace, name)
164 } else {
165 name.to_string()
166 };
167 Ok(format!("Attribute {}=\"{}\"", name, value))
168 }
169 xot::Value::Namespace(namespace) => {
170 let prefix_id = namespace.prefix();
171 let namespace_id = namespace.namespace();
172 let prefix_str = xot.prefix_str(prefix_id);
173 let namespace_str = xot.namespace_str(namespace_id);
174 Ok(format!("Namespace {}:{}", prefix_str, namespace_str))
175 }
176 xot::Value::Text(text) => Ok(format!("Text \"{}\"", text.get())),
177 _ => Ok(xot.serialize_xml_string(
179 {
180 xot::output::xml::Parameters {
181 indentation: Default::default(),
182 ..Default::default()
183 }
184 },
185 node,
186 )?),
187 }
188}
189
190impl<T> From<T> for Item
191where
192 T: Into<atomic::Atomic>,
193{
194 fn from(a: T) -> Self {
195 Self::Atomic(a.into())
196 }
197}
198
199impl TryFrom<Item> for atomic::Atomic {
200 type Error = error::Error;
201
202 fn try_from(item: Item) -> error::Result<atomic::Atomic> {
203 match item {
204 Item::Atomic(a) => Ok(a),
205 _ => Err(error::Error::XPTY0004),
206 }
207 }
208}
209
210impl TryFrom<&Item> for atomic::Atomic {
211 type Error = error::Error;
212
213 fn try_from(item: &Item) -> error::Result<atomic::Atomic> {
214 match item {
215 Item::Atomic(a) => Ok(a.clone()),
216 _ => Err(error::Error::XPTY0004),
217 }
218 }
219}
220
221impl From<xot::Node> for Item {
222 fn from(node: xot::Node) -> Self {
223 Self::Node(node)
224 }
225}
226
227impl TryFrom<Item> for xot::Node {
228 type Error = error::Error;
229
230 fn try_from(item: Item) -> error::Result<Self> {
231 match item {
232 Item::Node(node) => Ok(node),
233 _ => Err(error::Error::XPTY0004),
234 }
235 }
236}
237
238impl TryFrom<&Item> for xot::Node {
239 type Error = error::Error;
240
241 fn try_from(item: &Item) -> error::Result<Self> {
242 match item {
243 Item::Node(node) => Ok(*node),
244 _ => Err(error::Error::XPTY0004),
245 }
246 }
247}
248
249impl TryFrom<Item> for function::Function {
250 type Error = error::Error;
251
252 fn try_from(item: Item) -> error::Result<Self> {
253 match item {
254 Item::Function(f) => Ok(f.clone()),
255 _ => Err(error::Error::XPTY0004),
256 }
257 }
258}
259
260impl TryFrom<&Item> for function::Function {
261 type Error = error::Error;
262
263 fn try_from(item: &Item) -> error::Result<Self> {
264 match item {
265 Item::Function(f) => Ok(f.clone()),
266 _ => Err(error::Error::XPTY0004),
267 }
268 }
269}
270
271impl From<function::Function> for Item {
272 fn from(f: function::Function) -> Self {
273 Self::Function(f)
274 }
275}
276
277impl From<function::Array> for Item {
278 fn from(array: function::Array) -> Self {
279 Self::Function(function::Function::Array(array))
280 }
281}
282
283impl From<function::Map> for Item {
284 fn from(map: function::Map) -> Self {
285 Self::Function(function::Function::Map(map))
286 }
287}
288
289pub enum AtomizedItemIter<'a> {
290 Atomic(std::iter::Once<atomic::Atomic>),
291 Node(std::iter::Once<atomic::Atomic>),
292 Array(AtomizedArrayIter<'a>),
293 Erroring(std::iter::Once<error::Result<atomic::Atomic>>),
295}
296
297impl<'a> AtomizedItemIter<'a> {
298 pub(crate) fn new(item: &'a Item, xot: &'a Xot) -> Self {
299 match item {
300 Item::Atomic(a) => Self::Atomic(std::iter::once(a.clone())),
301 Item::Node(n) => {
302 let s = xot.string_value(*n);
303 let value = atomic::Atomic::Untyped(s.into());
304 Self::Node(std::iter::once(value))
305 }
306 Item::Function(function) => match function {
307 function::Function::Array(a) => Self::Array(AtomizedArrayIter::new(a, xot)),
308 _ => Self::Erroring(std::iter::once(Err(error::Error::FOTY0013))),
309 },
310 }
311 }
312}
313
314impl Iterator for AtomizedItemIter<'_> {
315 type Item = error::Result<atomic::Atomic>;
316
317 fn next(&mut self) -> Option<Self::Item> {
318 match self {
319 Self::Atomic(iter) => iter.next().map(Ok),
320 Self::Node(iter) => iter.next().map(Ok),
321 Self::Array(iter) => iter.next(),
322 Self::Erroring(iter) => iter.next(),
323 }
324 }
325
326 fn size_hint(&self) -> (usize, Option<usize>) {
327 match self {
328 Self::Atomic(iter) => iter.size_hint(),
329 Self::Node(iter) => iter.size_hint(),
330 Self::Array(iter) => iter.size_hint(),
331 Self::Erroring(iter) => iter.size_hint(),
332 }
333 }
334}
335
336pub struct AtomizedArrayIter<'a> {
379 xot: &'a Xot,
380 array: &'a function::Array,
381 array_index: usize,
382 iter: Option<Box<dyn Iterator<Item = error::Result<atomic::Atomic>> + 'a>>,
383}
384
385impl<'a> AtomizedArrayIter<'a> {
386 fn new(array: &'a function::Array, xot: &'a Xot) -> Self {
387 Self {
388 xot,
389 array,
390 array_index: 0,
391 iter: None,
392 }
393 }
394}
395
396impl Iterator for AtomizedArrayIter<'_> {
397 type Item = error::Result<atomic::Atomic>;
398
399 fn next(&mut self) -> Option<Self::Item> {
400 loop {
401 if let Some(iter) = &mut self.iter {
404 if let Some(item) = iter.next() {
405 return Some(item);
406 } else {
407 self.iter = None;
408 }
409 }
410 let array = &self.array.0;
411 if self.array_index >= array.len() {
413 return None;
414 }
415 let sequence = &array[self.array_index];
416 self.array_index += 1;
417
418 self.iter = Some(Box::new(sequence.atomized(self.xot)));
419 }
420 }
421
422 fn size_hint(&self) -> (usize, Option<usize>) {
423 let remaining = self.array.0.len() - self.array_index;
428 (remaining, None)
429 }
430}