use std::cmp::Ordering;
use std::ops::{Index, IndexMut};
use std::slice;
use super::error::XPathError;
use super::iterator::XmlItem;
use super::timsort::{timsort_slice_with_comparer, IComparer};
use super::{DomNavigator, XmlNodeOrder};
#[derive(Debug, Clone)]
pub struct ItemSet<T> {
items: Vec<T>,
completed: bool,
}
impl<T> Default for ItemSet<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> ItemSet<T> {
pub fn new() -> Self {
ItemSet {
items: Vec::new(),
completed: false,
}
}
pub fn with_capacity(capacity: usize) -> Self {
ItemSet {
items: Vec::with_capacity(capacity),
completed: false,
}
}
#[inline]
pub fn len(&self) -> usize {
self.items.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
#[inline]
pub fn capacity(&self) -> usize {
self.items.capacity()
}
pub fn set_capacity(&mut self, capacity: usize) {
if capacity < self.items.len() {
panic!("Capacity cannot be less than the current length");
}
if capacity > self.items.capacity() {
self.items.reserve(capacity - self.items.capacity());
}
}
fn ensure_capacity(&mut self, min: usize) {
if self.items.capacity() < min {
let new_capacity = if self.items.capacity() == 0 {
4
} else {
self.items.capacity() * 2
};
let new_capacity = new_capacity.max(min);
self.items.reserve(new_capacity - self.items.capacity());
}
}
#[inline]
pub fn completed(&self) -> bool {
self.completed
}
#[inline]
pub fn set_completed(&mut self, value: bool) {
self.completed = value;
}
#[inline]
pub fn get(&self, index: usize) -> Option<&T> {
self.items.get(index)
}
#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
self.items.get_mut(index)
}
pub fn add(&mut self, item: T) {
self.ensure_capacity(self.items.len() + 1);
self.items.push(item);
}
pub fn clear(&mut self) {
self.items.clear();
}
#[inline]
pub fn iter(&self) -> ItemSetIter<'_, T> {
ItemSetIter {
inner: self.items.iter(),
}
}
#[inline]
pub fn iter_mut(&mut self) -> ItemSetIterMut<'_, T> {
ItemSetIterMut {
inner: self.items.iter_mut(),
}
}
#[inline]
pub fn as_slice(&self) -> &[T] {
&self.items
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
&mut self.items
}
}
impl<T: Clone> ItemSet<T> {
pub fn sort_with<C: IComparer<T>>(&mut self, comparer: &C) {
timsort_slice_with_comparer(&mut self.items, comparer);
}
}
impl<T> Index<usize> for ItemSet<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.items[index]
}
}
impl<T> IndexMut<usize> for ItemSet<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.items[index]
}
}
impl<T> IntoIterator for ItemSet<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}
impl<'a, T> IntoIterator for &'a ItemSet<T> {
type Item = &'a T;
type IntoIter = ItemSetIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut ItemSet<T> {
type Item = &'a mut T;
type IntoIter = ItemSetIterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T> FromIterator<T> for ItemSet<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let items: Vec<T> = iter.into_iter().collect();
ItemSet {
items,
completed: false,
}
}
}
impl<T> Extend<T> for ItemSet<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
self.items.extend(iter);
}
}
#[derive(Debug, Clone)]
pub struct ItemSetIter<'a, T> {
inner: slice::Iter<'a, T>,
}
impl<'a, T> Iterator for ItemSetIter<'a, T> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<T> ExactSizeIterator for ItemSetIter<'_, T> {}
#[derive(Debug)]
pub struct ItemSetIterMut<'a, T> {
inner: slice::IterMut<'a, T>,
}
impl<'a, T> Iterator for ItemSetIterMut<'a, T> {
type Item = &'a mut T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<T> ExactSizeIterator for ItemSetIterMut<'_, T> {}
#[derive(Debug, Clone, Copy, Default)]
pub struct XPathComparer;
impl XPathComparer {
pub fn new() -> Self {
XPathComparer
}
pub fn try_compare<N: DomNavigator>(
&self,
x: &XmlItem<N>,
y: &XmlItem<N>,
) -> Result<Ordering, XPathError> {
match (x, y) {
(XmlItem::Node(nav1), XmlItem::Node(nav2)) => match nav1.compare_position(nav2) {
XmlNodeOrder::Before => Ok(Ordering::Less),
XmlNodeOrder::After => Ok(Ordering::Greater),
XmlNodeOrder::Same => Ok(Ordering::Equal),
XmlNodeOrder::Unknown => Ok(Ordering::Equal),
},
_ => Err(XPathError::XPTY0004 {
expected: "node".to_string(),
found: "atomic value".to_string(),
}),
}
}
}
impl<N: DomNavigator> IComparer<XmlItem<N>> for XPathComparer {
fn compare(&self, x: &XmlItem<N>, y: &XmlItem<N>) -> Ordering {
match (x, y) {
(XmlItem::Node(nav1), XmlItem::Node(nav2)) => {
match nav1.compare_position(nav2) {
XmlNodeOrder::Before => Ordering::Less,
XmlNodeOrder::After => Ordering::Greater,
XmlNodeOrder::Same => Ordering::Equal,
XmlNodeOrder::Unknown => {
Ordering::Equal
}
}
}
_ => panic!("Cannot compare non-node items in document order (XPTY0004)"),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct XPathEqualityComparer;
impl XPathEqualityComparer {
pub fn new() -> Self {
XPathEqualityComparer
}
pub fn equals<N: DomNavigator>(&self, x: &XmlItem<N>, y: &XmlItem<N>) -> bool {
match (x, y) {
(XmlItem::Node(nav1), XmlItem::Node(nav2)) => nav1.is_same_position(nav2),
_ => panic!("Cannot compare non-node items for position equality (XPTY0004)"),
}
}
pub fn try_equals<N: DomNavigator>(
&self,
x: &XmlItem<N>,
y: &XmlItem<N>,
) -> Result<bool, XPathError> {
match (x, y) {
(XmlItem::Node(nav1), XmlItem::Node(nav2)) => Ok(nav1.is_same_position(nav2)),
_ => Err(XPathError::XPTY0004 {
expected: "node".to_string(),
found: "atomic value".to_string(),
}),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::xpath::timsort::{OrdComparer, ReverseComparer};
#[test]
fn test_new() {
let set: ItemSet<i32> = ItemSet::new();
assert!(set.is_empty());
assert_eq!(set.len(), 0);
}
#[test]
fn test_with_capacity() {
let set: ItemSet<i32> = ItemSet::with_capacity(10);
assert!(set.is_empty());
assert!(set.capacity() >= 10);
}
#[test]
fn test_add() {
let mut set = ItemSet::new();
set.add(1);
set.add(2);
set.add(3);
assert_eq!(set.len(), 3);
assert_eq!(set[0], 1);
assert_eq!(set[1], 2);
assert_eq!(set[2], 3);
}
#[test]
fn test_clear() {
let mut set = ItemSet::new();
set.add(1);
set.add(2);
set.clear();
assert!(set.is_empty());
}
#[test]
fn test_get() {
let mut set = ItemSet::new();
set.add(42);
assert_eq!(set.get(0), Some(&42));
assert_eq!(set.get(1), None);
}
#[test]
fn test_get_mut() {
let mut set = ItemSet::new();
set.add(42);
if let Some(item) = set.get_mut(0) {
*item = 100;
}
assert_eq!(set[0], 100);
}
#[test]
fn test_completed() {
let mut set: ItemSet<i32> = ItemSet::new();
assert!(!set.completed());
set.set_completed(true);
assert!(set.completed());
}
#[test]
fn test_sort_with_ord_comparer() {
let mut set = ItemSet::new();
set.add(3);
set.add(1);
set.add(4);
set.add(1);
set.add(5);
let comparer = OrdComparer::<i32>::new();
set.sort_with(&comparer);
assert_eq!(set[0], 1);
assert_eq!(set[1], 1);
assert_eq!(set[2], 3);
assert_eq!(set[3], 4);
assert_eq!(set[4], 5);
}
#[test]
fn test_sort_with_reverse_comparer() {
let mut set = ItemSet::new();
set.add(1);
set.add(2);
set.add(3);
let comparer = ReverseComparer::new(OrdComparer::<i32>::new());
set.sort_with(&comparer);
assert_eq!(set[0], 3);
assert_eq!(set[1], 2);
assert_eq!(set[2], 1);
}
#[test]
fn test_iter() {
let mut set = ItemSet::new();
set.add(1);
set.add(2);
set.add(3);
let collected: Vec<_> = set.iter().cloned().collect();
assert_eq!(collected, vec![1, 2, 3]);
}
#[test]
fn test_into_iter() {
let mut set = ItemSet::new();
set.add(1);
set.add(2);
set.add(3);
let collected: Vec<_> = set.into_iter().collect();
assert_eq!(collected, vec![1, 2, 3]);
}
#[test]
fn test_from_iter() {
let set: ItemSet<i32> = vec![1, 2, 3].into_iter().collect();
assert_eq!(set.len(), 3);
assert_eq!(set[0], 1);
assert_eq!(set[1], 2);
assert_eq!(set[2], 3);
}
#[test]
fn test_extend() {
let mut set = ItemSet::new();
set.add(1);
set.extend(vec![2, 3, 4]);
assert_eq!(set.len(), 4);
}
#[test]
fn test_index() {
let mut set = ItemSet::new();
set.add(42);
assert_eq!(set[0], 42);
}
#[test]
fn test_index_mut() {
let mut set = ItemSet::new();
set.add(42);
set[0] = 100;
assert_eq!(set[0], 100);
}
#[test]
fn test_default() {
let set: ItemSet<i32> = ItemSet::default();
assert!(set.is_empty());
}
}