xee_interpreter/function/
array.rs

1use std::rc::Rc;
2
3use xot::Xot;
4
5use crate::{context, error, sequence, string};
6
7/// An XPath Array
8///
9/// Not to be confused with an XPath sequence, this is a type of item that can exist
10/// in a sequence when you need to have an actual list.
11///
12/// I tried to make this a Rc<[]> but this is bigger and blows up the item as a result.
13#[derive(Debug, Clone, PartialEq)]
14pub struct Array(pub(crate) Rc<Vec<sequence::Sequence>>);
15
16#[cfg(target_arch = "x86_64")]
17static_assertions::assert_eq_size!(Array, [u8; 8]);
18
19impl Array {
20    pub(crate) fn new(vec: Vec<sequence::Sequence>) -> Self {
21        Self(vec.into())
22    }
23
24    pub(crate) fn join(arrays: &[Self]) -> Self {
25        let mut vec = Vec::with_capacity(arrays.iter().map(|array| array.0.len()).sum());
26        for array in arrays {
27            vec.extend(array.0.as_ref().iter().cloned());
28        }
29        Self::new(vec)
30    }
31
32    pub(crate) fn index(&self, index: usize) -> Option<&sequence::Sequence> {
33        self.0.get(index)
34    }
35
36    pub(crate) fn iter(&self) -> impl DoubleEndedIterator<Item = &sequence::Sequence> {
37        self.0.iter()
38    }
39
40    pub(crate) fn put(&self, index: usize, member: &sequence::Sequence) -> Option<Self> {
41        if index >= self.0.len() {
42            return None;
43        }
44        let mut vec = self.0.as_ref().to_vec();
45        vec[index] = member.clone();
46        Some(Self::new(vec))
47    }
48
49    pub(crate) fn append(&self, appendage: &sequence::Sequence) -> Self {
50        let mut vec = self.0.as_ref().to_vec();
51        vec.push(appendage.clone());
52        Self::new(vec)
53    }
54
55    pub(crate) fn subarray(&self, start: usize, length: usize) -> Option<Self> {
56        if start > self.0.len() || (start + length) > self.0.len() {
57            return None;
58        }
59        let mut vec = Vec::with_capacity(length);
60        for i in start..(start + length) {
61            vec.push(self.0[i].clone());
62        }
63        Some(Self::new(vec))
64    }
65
66    pub(crate) fn remove_positions(&self, positions: &[usize]) -> Option<Self> {
67        for position in positions {
68            if position >= &self.0.len() {
69                return None;
70            }
71        }
72        let mut vec = Vec::with_capacity(self.0.len() - positions.len());
73
74        for (i, member) in self.0.iter().enumerate() {
75            if !positions.contains(&i) {
76                vec.push(member.clone());
77            }
78        }
79        Some(Self::new(vec))
80    }
81
82    pub(crate) fn reversed(&self) -> Self {
83        let mut vec = self.0.as_ref().to_vec();
84        vec.reverse();
85        Self::new(vec)
86    }
87
88    pub(crate) fn insert_before(
89        &self,
90        position: usize,
91        member: &sequence::Sequence,
92    ) -> Option<Self> {
93        if position > self.0.len() {
94            return None;
95        }
96        let mut vec = self.0.as_ref().to_vec();
97        vec.insert(position, member.clone());
98        Some(Self::new(vec))
99    }
100
101    pub(crate) fn len(&self) -> usize {
102        self.0.len()
103    }
104
105    pub(crate) fn is_empty(&self) -> bool {
106        self.0.is_empty()
107    }
108
109    pub(crate) fn deep_equal(
110        &self,
111        other: Array,
112        collation: &string::Collation,
113        default_offset: chrono::FixedOffset,
114        xot: &Xot,
115    ) -> error::Result<bool> {
116        if self.0.len() != other.0.len() {
117            return Ok(false);
118        }
119        for (a, b) in self.0.iter().zip(other.0.iter()) {
120            if !a.deep_equal(b, collation, default_offset, xot)? {
121                return Ok(false);
122            }
123        }
124        Ok(true)
125    }
126
127    pub fn display_representation(&self, xot: &Xot, context: &context::DynamicContext) -> String {
128        let members = self
129            .0
130            .iter()
131            .map(|member| member.display_representation(xot, context))
132            .collect::<Vec<_>>();
133        format!("[\n{}\n]", members.join(",\n"))
134    }
135}
136
137impl From<Vec<sequence::Sequence>> for Array {
138    fn from(vec: Vec<sequence::Sequence>) -> Self {
139        Self::new(vec)
140    }
141}