diff --git a/src/api/annotation.rs b/src/api/annotation.rs index 0e6178f..942b401 100644 --- a/src/api/annotation.rs +++ b/src/api/annotation.rs @@ -166,6 +166,7 @@ impl<'store> ResultItem<'store, Annotation> { /// Returns the (single!) resource the annotation points to. Only works if this annotation targets using a [`Selector::TextSelector`], /// [`Selector::ResourceSelector`] or [`Selector::AnnotationSelector`], and not for complex selectors. + /// Use [`Self::resources()`] if want to iterate over all resources instead. /// AnnotationSelectors are followed recursively if needed. pub fn resource(&self) -> Option> { match self.as_ref().target() { @@ -629,7 +630,7 @@ impl<'store> AnnotationsIter<'store> { pub fn filter_annotations(mut self, annotations: AnnotationsIter<'store>) -> Self { if self.iter.is_some() { if annotations.iter.is_some() { - self.iter = Some(self.iter.unwrap().merge(annotations.iter.unwrap())); + self.iter = Some(self.iter.unwrap().intersection(annotations.iter.unwrap())); } else { //invalidate the iterator, there will be no results self.abort(); @@ -817,10 +818,11 @@ impl<'store> AnnotationsIter<'store> { } /// Produces the union between two annotation iterators - /// Any constraints on either iterator remain valid! - pub fn extend(mut self, other: AnnotationsIter<'store>) -> AnnotationsIter<'store> { + /// Any filters on either iterator remain valid! + pub fn union(mut self, other: AnnotationsIter<'store>) -> AnnotationsIter<'store> { if self.iter.is_some() && other.iter.is_some() { - self.iter = Some(self.iter.unwrap().extend(other.iter.unwrap())); + self.filters.extend(other.filters.into_iter()); + self.iter = Some(self.iter.unwrap().union(other.iter.unwrap())); } else if self.iter.is_none() { return other; } @@ -828,10 +830,11 @@ impl<'store> AnnotationsIter<'store> { } /// Produces the intersection between two annotation iterators - /// Any constraints on either iterator remain valid! - pub fn merge(mut self, other: AnnotationsIter<'store>) -> AnnotationsIter<'store> { + /// Any filters on either iterator remain valid! + pub fn intersection(mut self, other: AnnotationsIter<'store>) -> AnnotationsIter<'store> { if self.iter.is_some() && other.iter.is_some() { - self.iter = Some(self.iter.unwrap().extend(other.iter.unwrap())); + self.filters.extend(other.filters.into_iter()); + self.iter = Some(self.iter.unwrap().intersection(other.iter.unwrap())); } else if self.iter.is_none() { return other; } diff --git a/src/api/annotationdata.rs b/src/api/annotationdata.rs index d4c4e46..940160b 100644 --- a/src/api/annotationdata.rs +++ b/src/api/annotationdata.rs @@ -298,7 +298,7 @@ impl<'store> DataIter<'store> { /// /// You can cast any existing iterator that produces [`ResultItem`] to a [`DataIter`] using [`DataIter::from_iter()`]. pub fn filter_data(self, data: DataIter<'store>) -> Self { - self.merge(data) + self.intersection(data) } /// Find and filter data. Returns an iterator over the data. @@ -447,10 +447,11 @@ impl<'store> DataIter<'store> { } /// Produces the union between two data iterators - /// Any constraints on either iterator remain valid! - pub fn extend(mut self, other: DataIter<'store>) -> DataIter<'store> { + /// Any filters on either iterator remain valid! + pub fn union(mut self, other: DataIter<'store>) -> DataIter<'store> { if self.iter.is_some() && other.iter.is_some() { - self.iter = Some(self.iter.unwrap().extend(other.iter.unwrap())); + self.filters.extend(other.filters.into_iter()); + self.iter = Some(self.iter.unwrap().union(other.iter.unwrap())); } else if self.iter.is_none() { return other; } @@ -458,10 +459,11 @@ impl<'store> DataIter<'store> { } /// Produces the intersection between two data iterators - /// Any constraints on either iterator remain valid! - pub fn merge(mut self, other: DataIter<'store>) -> DataIter<'store> { + /// Any filters on either iterator remain valid! + pub fn intersection(mut self, other: DataIter<'store>) -> DataIter<'store> { if self.iter.is_some() && other.iter.is_some() { - self.iter = Some(self.iter.unwrap().merge(other.iter.unwrap())); + self.filters.extend(other.filters.into_iter()); + self.iter = Some(self.iter.unwrap().intersection(other.iter.unwrap())); } else if self.iter.is_none() { return other; } diff --git a/src/api/resources.rs b/src/api/resources.rs index eeb725e..f4092f6 100644 --- a/src/api/resources.rs +++ b/src/api/resources.rs @@ -62,7 +62,7 @@ impl<'store> ResultItem<'store, TextResource> { /// Use `annotations_as_metadata()` or `annotations_on_text()` instead if you want to differentiate the two. pub fn annotations(&self) -> AnnotationsIter<'store> { self.annotations_as_metadata() - .extend(self.annotations_on_text()) + .union(self.annotations_on_text()) } /// Returns an iterator over all text selections that are marked in this resource (i.e. there are one or more annotations on it). @@ -306,6 +306,30 @@ impl<'store> ResourcesIter<'store> { self } + /// Produces the union between two resource iterators + /// Any filters on either iterator remain valid! + pub fn union(mut self, other: ResourcesIter<'store>) -> ResourcesIter<'store> { + if self.iter.is_some() && other.iter.is_some() { + self.filters.extend(other.filters.into_iter()); + self.iter = Some(self.iter.unwrap().union(other.iter.unwrap())); + } else if self.iter.is_none() { + return other; + } + self + } + + /// Produces the intersection between two resource iterators + /// Any filters on either iterator remain valid! + pub fn intersection(mut self, other: ResourcesIter<'store>) -> ResourcesIter<'store> { + if self.iter.is_some() && other.iter.is_some() { + self.filters.extend(other.filters.into_iter()); + self.iter = Some(self.iter.unwrap().intersection(other.iter.unwrap())); + } else if self.iter.is_none() { + return other; + } + self + } + /// Does this iterator return items in sorted order? pub fn returns_sorted(&self) -> bool { if let Some(iter) = self.iter.as_ref() { diff --git a/src/lib.rs b/src/lib.rs index ff38b18..6f2b5a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -267,7 +267,7 @@ where /// Merges another IntersectionIter into the current one. This effectively /// iterates over the intersection of both. - pub(crate) fn merge(mut self, other: IntersectionIter<'a, T>) -> Self { + pub(crate) fn intersection(mut self, other: IntersectionIter<'a, T>) -> Self { for source in other.sources { if source.array.is_some() { self = self.with(source.array.unwrap(), source.sorted); @@ -283,7 +283,7 @@ where /// Extends this iterator with another one. This is a *union* and not an *intersection*. /// However, all additional constraints on either iterator are preserved (and those are intersections). - pub(crate) fn extend(mut self, mut other: IntersectionIter<'a, T>) -> Self { + pub(crate) fn union(mut self, mut other: IntersectionIter<'a, T>) -> Self { //edge-cases first: if self.sources.is_empty() { return other; @@ -557,21 +557,21 @@ mod test { } #[test] - fn test_intersectioniter_merge() { + fn test_intersectioniter_intersection() { let mut iter = IntersectionIter::new(Cow::Owned(vec![1, 2, 3, 4, 5]), true); iter = iter.with(Cow::Owned(vec![1, 3, 5]), true); let iter2 = IntersectionIter::new(Cow::Owned(vec![5, 6]), true); - iter = iter.merge(iter2); + iter = iter.intersection(iter2); iter = iter.with(Cow::Owned(vec![5]), true); let v: Vec<_> = iter.collect(); assert_eq!(v, vec![5]); } #[test] - fn test_intersectioniter_extend() { + fn test_intersectioniter_union() { let mut iter = IntersectionIter::new(Cow::Owned(vec![1, 2, 3, 4, 5]), true); let iter2 = IntersectionIter::new(Cow::Owned(vec![6, 7]), true); - iter = iter.extend(iter2); + iter = iter.union(iter2); let v: Vec<_> = iter.collect(); assert_eq!(v, vec![1, 2, 3, 4, 5, 6, 7]); }