xee_interpreter/sequence/
compare.rs1use std::cmp::Ordering;
2
3use xot::Xot;
4
5use crate::{error, function, string::Collation};
6
7use super::{core::Sequence, item::Item};
8
9impl Sequence {
10 pub fn deep_equal(
14 &self,
15 other: &Self,
16 collation: &Collation,
17 default_offset: chrono::FixedOffset,
18 xot: &Xot,
19 ) -> error::Result<bool> {
20 if self.is_empty() && other.is_empty() {
22 return Ok(true);
23 }
24 if self.len() != other.len() {
25 return Ok(false);
26 }
27 for (a, b) in self.iter().zip(other.iter()) {
28 match (a, b) {
29 (Item::Atomic(a), Item::Atomic(b)) => {
30 if !a.deep_equal(&b, collation, default_offset) {
31 return Ok(false);
32 }
33 }
34 (Item::Node(a), Item::Node(b)) => {
35 if !xot.deep_equal_xpath(a, b, |a, b| collation.compare(a, b).is_eq()) {
36 return Ok(false);
37 }
38 }
39 (Item::Function(a), Item::Function(b)) => match (a, b) {
40 (function::Function::Array(a), function::Function::Array(b)) => {
41 if !a.deep_equal(b.clone(), collation, default_offset, xot)? {
42 return Ok(false);
43 }
44 }
45 (function::Function::Map(a), function::Function::Map(b)) => {
46 if !a.deep_equal(&b, collation, default_offset, xot)? {
47 return Ok(false);
48 }
49 }
50 (function::Function::Map(_), function::Function::Array(_)) => return Ok(false),
51 (function::Function::Array(_), function::Function::Map(_)) => return Ok(false),
52 _ => return Err(error::Error::FOTY0015),
53 },
54 _ => {
55 return Ok(false);
56 }
57 }
58 }
59 Ok(true)
60 }
61
62 pub(crate) fn fallible_compare(
63 &self,
64 other: &Sequence,
65 collation: &Collation,
66 implicit_offset: chrono::FixedOffset,
67 ) -> error::Result<Ordering> {
68 let a_atoms = self.iter().map(|item| item.to_atomic());
72 let mut b_atoms = other.iter().map(|item| item.to_atomic());
73 for a_atom in a_atoms {
74 let b_atom = b_atoms.next();
75 let a_atom = a_atom?;
76 if let Some(b_atom) = b_atom {
77 let b_atom = b_atom?;
78 let ordering = a_atom.fallible_compare(&b_atom, collation, implicit_offset)?;
79 if !ordering.is_eq() {
80 return Ok(ordering);
81 }
82 } else {
83 return Ok(Ordering::Greater);
84 }
85 }
86 if b_atoms.next().is_some() {
87 Ok(Ordering::Less)
88 } else {
89 Ok(Ordering::Equal)
90 }
91 }
92
93 pub(crate) fn compare(
97 &self,
98 other: &Sequence,
99 collation: &Collation,
100 implicit_offset: chrono::FixedOffset,
101 ) -> Ordering {
102 self.fallible_compare(other, collation, implicit_offset)
103 .unwrap_or(Ordering::Less)
104 }
105}