1use std::cmp::Ordering;
13use std::ops::{Index, IndexMut};
14use std::slice;
15
16use super::error::XPathError;
17use super::iterator::XmlItem;
18use super::timsort::{timsort_slice_with_comparer, IComparer};
19use super::{DomNavigator, XmlNodeOrder};
20
21#[derive(Debug, Clone)]
31pub struct ItemSet<T> {
32 items: Vec<T>,
33 completed: bool,
34}
35
36impl<T> Default for ItemSet<T> {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl<T> ItemSet<T> {
43 pub fn new() -> Self {
45 ItemSet {
46 items: Vec::new(),
47 completed: false,
48 }
49 }
50
51 pub fn with_capacity(capacity: usize) -> Self {
53 ItemSet {
54 items: Vec::with_capacity(capacity),
55 completed: false,
56 }
57 }
58
59 #[inline]
61 pub fn len(&self) -> usize {
62 self.items.len()
63 }
64
65 #[inline]
67 pub fn is_empty(&self) -> bool {
68 self.items.is_empty()
69 }
70
71 #[inline]
73 pub fn capacity(&self) -> usize {
74 self.items.capacity()
75 }
76
77 pub fn set_capacity(&mut self, capacity: usize) {
83 if capacity < self.items.len() {
84 panic!("Capacity cannot be less than the current length");
85 }
86 if capacity > self.items.capacity() {
87 self.items.reserve(capacity - self.items.capacity());
88 }
89 }
90
91 fn ensure_capacity(&mut self, min: usize) {
93 if self.items.capacity() < min {
94 let new_capacity = if self.items.capacity() == 0 {
95 4
96 } else {
97 self.items.capacity() * 2
98 };
99 let new_capacity = new_capacity.max(min);
100 self.items.reserve(new_capacity - self.items.capacity());
101 }
102 }
103
104 #[inline]
106 pub fn completed(&self) -> bool {
107 self.completed
108 }
109
110 #[inline]
112 pub fn set_completed(&mut self, value: bool) {
113 self.completed = value;
114 }
115
116 #[inline]
118 pub fn get(&self, index: usize) -> Option<&T> {
119 self.items.get(index)
120 }
121
122 #[inline]
124 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
125 self.items.get_mut(index)
126 }
127
128 pub fn add(&mut self, item: T) {
130 self.ensure_capacity(self.items.len() + 1);
131 self.items.push(item);
132 }
133
134 pub fn clear(&mut self) {
136 self.items.clear();
137 }
138
139 #[inline]
141 pub fn iter(&self) -> ItemSetIter<'_, T> {
142 ItemSetIter {
143 inner: self.items.iter(),
144 }
145 }
146
147 #[inline]
149 pub fn iter_mut(&mut self) -> ItemSetIterMut<'_, T> {
150 ItemSetIterMut {
151 inner: self.items.iter_mut(),
152 }
153 }
154
155 #[inline]
157 pub fn as_slice(&self) -> &[T] {
158 &self.items
159 }
160
161 #[inline]
163 pub fn as_mut_slice(&mut self) -> &mut [T] {
164 &mut self.items
165 }
166}
167
168impl<T: Clone> ItemSet<T> {
169 pub fn sort_with<C: IComparer<T>>(&mut self, comparer: &C) {
173 timsort_slice_with_comparer(&mut self.items, comparer);
174 }
175}
176
177impl<T> Index<usize> for ItemSet<T> {
178 type Output = T;
179
180 fn index(&self, index: usize) -> &Self::Output {
181 &self.items[index]
182 }
183}
184
185impl<T> IndexMut<usize> for ItemSet<T> {
186 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
187 &mut self.items[index]
188 }
189}
190
191impl<T> IntoIterator for ItemSet<T> {
192 type Item = T;
193 type IntoIter = std::vec::IntoIter<T>;
194
195 fn into_iter(self) -> Self::IntoIter {
196 self.items.into_iter()
197 }
198}
199
200impl<'a, T> IntoIterator for &'a ItemSet<T> {
201 type Item = &'a T;
202 type IntoIter = ItemSetIter<'a, T>;
203
204 fn into_iter(self) -> Self::IntoIter {
205 self.iter()
206 }
207}
208
209impl<'a, T> IntoIterator for &'a mut ItemSet<T> {
210 type Item = &'a mut T;
211 type IntoIter = ItemSetIterMut<'a, T>;
212
213 fn into_iter(self) -> Self::IntoIter {
214 self.iter_mut()
215 }
216}
217
218impl<T> FromIterator<T> for ItemSet<T> {
219 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
220 let items: Vec<T> = iter.into_iter().collect();
221 ItemSet {
222 items,
223 completed: false,
224 }
225 }
226}
227
228impl<T> Extend<T> for ItemSet<T> {
229 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
230 self.items.extend(iter);
231 }
232}
233
234#[derive(Debug, Clone)]
236pub struct ItemSetIter<'a, T> {
237 inner: slice::Iter<'a, T>,
238}
239
240impl<'a, T> Iterator for ItemSetIter<'a, T> {
241 type Item = &'a T;
242
243 #[inline]
244 fn next(&mut self) -> Option<Self::Item> {
245 self.inner.next()
246 }
247
248 #[inline]
249 fn size_hint(&self) -> (usize, Option<usize>) {
250 self.inner.size_hint()
251 }
252}
253
254impl<T> ExactSizeIterator for ItemSetIter<'_, T> {}
255
256#[derive(Debug)]
258pub struct ItemSetIterMut<'a, T> {
259 inner: slice::IterMut<'a, T>,
260}
261
262impl<'a, T> Iterator for ItemSetIterMut<'a, T> {
263 type Item = &'a mut T;
264
265 #[inline]
266 fn next(&mut self) -> Option<Self::Item> {
267 self.inner.next()
268 }
269
270 #[inline]
271 fn size_hint(&self) -> (usize, Option<usize>) {
272 self.inner.size_hint()
273 }
274}
275
276impl<T> ExactSizeIterator for ItemSetIterMut<'_, T> {}
277
278#[derive(Debug, Clone, Copy, Default)]
292pub struct XPathComparer;
293
294impl XPathComparer {
295 pub fn new() -> Self {
297 XPathComparer
298 }
299
300 pub fn try_compare<N: DomNavigator>(
304 &self,
305 x: &XmlItem<N>,
306 y: &XmlItem<N>,
307 ) -> Result<Ordering, XPathError> {
308 match (x, y) {
309 (XmlItem::Node(nav1), XmlItem::Node(nav2)) => match nav1.compare_position(nav2) {
310 XmlNodeOrder::Before => Ok(Ordering::Less),
311 XmlNodeOrder::After => Ok(Ordering::Greater),
312 XmlNodeOrder::Same => Ok(Ordering::Equal),
313 XmlNodeOrder::Unknown => Ok(Ordering::Equal),
314 },
315 _ => Err(XPathError::XPTY0004 {
316 expected: "node".to_string(),
317 found: "atomic value".to_string(),
318 }),
319 }
320 }
321}
322
323impl<N: DomNavigator> IComparer<XmlItem<N>> for XPathComparer {
324 fn compare(&self, x: &XmlItem<N>, y: &XmlItem<N>) -> Ordering {
325 match (x, y) {
326 (XmlItem::Node(nav1), XmlItem::Node(nav2)) => {
327 match nav1.compare_position(nav2) {
328 XmlNodeOrder::Before => Ordering::Less,
329 XmlNodeOrder::After => Ordering::Greater,
330 XmlNodeOrder::Same => Ordering::Equal,
331 XmlNodeOrder::Unknown => {
332 Ordering::Equal
337 }
338 }
339 }
340 _ => panic!("Cannot compare non-node items in document order (XPTY0004)"),
341 }
342 }
343}
344
345#[derive(Debug, Clone, Copy, Default)]
349pub struct XPathEqualityComparer;
350
351impl XPathEqualityComparer {
352 pub fn new() -> Self {
354 XPathEqualityComparer
355 }
356
357 pub fn equals<N: DomNavigator>(&self, x: &XmlItem<N>, y: &XmlItem<N>) -> bool {
363 match (x, y) {
364 (XmlItem::Node(nav1), XmlItem::Node(nav2)) => nav1.is_same_position(nav2),
365 _ => panic!("Cannot compare non-node items for position equality (XPTY0004)"),
366 }
367 }
368
369 pub fn try_equals<N: DomNavigator>(
373 &self,
374 x: &XmlItem<N>,
375 y: &XmlItem<N>,
376 ) -> Result<bool, XPathError> {
377 match (x, y) {
378 (XmlItem::Node(nav1), XmlItem::Node(nav2)) => Ok(nav1.is_same_position(nav2)),
379 _ => Err(XPathError::XPTY0004 {
380 expected: "node".to_string(),
381 found: "atomic value".to_string(),
382 }),
383 }
384 }
385}
386
387#[cfg(test)]
388mod tests {
389 use super::*;
390 use crate::xpath::timsort::{OrdComparer, ReverseComparer};
391
392 #[test]
393 fn test_new() {
394 let set: ItemSet<i32> = ItemSet::new();
395 assert!(set.is_empty());
396 assert_eq!(set.len(), 0);
397 }
398
399 #[test]
400 fn test_with_capacity() {
401 let set: ItemSet<i32> = ItemSet::with_capacity(10);
402 assert!(set.is_empty());
403 assert!(set.capacity() >= 10);
404 }
405
406 #[test]
407 fn test_add() {
408 let mut set = ItemSet::new();
409 set.add(1);
410 set.add(2);
411 set.add(3);
412 assert_eq!(set.len(), 3);
413 assert_eq!(set[0], 1);
414 assert_eq!(set[1], 2);
415 assert_eq!(set[2], 3);
416 }
417
418 #[test]
419 fn test_clear() {
420 let mut set = ItemSet::new();
421 set.add(1);
422 set.add(2);
423 set.clear();
424 assert!(set.is_empty());
425 }
426
427 #[test]
428 fn test_get() {
429 let mut set = ItemSet::new();
430 set.add(42);
431 assert_eq!(set.get(0), Some(&42));
432 assert_eq!(set.get(1), None);
433 }
434
435 #[test]
436 fn test_get_mut() {
437 let mut set = ItemSet::new();
438 set.add(42);
439 if let Some(item) = set.get_mut(0) {
440 *item = 100;
441 }
442 assert_eq!(set[0], 100);
443 }
444
445 #[test]
446 fn test_completed() {
447 let mut set: ItemSet<i32> = ItemSet::new();
448 assert!(!set.completed());
449 set.set_completed(true);
450 assert!(set.completed());
451 }
452
453 #[test]
454 fn test_sort_with_ord_comparer() {
455 let mut set = ItemSet::new();
456 set.add(3);
457 set.add(1);
458 set.add(4);
459 set.add(1);
460 set.add(5);
461
462 let comparer = OrdComparer::<i32>::new();
463 set.sort_with(&comparer);
464
465 assert_eq!(set[0], 1);
466 assert_eq!(set[1], 1);
467 assert_eq!(set[2], 3);
468 assert_eq!(set[3], 4);
469 assert_eq!(set[4], 5);
470 }
471
472 #[test]
473 fn test_sort_with_reverse_comparer() {
474 let mut set = ItemSet::new();
475 set.add(1);
476 set.add(2);
477 set.add(3);
478
479 let comparer = ReverseComparer::new(OrdComparer::<i32>::new());
480 set.sort_with(&comparer);
481
482 assert_eq!(set[0], 3);
483 assert_eq!(set[1], 2);
484 assert_eq!(set[2], 1);
485 }
486
487 #[test]
488 fn test_iter() {
489 let mut set = ItemSet::new();
490 set.add(1);
491 set.add(2);
492 set.add(3);
493
494 let collected: Vec<_> = set.iter().cloned().collect();
495 assert_eq!(collected, vec![1, 2, 3]);
496 }
497
498 #[test]
499 fn test_into_iter() {
500 let mut set = ItemSet::new();
501 set.add(1);
502 set.add(2);
503 set.add(3);
504
505 let collected: Vec<_> = set.into_iter().collect();
506 assert_eq!(collected, vec![1, 2, 3]);
507 }
508
509 #[test]
510 fn test_from_iter() {
511 let set: ItemSet<i32> = vec![1, 2, 3].into_iter().collect();
512 assert_eq!(set.len(), 3);
513 assert_eq!(set[0], 1);
514 assert_eq!(set[1], 2);
515 assert_eq!(set[2], 3);
516 }
517
518 #[test]
519 fn test_extend() {
520 let mut set = ItemSet::new();
521 set.add(1);
522 set.extend(vec![2, 3, 4]);
523 assert_eq!(set.len(), 4);
524 }
525
526 #[test]
527 fn test_index() {
528 let mut set = ItemSet::new();
529 set.add(42);
530 assert_eq!(set[0], 42);
531 }
532
533 #[test]
534 fn test_index_mut() {
535 let mut set = ItemSet::new();
536 set.add(42);
537 set[0] = 100;
538 assert_eq!(set[0], 100);
539 }
540
541 #[test]
542 fn test_default() {
543 let set: ItemSet<i32> = ItemSet::default();
544 assert!(set.is_empty());
545 }
546}