xee_interpreter/sequence/
core.rs

1// this is unfortunately a ridiculously verbose module, wiring everything up
2// carefully so we don't use performance due to dynamic dispatch on the inside.
3// The verbosity is all pretty straightforward though.
4
5// creation.rs contains various functions that create Sequence
6// compare.rs contains various comparison functions
7
8use xot::Xot;
9
10use crate::{
11    atomic::{self, AtomicCompare},
12    context, error, function,
13    string::Collation,
14    xml,
15};
16
17use super::{
18    item::Item,
19    traits::{BoxedItemIter, SequenceCompare, SequenceCore, SequenceExt, SequenceOrder},
20    variant::{Empty, Many, One, Range},
21};
22
23// The Sequence that goes onto the stack is the size of an single item, as
24// that's the biggest thing in it.
25#[derive(Debug, Clone, PartialEq)]
26pub enum Sequence {
27    Empty(Empty),
28    One(One),
29    Many(Many),
30    Range(Range),
31}
32
33impl From<Range> for Sequence {
34    fn from(inner: Range) -> Self {
35        Self::Range(inner)
36    }
37}
38
39// a static assertion to ensure that Sequence never grows in size
40#[cfg(target_arch = "x86_64")]
41static_assertions::assert_eq_size!(Sequence, [u8; 24]);
42
43impl Default for Sequence {
44    fn default() -> Self {
45        Self::Empty(Empty {})
46    }
47}
48
49impl Sequence {
50    /// Check whether the sequence is empty
51    pub fn is_empty(&self) -> bool {
52        match self {
53            Sequence::Empty(inner) => inner.is_empty(),
54            Sequence::One(inner) => inner.is_empty(),
55            Sequence::Many(inner) => inner.is_empty(),
56            Sequence::Range(inner) => inner.is_empty(),
57        }
58    }
59
60    /// Get the sequence length
61    pub fn len(&self) -> usize {
62        match self {
63            Sequence::Empty(inner) => inner.len(),
64            Sequence::One(inner) => inner.len(),
65            Sequence::Many(inner) => inner.len(),
66            Sequence::Range(inner) => inner.len(),
67        }
68    }
69
70    /// Get an item in the index, if it exists
71    pub fn get(&self, index: usize) -> Option<Item> {
72        match self {
73            Sequence::Empty(inner) => inner.get(index),
74            Sequence::One(inner) => inner.get(index),
75            Sequence::Many(inner) => inner.get(index),
76            Sequence::Range(inner) => inner.get(index),
77        }
78    }
79
80    /// Get a single item from the sequence, if it only contains one item
81    ///
82    /// Otherwise you get a type error.
83    pub fn one(self) -> error::Result<Item> {
84        match self {
85            Sequence::Empty(inner) => inner.one(),
86            Sequence::One(inner) => inner.one(),
87            Sequence::Many(inner) => inner.one(),
88            Sequence::Range(inner) => inner.one(),
89        }
90    }
91
92    /// Get a optional item from the sequence
93    ///
94    /// If it contains more than one item, you get a type error.
95    pub fn option(self) -> error::Result<Option<Item>> {
96        match self {
97            Sequence::Empty(inner) => inner.option(),
98            Sequence::One(inner) => inner.option(),
99            Sequence::Many(inner) => inner.option(),
100            Sequence::Range(inner) => inner.option(),
101        }
102    }
103
104    /// Get the items from the sequence as an iterator
105    pub fn iter(&self) -> BoxedItemIter {
106        match self {
107            Sequence::Empty(inner) => Box::new(inner.iter()),
108            Sequence::One(inner) => Box::new(inner.iter()),
109            Sequence::Many(inner) => Box::new(inner.iter()),
110            Sequence::Range(inner) => Box::new(inner.iter()),
111        }
112    }
113
114    /// Effective boolean value
115    pub fn effective_boolean_value(&self) -> error::Result<bool> {
116        match self {
117            Sequence::Empty(inner) => inner.effective_boolean_value(),
118            Sequence::One(inner) => inner.effective_boolean_value(),
119            Sequence::Many(inner) => inner.effective_boolean_value(),
120            Sequence::Range(inner) => inner.effective_boolean_value(),
121        }
122    }
123
124    /// String value
125    pub fn string_value(&self, xot: &xot::Xot) -> error::Result<String> {
126        match self {
127            Sequence::Empty(inner) => inner.string_value(xot),
128            Sequence::One(inner) => inner.string_value(xot),
129            Sequence::Many(inner) => inner.string_value(xot),
130            Sequence::Range(inner) => inner.string_value(xot),
131        }
132    }
133
134    /// Iterator over the nodes in the sequence
135    ///
136    /// An error is returned for items that are not a node.
137    pub fn nodes<'a>(&'a self) -> Box<dyn Iterator<Item = error::Result<xot::Node>> + 'a> {
138        match self {
139            Sequence::Empty(inner) => Box::new(inner.nodes()),
140            Sequence::One(inner) => Box::new(inner.nodes()),
141            Sequence::Many(inner) => Box::new(inner.nodes()),
142            Sequence::Range(inner) => Box::new(inner.nodes()),
143        }
144    }
145
146    /// Iterator for the atomized values in the sequence
147    pub fn atomized<'a>(
148        &'a self,
149        xot: &'a xot::Xot,
150    ) -> Box<dyn Iterator<Item = error::Result<atomic::Atomic>> + 'a> {
151        match self {
152            Sequence::Empty(inner) => Box::new(inner.atomized(xot)),
153            Sequence::One(inner) => Box::new(inner.atomized(xot)),
154            Sequence::Many(inner) => Box::new(inner.atomized(xot)),
155            Sequence::Range(inner) => Box::new(inner.atomized(xot)),
156        }
157    }
158
159    /// Get just one atomized value from the sequence
160    ///
161    /// If there are less or more, you get a type error.
162    pub fn atomized_one(&self, xot: &xot::Xot) -> error::Result<atomic::Atomic> {
163        match self {
164            Sequence::Empty(inner) => inner.atomized_one(xot),
165            Sequence::One(inner) => inner.atomized_one(xot),
166            Sequence::Many(inner) => inner.atomized_one(xot),
167            Sequence::Range(inner) => inner.atomized_one(xot),
168        }
169    }
170
171    /// Get an optional atomized value from the sequence
172    ///
173    /// If there are more than one, you get a type error.
174    pub fn atomized_option(&self, xot: &xot::Xot) -> error::Result<Option<atomic::Atomic>> {
175        match self {
176            Sequence::Empty(inner) => inner.atomized_option(xot),
177            Sequence::One(inner) => inner.atomized_option(xot),
178            Sequence::Many(inner) => inner.atomized_option(xot),
179            Sequence::Range(inner) => inner.atomized_option(xot),
180        }
181    }
182
183    /// Is used internally by the library macro.
184    pub(crate) fn unboxed_atomized<'a, T: 'a>(
185        &'a self,
186        xot: &'a xot::Xot,
187        extract: impl Fn(atomic::Atomic) -> error::Result<T> + 'a,
188    ) -> Box<dyn Iterator<Item = error::Result<T>> + 'a> {
189        match self {
190            Sequence::Empty(inner) => Box::new(inner.unboxed_atomized(xot, extract)),
191            Sequence::One(inner) => Box::new(inner.unboxed_atomized(xot, extract)),
192            Sequence::Many(inner) => Box::new(inner.unboxed_atomized(xot, extract)),
193            Sequence::Range(inner) => Box::new(inner.unboxed_atomized(xot, extract)),
194        }
195    }
196
197    /// Iterator over the XPath maps in the sequence
198    ///
199    /// An error is returned for items that are not a map.
200    pub fn map_iter<'a>(&'a self) -> Box<dyn Iterator<Item = error::Result<function::Map>> + 'a> {
201        match self {
202            Sequence::Empty(inner) => Box::new(inner.map_iter()),
203            Sequence::One(inner) => Box::new(inner.map_iter()),
204            Sequence::Many(inner) => Box::new(inner.map_iter()),
205            Sequence::Range(inner) => Box::new(inner.map_iter()),
206        }
207    }
208
209    /// Iterator over the XPath arrays in the sequence
210    ///
211    /// An error is returned for items that are not an array.
212    pub fn array_iter<'a>(
213        &'a self,
214    ) -> Box<dyn Iterator<Item = error::Result<function::Array>> + 'a> {
215        match self {
216            Sequence::Empty(inner) => Box::new(inner.array_iter()),
217            Sequence::One(inner) => Box::new(inner.array_iter()),
218            Sequence::Many(inner) => Box::new(inner.array_iter()),
219            Sequence::Range(inner) => Box::new(inner.array_iter()),
220        }
221    }
222
223    /// Oterator over elements nodes in the sequence
224    ///
225    /// An error is returned for items that are not an element.
226    pub fn elements<'a>(
227        &'a self,
228        xot: &'a xot::Xot,
229    ) -> error::Result<Box<dyn Iterator<Item = error::Result<xot::Node>> + 'a>> {
230        match self {
231            Sequence::Empty(inner) => Ok(Box::new(inner.elements(xot)?)),
232            Sequence::One(inner) => Ok(Box::new(inner.elements(xot)?)),
233            Sequence::Many(inner) => Ok(Box::new(inner.elements(xot)?)),
234            Sequence::Range(inner) => Ok(Box::new(inner.elements(xot)?)),
235        }
236    }
237
238    /// Create an XPath array from this sequence.
239    pub fn to_array(&self) -> error::Result<function::Array> {
240        match self {
241            Sequence::Empty(inner) => inner.to_array(),
242            Sequence::One(inner) => inner.to_array(),
243            Sequence::Many(inner) => inner.to_array(),
244            Sequence::Range(inner) => inner.to_array(),
245        }
246    }
247
248    pub(crate) fn general_comparison<O>(
249        &self,
250        other: &Self,
251        op: O,
252        context: &context::DynamicContext,
253        xot: &xot::Xot,
254    ) -> error::Result<bool>
255    where
256        O: AtomicCompare,
257    {
258        match (self, other) {
259            (Sequence::Empty(_a), Sequence::Empty(_b)) => Ok(false),
260            (Sequence::Empty(_a), Sequence::One(_b)) => Ok(false),
261            (Sequence::Empty(_a), Sequence::Many(_b)) => Ok(false),
262            (Sequence::Empty(_a), Sequence::Range(_b)) => Ok(false),
263            (Sequence::One(_a), Sequence::Empty(_b)) => Ok(false),
264            (Sequence::One(a), Sequence::One(b)) => a.general_comparison(b, op, context, xot),
265            (Sequence::One(a), Sequence::Many(b)) => a.general_comparison(b, op, context, xot),
266            (Sequence::One(a), Sequence::Range(b)) => {
267                if let Item::Atomic(atomic::Atomic::Integer(_, i)) = a.item() {
268                    Ok(b.general_comparison_integer(i, O::value()))
269                } else {
270                    a.general_comparison(b, op, context, xot)
271                }
272            }
273            (Sequence::Many(_a), Sequence::Empty(_b)) => Ok(false),
274            (Sequence::Many(a), Sequence::One(b)) => a.general_comparison(b, op, context, xot),
275            (Sequence::Many(a), Sequence::Many(b)) => a.general_comparison(b, op, context, xot),
276            (Sequence::Many(a), Sequence::Range(b)) => a.general_comparison(b, op, context, xot),
277            (Sequence::Range(_a), Sequence::Empty(_b)) => Ok(false),
278            (Sequence::Range(a), Sequence::One(b)) => a.general_comparison(b, op, context, xot),
279            (Sequence::Range(a), Sequence::Many(b)) => a.general_comparison(b, op, context, xot),
280            (Sequence::Range(a), Sequence::Range(b)) => a.general_comparison(b, op, context, xot),
281        }
282    }
283
284    pub(crate) fn value_compare<O>(
285        &self,
286        other: &Self,
287        op: O,
288        collation: &Collation,
289        timezone: chrono::FixedOffset,
290        xot: &Xot,
291    ) -> error::Result<bool>
292    where
293        O: AtomicCompare,
294    {
295        match (self, other) {
296            (Sequence::Empty(a), Sequence::Empty(b)) => {
297                a.value_compare(b, op, collation, timezone, xot)
298            }
299            (Sequence::Empty(a), Sequence::One(b)) => {
300                a.value_compare(b, op, collation, timezone, xot)
301            }
302            (Sequence::Empty(a), Sequence::Many(b)) => {
303                a.value_compare(b, op, collation, timezone, xot)
304            }
305            (Sequence::Empty(a), Sequence::Range(b)) => {
306                a.value_compare(b, op, collation, timezone, xot)
307            }
308            (Sequence::One(a), Sequence::Empty(b)) => {
309                a.value_compare(b, op, collation, timezone, xot)
310            }
311            (Sequence::One(a), Sequence::One(b)) => {
312                a.value_compare(b, op, collation, timezone, xot)
313            }
314            (Sequence::One(a), Sequence::Many(b)) => {
315                a.value_compare(b, op, collation, timezone, xot)
316            }
317            (Sequence::One(a), Sequence::Range(b)) => {
318                a.value_compare(b, op, collation, timezone, xot)
319            }
320            (Sequence::Many(a), Sequence::Empty(b)) => {
321                a.value_compare(b, op, collation, timezone, xot)
322            }
323            (Sequence::Many(a), Sequence::One(b)) => {
324                a.value_compare(b, op, collation, timezone, xot)
325            }
326            (Sequence::Many(a), Sequence::Many(b)) => {
327                a.value_compare(b, op, collation, timezone, xot)
328            }
329            (Sequence::Many(a), Sequence::Range(b)) => {
330                a.value_compare(b, op, collation, timezone, xot)
331            }
332            (Sequence::Range(a), Sequence::Empty(b)) => {
333                a.value_compare(b, op, collation, timezone, xot)
334            }
335            (Sequence::Range(a), Sequence::One(b)) => {
336                a.value_compare(b, op, collation, timezone, xot)
337            }
338            (Sequence::Range(a), Sequence::Many(b)) => {
339                a.value_compare(b, op, collation, timezone, xot)
340            }
341            (Sequence::Range(a), Sequence::Range(b)) => {
342                a.value_compare(b, op, collation, timezone, xot)
343            }
344        }
345    }
346
347    pub(crate) fn one_node(&self) -> error::Result<xot::Node> {
348        match self {
349            Sequence::Empty(inner) => inner.one_node(),
350            Sequence::One(inner) => inner.one_node(),
351            Sequence::Many(inner) => inner.one_node(),
352            Sequence::Range(inner) => inner.one_node(),
353        }
354    }
355
356    pub(crate) fn is(&self, other: &Self) -> error::Result<bool> {
357        match (self, other) {
358            (Sequence::Empty(a), Sequence::Empty(b)) => a.is(b),
359            (Sequence::Empty(a), Sequence::One(b)) => a.is(b),
360            (Sequence::Empty(a), Sequence::Many(b)) => a.is(b),
361            (Sequence::Empty(a), Sequence::Range(b)) => a.is(b),
362            (Sequence::One(a), Sequence::Empty(b)) => a.is(b),
363            (Sequence::One(a), Sequence::One(b)) => a.is(b),
364            (Sequence::One(a), Sequence::Many(b)) => a.is(b),
365            (Sequence::One(a), Sequence::Range(b)) => a.is(b),
366            (Sequence::Many(a), Sequence::Empty(b)) => a.is(b),
367            (Sequence::Many(a), Sequence::One(b)) => a.is(b),
368            (Sequence::Many(a), Sequence::Many(b)) => a.is(b),
369            (Sequence::Many(a), Sequence::Range(b)) => a.is(b),
370            (Sequence::Range(a), Sequence::Empty(b)) => a.is(b),
371            (Sequence::Range(a), Sequence::One(b)) => a.is(b),
372            (Sequence::Range(a), Sequence::Many(b)) => a.is(b),
373            (Sequence::Range(a), Sequence::Range(b)) => a.is(b),
374        }
375    }
376
377    pub(crate) fn precedes(
378        &self,
379        other: &Self,
380        annotations: xml::DocumentOrderAccess,
381    ) -> error::Result<bool> {
382        match (self, other) {
383            (Sequence::Empty(a), Sequence::Empty(b)) => a.precedes(b, annotations),
384            (Sequence::Empty(a), Sequence::One(b)) => a.precedes(b, annotations),
385            (Sequence::Empty(a), Sequence::Many(b)) => a.precedes(b, annotations),
386            (Sequence::Empty(a), Sequence::Range(b)) => a.precedes(b, annotations),
387            (Sequence::One(a), Sequence::Empty(b)) => a.precedes(b, annotations),
388            (Sequence::One(a), Sequence::One(b)) => a.precedes(b, annotations),
389            (Sequence::One(a), Sequence::Many(b)) => a.precedes(b, annotations),
390            (Sequence::One(a), Sequence::Range(b)) => a.precedes(b, annotations),
391            (Sequence::Many(a), Sequence::Empty(b)) => a.precedes(b, annotations),
392            (Sequence::Many(a), Sequence::One(b)) => a.precedes(b, annotations),
393            (Sequence::Many(a), Sequence::Many(b)) => a.precedes(b, annotations),
394            (Sequence::Many(a), Sequence::Range(b)) => a.precedes(b, annotations),
395            (Sequence::Range(a), Sequence::Empty(b)) => a.precedes(b, annotations),
396            (Sequence::Range(a), Sequence::One(b)) => a.precedes(b, annotations),
397            (Sequence::Range(a), Sequence::Many(b)) => a.precedes(b, annotations),
398            (Sequence::Range(a), Sequence::Range(b)) => a.precedes(b, annotations),
399        }
400    }
401
402    pub(crate) fn follows(
403        &self,
404        other: &Self,
405        annotations: xml::DocumentOrderAccess,
406    ) -> error::Result<bool> {
407        match (self, other) {
408            (Sequence::Empty(a), Sequence::Empty(b)) => a.follows(b, annotations),
409            (Sequence::Empty(a), Sequence::One(b)) => a.follows(b, annotations),
410            (Sequence::Empty(a), Sequence::Many(b)) => a.follows(b, annotations),
411            (Sequence::Empty(a), Sequence::Range(b)) => a.follows(b, annotations),
412            (Sequence::One(a), Sequence::Empty(b)) => a.follows(b, annotations),
413            (Sequence::One(a), Sequence::One(b)) => a.follows(b, annotations),
414            (Sequence::One(a), Sequence::Many(b)) => a.follows(b, annotations),
415            (Sequence::One(a), Sequence::Range(b)) => a.follows(b, annotations),
416            (Sequence::Many(a), Sequence::Empty(b)) => a.follows(b, annotations),
417            (Sequence::Many(a), Sequence::One(b)) => a.follows(b, annotations),
418            (Sequence::Many(a), Sequence::Many(b)) => a.follows(b, annotations),
419            (Sequence::Many(a), Sequence::Range(b)) => a.follows(b, annotations),
420            (Sequence::Range(a), Sequence::Empty(b)) => a.follows(b, annotations),
421            (Sequence::Range(a), Sequence::One(b)) => a.follows(b, annotations),
422            (Sequence::Range(a), Sequence::Many(b)) => a.follows(b, annotations),
423            (Sequence::Range(a), Sequence::Range(b)) => a.follows(b, annotations),
424        }
425    }
426}