mod annotation;
mod annotationdata;
mod annotationdataset;
mod annotationstore;
mod datakey;
mod query;
mod resources;
mod substore;
mod text;
mod textselection;
#[cfg(feature = "webanno")]
mod webanno;
#[cfg(feature = "transpose")]
mod transpose;
#[cfg(feature = "translate")]
mod translate;
pub use annotation::*;
pub use annotationdata::*;
pub use annotationdataset::*;
pub use datakey::*;
pub use query::*;
pub use resources::*;
pub use text::*;
pub use textselection::*;
#[cfg(feature = "webanno")]
pub use webanno::*;
#[cfg(feature = "transpose")]
pub use transpose::*;
#[cfg(feature = "translate")]
pub use translate::*;
#[cfg(feature = "textvalidation")]
pub use crate::textvalidation::*;
use crate::annotation::{Annotation, AnnotationHandle};
use crate::annotationdata::{AnnotationData, AnnotationDataHandle};
use crate::annotationdataset::{AnnotationDataSet, AnnotationDataSetHandle};
use crate::annotationstore::AnnotationStore;
use crate::datakey::{DataKey, DataKeyHandle};
use crate::datavalue::{DataOperator, DataValue};
use crate::resources::{TextResource, TextResourceHandle};
use crate::substore::AnnotationSubStoreHandle;
use crate::textselection::{TextSelection, TextSelectionOperator};
use crate::{store::*, Offset, TextSelectionHandle};
use regex::Regex;
use std::borrow::Cow;
use std::collections::VecDeque;
use std::fmt::Debug;
use std::marker::PhantomData;
#[derive(Clone)]
pub struct Handles<'store, T>
where
T: Storable,
{
array: Cow<'store, [T::FullHandleType]>,
sorted: bool,
store: &'store AnnotationStore,
}
impl<'store, T> Debug for Handles<'store, T>
where
T: Storable,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = format!("Collection<{}>", T::typeinfo());
f.debug_struct(s.as_str())
.field("array", &self.array)
.field("sorted", &self.sorted)
.finish()
}
}
pub type HandlesIter<'a, T> =
std::iter::Copied<std::slice::Iter<'a, <T as Storable>::FullHandleType>>;
impl<'store, T> Handles<'store, T>
where
T: Storable,
{
pub fn returns_sorted(&self) -> bool {
self.sorted
}
pub fn store(&self) -> &'store AnnotationStore {
self.store
}
pub fn new(
array: Cow<'store, [T::FullHandleType]>,
sorted: bool,
store: &'store AnnotationStore,
) -> Self {
Self {
array,
sorted,
store,
}
}
pub fn new_empty(store: &'store AnnotationStore) -> Self {
Self {
array: Cow::Owned(Vec::new()),
sorted: false,
store,
}
}
pub fn from_iter(
iter: impl Iterator<Item = T::FullHandleType>,
store: &'store AnnotationStore,
) -> Self {
let mut sorted = true;
let mut v = Vec::new();
let mut prev: Option<T::FullHandleType> = None;
for item in iter {
if let Some(p) = prev {
if p > item {
sorted = false;
}
}
v.push(item);
prev = Some(item);
}
Self {
array: Cow::Owned(v),
sorted,
store,
}
}
pub fn take(self) -> Cow<'store, [T::FullHandleType]>
where
Self: Sized,
{
self.array
}
pub fn len(&self) -> usize {
self.array.len()
}
pub fn get(&self, index: usize) -> Option<T::FullHandleType> {
self.array.get(index).copied()
}
pub fn is_empty(&self) -> bool {
self.array.is_empty()
}
pub fn contains(&self, handle: &T::FullHandleType) -> bool {
if self.sorted {
match self.array.binary_search(&handle) {
Ok(_) => true,
Err(_) => false,
}
} else {
self.array.contains(&handle)
}
}
pub fn position(&self, handle: &T::FullHandleType) -> Option<usize> {
if self.sorted {
match self.array.binary_search(&handle) {
Ok(index) => Some(index),
Err(_) => None,
}
} else {
self.array.iter().position(|x| x == handle)
}
}
pub fn iter<'a>(&'a self) -> HandlesIter<'a, T> {
self.array.iter().copied()
}
pub fn items<'a>(&'a self) -> FromHandles<'store, T, HandlesIter<'store, T>>
where
'a: 'store,
{
FromHandles::new(self.iter(), self.store())
}
pub fn into_items(self) -> FromHandles<'store, T, OwnedHandlesIter<'store, T>> {
let store = self.store();
FromHandles::new(self.into_iter(), store)
}
pub fn union(&mut self, other: &Self) {
match other.len() {
0 => return, 1 => self.add(other.iter().next().unwrap()), _ => {
let mut updated = false;
let mut offset = 0;
for item in other.iter() {
if self.sorted && other.sorted {
match self.array[offset..].binary_search(&item) {
Ok(index) => offset = index + 1,
Err(index) => {
offset = index + 1;
updated = true;
self.add_unchecked(item);
}
}
} else {
if !self.contains(&item) {
updated = true;
self.add_unchecked(item);
}
}
}
if self.sorted && updated {
self.array.to_mut().sort_unstable();
}
}
}
}
pub fn intersection(&mut self, other: &Self) {
match (self.len(), other.len()) {
(0, _) | (_, 0) =>
{
self.array.to_mut().clear();
return;
}
(len, otherlen) => {
if len == otherlen && self.sorted && other.sorted {
if self.iter().zip(other.iter()).all(|(x, y)| x == y) {
return;
}
} else if otherlen < len {
if self.contains_subset(other) {
self.array = other.array.clone(); return;
}
} else if len < otherlen {
if other.contains_subset(self) {
return; }
}
}
}
let mut offset = 0;
self.array.to_mut().retain(|x| {
if self.sorted && other.sorted {
match other.array[offset..].binary_search(x) {
Ok(index) => {
offset = index + 1;
true
}
Err(index) => {
offset = index + 1;
false
}
}
} else {
other.contains(x) }
});
}
pub fn contains_subset(&self, subset: &Self) -> bool {
for handle in subset.iter() {
if !self.contains(&handle) {
return false;
}
}
true
}
pub fn sort(&mut self) {
if !self.sorted {
self.array.to_mut().sort_unstable();
self.sorted = true;
}
}
pub(crate) fn add_unchecked(&mut self, item: T::FullHandleType) {
self.array.to_mut().push(item);
}
pub fn add(&mut self, item: T::FullHandleType) {
if self.sorted {
if let Err(pos) = self.array.binary_search(&item) {
self.array.to_mut().insert(pos, item)
}
} else {
if !self.contains(&item) {
self.array.to_mut().push(item);
}
}
}
}
pub struct OwnedHandlesIter<'store, T>
where
T: Storable,
{
handles: Handles<'store, T>,
cursor: usize,
}
impl<'store, T> Iterator for OwnedHandlesIter<'store, T>
where
T: Storable,
{
type Item = T::FullHandleType;
fn next(&mut self) -> Option<Self::Item> {
if let Some(handle) = self.handles.get(self.cursor) {
self.cursor += 1;
Some(handle)
} else {
None
}
}
}
impl<'store, T> IntoIterator for Handles<'store, T>
where
T: Storable,
{
type Item = T::FullHandleType;
type IntoIter = OwnedHandlesIter<'store, T>;
fn into_iter(self) -> Self::IntoIter {
OwnedHandlesIter {
handles: self,
cursor: 0,
}
}
}
pub(crate) trait FullHandleToResultItem<'store, T>
where
T: Storable,
{
fn get_item(&self, handle: T::FullHandleType) -> Option<ResultItem<'store, T>>;
}
pub struct FromHandles<'store, T, I>
where
T: Storable + 'store,
I: Iterator<Item = T::FullHandleType>,
{
inner: I,
store: &'store AnnotationStore,
_marker: PhantomData<T>, }
impl<'store, T, I> FromHandles<'store, T, I>
where
T: Storable + 'store,
I: Iterator<Item = T::FullHandleType>,
{
pub fn new(inner: I, store: &'store AnnotationStore) -> Self {
Self {
inner,
store,
_marker: PhantomData,
}
}
}
impl<'store, T, I> Iterator for FromHandles<'store, T, I>
where
T: Storable + 'store,
I: Iterator<Item = T::FullHandleType>,
Self: FullHandleToResultItem<'store, T>,
{
type Item = ResultItem<'store, T>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(full_handle) = self.inner.next() {
let item = self.get_item(full_handle);
if item.is_none() {
continue; } else {
return item;
}
} else {
return None;
}
}
}
}
pub trait ToHandles<'store, T>
where
T: Storable,
{
fn to_handles(&mut self, store: &'store AnnotationStore) -> Handles<'store, T>;
}
impl<'store, T, I> ToHandles<'store, T> for I
where
T: Storable + 'store,
I: Iterator<Item = ResultItem<'store, T>>,
ResultItem<'store, T>: FullHandle<T>,
{
fn to_handles(&mut self, store: &'store AnnotationStore) -> Handles<'store, T> {
Handles::from_iter(self.map(|item| item.fullhandle()), store)
}
}
pub trait TestableIterator: Iterator
where
Self: Sized,
{
fn test(mut self) -> bool {
self.next().is_some()
}
}
impl<I> TestableIterator for I where I: Iterator {}
pub trait MaybeSortedIterator: Iterator {
fn returns_sorted(&self) -> bool;
}
pub trait IteratorToValue<'a>: Iterator {
fn value(&mut self) -> Option<&'a DataValue>;
fn value_as_str(&mut self) -> Option<&'a str>;
}
pub struct ResultIter<I>
where
I: Iterator,
{
inner: Option<I>,
sorted: bool,
}
impl<I: Iterator> MaybeSortedIterator for ResultIter<I> {
fn returns_sorted(&self) -> bool {
self.sorted
}
}
impl<'a, I> IteratorToValue<'a> for I
where
I: Iterator<Item = ResultItem<'a, AnnotationData>>,
{
fn value(&mut self) -> Option<&'a DataValue> {
self.next().map(|x| x.value())
}
fn value_as_str(&mut self) -> Option<&'a str> {
self.filter_map(|x| {
if let DataValue::String(s) = x.value() {
Some(s.as_str())
} else {
None
}
})
.next()
}
}
impl<I: Iterator> ResultIter<I> {
pub(crate) fn new(inner: I, sorted: bool) -> Self {
Self {
inner: Some(inner),
sorted,
}
}
pub(crate) fn new_sorted(inner: I) -> Self {
Self {
inner: Some(inner),
sorted: true,
}
}
pub(crate) fn new_unsorted(inner: I) -> Self {
Self {
inner: Some(inner),
sorted: false,
}
}
pub(crate) fn new_empty() -> Self {
Self {
inner: None,
sorted: true,
}
}
}
impl<I: Iterator> Iterator for ResultIter<I> {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if let Some(inner) = self.inner.as_mut() {
inner.next()
} else {
None
}
}
}
pub struct FilterAllIter<'store, T, I>
where
T: Storable + 'store,
I: Iterator<Item = ResultItem<'store, T>>,
{
inner: I,
filter: Handles<'store, T>,
store: &'store AnnotationStore,
buffer: Option<Handles<'store, T>>,
cursor: usize,
}
impl<'store, T, I> FilterAllIter<'store, T, I>
where
T: Storable + 'store,
I: Iterator<Item = ResultItem<'store, T>>,
I: ToHandles<'store, T>,
{
pub fn new(inner: I, filter: Handles<'store, T>, store: &'store AnnotationStore) -> Self {
Self {
inner,
filter,
store,
buffer: None,
cursor: 0,
}
}
}
impl<'store, T, I> Iterator for FilterAllIter<'store, T, I>
where
T: Storable + 'store,
I: Iterator<Item = ResultItem<'store, T>>,
Self: FullHandleToResultItem<'store, T>,
I: ToHandles<'store, T>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.buffer.is_none() {
let buffer = self.inner.to_handles(self.store);
if !self.filter.iter().all(|h| buffer.contains(&h)) {
return None;
}
self.buffer = Some(buffer);
}
let buffer = self
.buffer
.as_mut()
.expect("buffer must exist at this point");
if let Some(handle) = buffer.get(self.cursor) {
self.cursor += 1;
self.get_item(handle)
} else {
None
}
}
}
pub trait LimitIterator<I>
where
I: Iterator,
{
fn limit(self, begin: isize, end: isize) -> LimitIter<I>;
}
impl<I> LimitIterator<I> for I
where
I: Iterator,
{
fn limit(self, begin: isize, end: isize) -> LimitIter<I> {
LimitIter {
begin,
end,
cursor: 0,
buffer: VecDeque::new(),
emptybuffer: false,
inner: self,
}
}
}
pub struct LimitIter<I>
where
I: Iterator,
{
inner: I,
cursor: isize,
begin: isize,
end: isize,
emptybuffer: bool,
buffer: VecDeque<I::Item>,
}
impl<I> Iterator for LimitIter<I>
where
I: Iterator,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.emptybuffer {
return self.buffer.pop_front();
} else if let Some(item) = self.inner.next() {
if self.begin >= 0 && self.cursor >= self.begin {
if self.end == 0 || self.cursor < self.end {
self.cursor += 1;
return Some(item);
} else if self.end > 0 && self.cursor >= self.end {
self.cursor += 1;
return None;
}
}
if ((self.begin < 0) || (self.begin >= 0 && self.cursor >= self.begin))
&& ((self.end <= 0) || (self.cursor < self.end))
{
self.buffer.push_back(item);
if self.end == 0 && self.begin < 0 {
if self.buffer.len() > self.begin.abs() as usize {
let excess = self.buffer.len() - self.begin.abs() as usize;
for _ in 0..excess {
self.buffer.pop_front();
}
}
}
}
self.cursor += 1;
} else {
if self.begin >= 0 && self.end >= 0 {
return None;
} else {
self.emptybuffer = true;
if self.end < 0 && self.begin < 0 {
for _ in 0..self.begin.abs() {
self.buffer.pop_front();
}
}
if self.end < 0 {
for _ in 0..self.end.abs() {
self.buffer.pop_back();
}
}
}
}
}
}
}
#[derive(Clone, Debug, Copy, PartialEq, Eq)]
pub enum FilterMode {
Any,
All,
}
impl Default for FilterMode {
fn default() -> Self {
Self::Any
}
}
#[derive(Clone, Debug, Copy, PartialEq, Eq)]
pub enum TextMode {
Exact,
CaseInsensitive,
}
impl Default for TextMode {
fn default() -> Self {
Self::Exact
}
}
#[derive(Debug)]
#[allow(dead_code)] pub(crate) enum Filter<'store> {
AnnotationData(
AnnotationDataSetHandle,
AnnotationDataHandle,
SelectionQualifier,
),
AnnotationDataSet(AnnotationDataSetHandle, SelectionQualifier),
DataKey(AnnotationDataSetHandle, DataKeyHandle, SelectionQualifier),
DataKeyAndOperator(
AnnotationDataSetHandle,
DataKeyHandle,
DataOperator<'store>,
SelectionQualifier,
),
Annotation(AnnotationHandle, SelectionQualifier, AnnotationDepth),
TextResource(TextResourceHandle, SelectionQualifier),
DataOperator(DataOperator<'store>, SelectionQualifier),
TextSelectionOperator(TextSelectionOperator, SelectionQualifier),
AnnotationSubStore(Option<AnnotationSubStoreHandle>),
Annotations(
Handles<'store, Annotation>,
FilterMode,
SelectionQualifier,
AnnotationDepth,
),
Resources(
Handles<'store, TextResource>,
FilterMode,
SelectionQualifier,
),
Data(
Handles<'store, AnnotationData>,
FilterMode,
SelectionQualifier,
),
Keys(Handles<'store, DataKey>, FilterMode, SelectionQualifier),
DataSets(
Handles<'store, AnnotationDataSet>,
FilterMode,
SelectionQualifier,
),
Text(String, TextMode, &'store str), Regex(Regex, &'store str), TextSelection(TextResourceHandle, TextSelectionHandle),
TextSelections(Handles<'store, TextSelection>, FilterMode),
Offset(Offset),
BorrowedAnnotations(
&'store Annotations<'store>,
FilterMode,
SelectionQualifier,
AnnotationDepth,
),
BorrowedData(
&'store Handles<'store, AnnotationData>,
FilterMode,
SelectionQualifier,
),
BorrowedKeys(
&'store Handles<'store, DataKey>,
FilterMode,
SelectionQualifier,
),
BorrowedDataSets(
&'store Handles<'store, AnnotationDataSet>,
FilterMode,
SelectionQualifier,
),
BorrowedText(&'store str, TextMode, &'store str), BorrowedResources(
&'store Handles<'store, TextResource>,
FilterMode,
SelectionQualifier,
),
}