use serde::ser::{SerializeSeq, SerializeStruct, Serializer};
use serde::{Deserialize, Serialize};
use std::ops::Deref;
use std::borrow::Cow;
use datasize::{DataSize,data_size};
use minicbor::{Encode,Decode};
use smallvec::SmallVec;
use crate::annotation::{Annotation, AnnotationHandle};
use crate::annotationdataset::{AnnotationDataSet, AnnotationDataSetHandle};
use crate::annotationstore::AnnotationStore;
use crate::error::*;
use crate::annotationdata::{AnnotationData,AnnotationDataHandle};
use crate::datakey::{DataKey,DataKeyHandle};
use crate::resources::{TextResource, TextResourceHandle};
use crate::textselection::{TextSelection, TextSelectionHandle};
use crate::types::*;
use crate::store::*;
use crate::text::Text;
#[derive(Debug, Clone, Deserialize, PartialEq, DataSize, Encode, Decode)]
pub struct Offset {
#[n(0)] pub begin: Cursor,
#[n(1)]
pub end: Cursor,
}
impl Offset {
pub fn new(begin: Cursor, end: Cursor) -> Self {
Offset { begin, end }
}
pub fn simple(begin: usize, end: usize) -> Self {
Offset {
begin: Cursor::BeginAligned(begin),
end: Cursor::BeginAligned(end),
}
}
pub fn whole() -> Self {
Offset {
begin: Cursor::BeginAligned(0),
end: Cursor::EndAligned(0),
}
}
pub fn is_simple(&self) -> bool {
match (self.begin, self.end) {
(Cursor::BeginAligned(_), Cursor::BeginAligned(_)) => true,
_ => false
}
}
pub fn is_simple_or_whole(&self) -> bool {
match (self.begin, self.end) {
(Cursor::BeginAligned(_), Cursor::BeginAligned(_)) => true,
(Cursor::BeginAligned(0), Cursor::EndAligned(0)) => true,
_ => false
}
}
pub fn to_json(&self) -> Result<String, StamError> {
serde_json::to_string_pretty(&self).map_err(|e| {
StamError::SerializationError(format!("Writing textselection to string: {}", e))
})
}
pub fn to_json_compact(&self) -> Result<String, StamError> {
serde_json::to_string(&self).map_err(|e| {
StamError::SerializationError(format!("Writing textselection to string: {}", e))
})
}
pub fn mode(&self) -> OffsetMode {
self.into()
}
pub fn shift(&self, distance: isize) -> Result<Offset,StamError> {
Ok(Offset {
begin: self.begin.shift(distance)?,
end: self.end.shift(distance)?,
})
}
pub fn len(&self) -> Option<usize> {
match (self.begin, self.end) {
(Cursor::BeginAligned(begin), Cursor::BeginAligned(end)) => Some(end - begin),
(Cursor::EndAligned(begin), Cursor::EndAligned(end)) => Some((end - begin).abs() as usize),
_ => None
}
}
}
impl Default for Offset {
fn default() -> Self {
Offset {
begin: Cursor::BeginAligned(0),
end: Cursor::EndAligned(0),
}
}
}
impl Serialize for Offset {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("AnnotationData", 2)?;
state.serialize_field("@type", "Offset")?;
state.serialize_field("begin", &self.begin)?;
state.serialize_field("end", &self.end)?;
state.end()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Encode, Decode,DataSize)]
pub enum OffsetMode {
#[n(0)]
BeginBegin,
#[n(1)]
BeginEnd,
#[n(2)]
EndEnd,
#[n(3)]
EndBegin,
}
impl Default for OffsetMode {
fn default() -> Self {
Self::BeginBegin
}
}
impl From<&Offset> for OffsetMode {
fn from(offset: &Offset) -> OffsetMode {
match offset.begin {
Cursor::BeginAligned(_) => {
match offset.end {
Cursor::BeginAligned(_) => {
Self::BeginBegin
},
Cursor::EndAligned(_) => {
Self::BeginEnd
}
}
},
Cursor::EndAligned(_) => {
match offset.end {
Cursor::BeginAligned(_) => {
Self::EndBegin
},
Cursor::EndAligned(_) => {
Self::EndEnd
}
}
}
}
}
}
impl From<(isize,isize)> for OffsetMode {
fn from(value: (isize,isize)) -> Self {
if value.0 >= 0 && value.1 > 0 {
Self::BeginBegin
} else if value.0 >= 0 && value.1 <= 0 {
Self::BeginEnd
} else if value.0 < 0 && value.1 <= 0 {
Self::EndEnd
} else {
Self::EndBegin
}
}
}
impl From<(isize,isize)> for Offset {
fn from(value: (isize,isize)) -> Self {
if value.0 >= 0 && value.1 > 0 {
Offset::new(Cursor::BeginAligned(value.0 as usize), Cursor::BeginAligned(value.1 as usize))
} else if value.0 >= 0 && value.1 <= 0 {
Offset::new(Cursor::BeginAligned(value.0 as usize), Cursor::EndAligned(value.1))
} else if value.0 < 0 && value.1 <= 0 {
Offset::new(Cursor::EndAligned(value.0), Cursor::EndAligned(value.1))
} else {
Offset::new(Cursor::EndAligned(value.0), Cursor::BeginAligned(value.1 as usize))
}
}
}
impl TryFrom<&str> for Offset {
type Error = StamError;
fn try_from(offset: &str) -> Result<Self, Self::Error> {
let fields: SmallVec<[&str; 2]> = offset.split(|c| [':',','].contains(&c)).collect();
let begin: isize = if fields.len() >= 1 && fields.get(0) != Some(&"") {
fields.get(0).unwrap().parse().map_err(|_| {
StamError::ValueError(offset.into(), "offset string must be in 'start:end' or 'start,end' form, with start and end being a (possibly signed) integer")
})?
} else {
0
};
let end: isize = if fields.len() == 2 && fields.get(1) != Some(&"") {
fields.get(1).unwrap().parse().map_err(|_| {
StamError::ValueError(offset.into(), "offset string must be in 'start:end' or 'start,end' form, with start and end being a (possibly signed) integer")
})?
} else {
0
};
Ok((begin,end).into())
}
}
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
pub enum Selector {
#[n(0)] TextSelector(
#[n(0)]
TextResourceHandle,
#[n(1)]
TextSelectionHandle,
#[n(2)]
OffsetMode, ),
#[n(1)] AnnotationSelector(
#[n(0)]
AnnotationHandle,
#[n(1)]
Option<(TextResourceHandle, TextSelectionHandle, OffsetMode)>
),
#[n(2)]
ResourceSelector(
#[n(0)]
TextResourceHandle
),
#[n(3)]
DataSetSelector(
#[n(0)]
AnnotationDataSetHandle
),
#[n(4)]
MultiSelector(
#[n(0)]
Vec<Selector>
),
#[n(5)]
CompositeSelector(
#[n(0)]
Vec<Selector>
),
#[n(6)]
DirectionalSelector(
#[n(0)]
Vec<Selector>
),
#[n[7]]
DataKeySelector(
#[n(0)]
AnnotationDataSetHandle,
#[n(1)]
DataKeyHandle
),
#[n[8]]
AnnotationDataSelector(
#[n(0)]
AnnotationDataSetHandle,
#[n(1)]
AnnotationDataHandle
),
#[n(52)]
RangedTextSelector {
#[n(0)]
resource: TextResourceHandle,
#[n(1)]
begin: TextSelectionHandle,
#[n(2)]
end: TextSelectionHandle,
},
#[n(53)]
RangedAnnotationSelector {
#[n(0)]
begin: AnnotationHandle,
#[n(1)]
end: AnnotationHandle,
#[n(2)]
with_text: bool, },
}
impl Selector {
pub fn kind(&self) -> SelectorKind {
self.into()
}
pub fn is_complex(&self) -> bool {
self.kind().is_complex()
}
pub fn to_json(&self, store: &AnnotationStore) -> Result<String, StamError> {
let wrapped = WrappedSelector::new(self, store);
serde_json::to_string_pretty(&wrapped).map_err(|e| {
StamError::SerializationError(format!("Writing selector to string: {}", e))
})
}
pub fn to_json_compact(&self, store: &AnnotationStore) -> Result<String, StamError> {
let wrapped = WrappedSelector::new(self, store);
serde_json::to_string(&wrapped).map_err(|e| {
StamError::SerializationError(format!("Writing selector to string: {}", e))
})
}
pub fn subselectors(&self) -> Option<&[Selector]> {
match self {
Selector::MultiSelector(v) | Selector::CompositeSelector(v) | Selector::DirectionalSelector(v) => Some(v),
_ => None,
}
}
pub fn len(&self) -> usize {
match self {
Selector::MultiSelector(v) | Selector::CompositeSelector(v) | Selector::DirectionalSelector(v) => v.len(),
_ => 0,
}
}
pub fn textselection<'store>(&self, store: &'store AnnotationStore) -> Option<&'store TextSelection> {
match self {
Selector::TextSelector(res_handle,tsel_handle,_) | Selector::AnnotationSelector(_, Some((res_handle,tsel_handle,_))) => {
let resource: &TextResource = store.get(*res_handle).expect("handle must be valid");
let textselection: &TextSelection = resource.get(*tsel_handle).expect("handle must be valid");
Some(textselection)
}
_ => None
}
}
pub fn textselection_handle(&self) -> Option<TextSelectionHandle> {
match self {
Selector::TextSelector(_,tsel_handle,_) | Selector::AnnotationSelector(_, Some((_,tsel_handle,_))) => {
Some(*tsel_handle)
}
_ => None
}
}
pub fn resource_handle(&self) -> Option<TextResourceHandle> {
match self {
Selector::ResourceSelector(res_handle) | Selector::TextSelector(res_handle,_,_) | Selector::AnnotationSelector(_, Some((res_handle,_,_))) => {
Some(*res_handle)
}
_ => None
}
}
pub fn offset(&self, store: &AnnotationStore) -> Option<Offset> {
self.offset_with_mode(store, None)
}
pub fn offset_with_mode(&self, store: &AnnotationStore, override_mode: Option<OffsetMode>) -> Option<Offset> {
match self {
Selector::TextSelector(res_handle,tsel_handle,offsetmode) => {
let offsetmode = if let Some(override_mode) = override_mode {
override_mode
} else {
*offsetmode
};
let resource: &TextResource = store.get(*res_handle).expect("handle must be valid");
let textselection: &TextSelection = resource.get(*tsel_handle).expect("handle must be valid");
match offsetmode {
OffsetMode::BeginBegin => Some(textselection.into()),
OffsetMode::BeginEnd => {
let begin = textselection.begin();
let end: isize = textselection.end() as isize - resource.textlen() as isize;
Some(Offset::new(Cursor::BeginAligned(begin), Cursor::EndAligned(end)))
}
OffsetMode::EndBegin => {
let begin: isize = textselection.begin() as isize - resource.textlen() as isize;
let end = textselection.end();
Some(Offset::new(Cursor::EndAligned(begin), Cursor::BeginAligned(end)))
}
OffsetMode::EndEnd => {
let begin: isize = textselection.begin() as isize - resource.textlen() as isize;
let end: isize = textselection.end() as isize - resource.textlen() as isize;
Some(Offset::new(Cursor::EndAligned(begin), Cursor::EndAligned(end)))
}
}
}
Selector::AnnotationSelector(annotation_handle, Some((res_handle, tsel_handle, offsetmode))) => {
let offsetmode = if let Some(override_mode) = override_mode {
override_mode
} else {
*offsetmode
};
let resource: &TextResource = store.get(*res_handle).expect("handle must be valid");
let textselection: &TextSelection = resource.get(*tsel_handle).expect("handle must be valid");
let target: &Annotation = store.get(*annotation_handle).expect("handle must be valid");
if let Some(parent_textselection) = target.target().textselection(store) {
textselection.relative_offset(parent_textselection, offsetmode)
} else {
None
}
}
_ => None
}
}
}
impl DataSize for Selector {
const IS_DYNAMIC: bool = true;
const STATIC_HEAP_SIZE: usize = 8;
#[inline]
fn estimate_heap_size(&self) -> usize {
match self {
Self::TextSelector(handle, handle2 ,mode) => 8 + data_size(handle) + data_size(handle2) + data_size(mode),
Self::AnnotationSelector(handle, handle2) => 8 + data_size(handle) + data_size(handle2),
Self::ResourceSelector(handle) => 8 + data_size(handle),
Self::DataSetSelector(handle) => 8 + data_size(handle),
Self::DataKeySelector(handle,handle2) => 8 + data_size(handle)+ data_size(handle2),
Self::AnnotationDataSelector(handle,handle2) => 8 + data_size(handle)+ data_size(handle2),
Self::MultiSelector(v) => 8 + data_size(v),
Self::CompositeSelector(v) => 8 + data_size(v),
Self::DirectionalSelector(v) => 8 + data_size(v),
Self::RangedTextSelector { resource, begin, end } => 8 + data_size(resource) + data_size(begin) + data_size(end),
Self::RangedAnnotationSelector { begin, end, with_text } => 8 + data_size(with_text) + data_size(begin) + data_size(end),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize,Deserialize)]
pub enum SelectorKind {
ResourceSelector = 1,
AnnotationSelector = 2,
TextSelector = 3,
DataSetSelector = 4,
MultiSelector = 5,
CompositeSelector = 6,
DirectionalSelector = 7,
InternalRangedSelector = 8,
DataKeySelector = 9,
AnnotationDataSelector = 10,
}
impl SelectorKind {
pub fn as_str(&self) -> &'static str {
match self {
Self::ResourceSelector => "ResourceSelector",
Self::AnnotationSelector => "AnnotationSelector",
Self::TextSelector => "TextSelector",
Self::DataSetSelector => "DataSetSelector",
Self::MultiSelector => "MultiSelector",
Self::CompositeSelector => "CompositeSelector",
Self::DirectionalSelector => "DirectionalSelector",
Self::InternalRangedSelector => "InternalRangedSelector",
Self::DataKeySelector => "DataKeySelector",
Self::AnnotationDataSelector => "AnnotationDataSelector",
}
}
pub fn is_complex(&self) -> bool {
match self {
Self::MultiSelector => true,
Self::DirectionalSelector => true,
Self::CompositeSelector => true,
_ => false,
}
}
}
impl TryFrom<&str> for SelectorKind {
type Error = StamError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"ResourceSelector" | "resourceselector" | "resource" => Ok(Self::ResourceSelector),
"AnnotationSelector" | "annotationselector" | "annotation" => Ok(Self::AnnotationSelector),
"TextSelector" | "textselector" | "text" => Ok(Self::TextSelector),
"DataSetSelector" | "datasetselector" | "set" | "annotationset" | "dataset" => Ok(Self::DataSetSelector),
"DataKeySelector" | "datakeyselector" | "key" => Ok(Self::DataKeySelector),
"AnnotationDataSelector" | "annotationdataselector" | "dataselector" | "data" => Ok(Self::AnnotationDataSelector),
"MultiSelector" | "multiselector" | "multi" => Ok(Self::MultiSelector),
"CompositeSelector" | "compositeselector" | "composite" => Ok(Self::CompositeSelector),
"DirectionalSelector" | "directionalselector" | "directional" => Ok(Self::DirectionalSelector),
_ => Err(StamError::ValueError(value.to_string(), "Expected a valid SelectorKind"))
}
}
}
impl From<&Selector> for SelectorKind {
fn from(selector: &Selector) -> Self {
match selector {
Selector::ResourceSelector(..) => Self::ResourceSelector,
Selector::AnnotationSelector(..) => Self::AnnotationSelector,
Selector::TextSelector(..) => Self::TextSelector,
Selector::DataSetSelector(_) => Self::DataSetSelector,
Selector::DataKeySelector(..) => Self::DataKeySelector,
Selector::AnnotationDataSelector(..) => Self::AnnotationDataSelector,
Selector::MultiSelector(..) => Self::MultiSelector,
Selector::CompositeSelector(..) => Self::CompositeSelector,
Selector::DirectionalSelector(..) => Self::DirectionalSelector,
Selector::RangedTextSelector {
..
}
| Selector::RangedAnnotationSelector { .. } => {
Self::InternalRangedSelector
}
}
}
}
impl<'a> From<&SelectorBuilder<'a>> for SelectorKind {
fn from(selector: &SelectorBuilder<'a>) -> Self {
match selector {
SelectorBuilder::ResourceSelector(..) => Self::ResourceSelector,
SelectorBuilder::AnnotationSelector(..) => Self::AnnotationSelector,
SelectorBuilder::TextSelector(..) => Self::TextSelector,
SelectorBuilder::DataSetSelector(..) => Self::DataSetSelector,
SelectorBuilder::DataKeySelector(..) => Self::DataKeySelector,
SelectorBuilder::AnnotationDataSelector(..) => Self::AnnotationDataSelector,
SelectorBuilder::MultiSelector(..) => Self::MultiSelector,
SelectorBuilder::CompositeSelector(..) => Self::CompositeSelector,
SelectorBuilder::DirectionalSelector(..) => Self::DirectionalSelector,
}
}
}
#[derive(Debug, Deserialize)]
#[serde(from = "SelectorJson")]
pub enum SelectorBuilder<'a> {
ResourceSelector(BuildItem<'a,TextResource>),
AnnotationSelector(BuildItem<'a,Annotation>, Option<Offset>),
TextSelector(BuildItem<'a,TextResource>, Offset),
DataSetSelector(BuildItem<'a,AnnotationDataSet>),
DataKeySelector(BuildItem<'a, AnnotationDataSet>, BuildItem<'a,DataKey>),
AnnotationDataSelector(BuildItem<'a, AnnotationDataSet>, BuildItem<'a,AnnotationData>),
MultiSelector(Vec<SelectorBuilder<'a>>),
CompositeSelector(Vec<SelectorBuilder<'a>>),
DirectionalSelector(Vec<SelectorBuilder<'a>>),
}
impl<'a> SelectorBuilder<'a> {
pub fn kind(&self) -> SelectorKind {
self.into()
}
pub fn is_complex(&self) -> bool {
self.kind().is_complex()
}
pub fn resourceselector(resource: impl Into<BuildItem<'a,TextResource>>) -> Self {
Self::ResourceSelector(resource.into())
}
pub fn textselector(resource: impl Into<BuildItem<'a,TextResource>>, offset: impl Into<Offset>) -> Self {
Self::TextSelector(resource.into(), offset.into())
}
pub fn annotationselector(annotation: impl Into<BuildItem<'a,Annotation>>, offset: Option<Offset>) -> Self {
Self::AnnotationSelector(annotation.into(), offset)
}
pub fn datasetselector(dataset: impl Into<BuildItem<'a,AnnotationDataSet>>) -> Self {
Self::DataSetSelector(dataset.into())
}
pub fn datakeyselector(dataset: impl Into<BuildItem<'a,AnnotationDataSet>>, datakey: impl Into<BuildItem<'a,DataKey>>) -> Self {
Self::DataKeySelector(dataset.into(), datakey.into())
}
pub fn annotationdataselector(dataset: impl Into<BuildItem<'a,AnnotationDataSet>>,annotationdata: impl Into<BuildItem<'a,AnnotationData>>) -> Self {
Self::AnnotationDataSelector(dataset.into(), annotationdata.into())
}
pub fn multiselector<I>(iter: I) -> Self where I: IntoIterator<Item = SelectorBuilder<'a>>, {
Self::MultiSelector(iter.into_iter().collect())
}
pub fn compositeselector<I>(iter: I) -> Self where I: IntoIterator<Item = SelectorBuilder<'a>> {
Self::CompositeSelector(iter.into_iter().collect())
}
pub fn directionalselector<I>(iter: I) -> Self where I: IntoIterator<Item = SelectorBuilder<'a>> {
Self::DirectionalSelector(iter.into_iter().collect())
}
pub fn offset(&self) -> Option<&Offset> {
if let Self::AnnotationSelector(_, Some(offset)) | Self::TextSelector(_, offset) = self {
Some(offset)
} else {
None
}
}
pub fn resource(&self) -> Option<&BuildItem<'a, TextResource>> {
if let Self::ResourceSelector(resource) | Self::TextSelector(resource, _) = self {
Some(resource)
} else {
None
}
}
}
#[derive(Debug, Deserialize)]
#[serde(tag = "@type")]
enum SelectorJson where
{
ResourceSelector {
resource: String,
},
AnnotationSelector {
annotation: String,
offset: Option<Offset>,
},
TextSelector {
resource: String,
offset: Offset,
},
DataSetSelector {
annotationset: String,
},
DataKeySelector {
annotationset: String,
key: String,
},
AnnotationDataSelector {
annotationset: String,
data: String,
},
MultiSelector { selectors: Vec<SelectorJson> },
CompositeSelector { selectors: Vec<SelectorJson>},
DirectionalSelector{ selectors: Vec<SelectorJson>},
}
impl<'a> From<SelectorJson> for SelectorBuilder<'a> {
fn from(helper: SelectorJson) -> Self {
match helper {
SelectorJson::ResourceSelector { resource: res } => Self::ResourceSelector(res.into()),
SelectorJson::TextSelector {
resource: res,
offset: o,
} => Self::TextSelector(res.into(), o),
SelectorJson::AnnotationSelector {
annotation: a,
offset: o,
} => Self::AnnotationSelector(a.into(), o),
SelectorJson::DataSetSelector { annotationset: s } => Self::DataSetSelector(s.into()),
SelectorJson::DataKeySelector { annotationset: s, key: k } => Self::DataKeySelector(s.into(), k.into()),
SelectorJson::AnnotationDataSelector { annotationset: s, data: d } => Self::AnnotationDataSelector(s.into(), d.into()),
SelectorJson::MultiSelector { selectors: v } => Self::MultiSelector(v.into_iter().map(|j| j.into()).collect()),
SelectorJson::CompositeSelector { selectors: v } => Self::CompositeSelector(v.into_iter().map(|j| j.into()).collect()),
SelectorJson::DirectionalSelector { selectors: v } => Self::DirectionalSelector(v.into_iter().map(|j| j.into()).collect()),
}
}
}
pub trait SelfSelector {
fn to_selector(&self) -> Result<Selector, StamError>;
}
pub struct WrappedSelector<'a> {
selector: &'a Selector,
store: &'a AnnotationStore,
}
impl<'a> Deref for WrappedSelector<'a> {
type Target = Selector;
fn deref(&self) -> &Self::Target {
self.selector
}
}
impl<'a> WrappedSelector<'a> {
pub(crate) fn new(selector: &'a Selector, store: &'a AnnotationStore) -> Self {
WrappedSelector { selector, store }
}
pub(crate) fn store(&'a self) -> &'a AnnotationStore {
self.store
}
}
pub struct WrappedSelectors<'a> {
selectors: &'a Vec<Selector>,
store: &'a AnnotationStore,
}
impl<'a> Serialize for WrappedSelectors<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.selectors.len()))?;
for subselector in self.selectors.iter() {
if subselector.kind() != SelectorKind::InternalRangedSelector {
let wrappedselector = WrappedSelector {
selector: subselector,
store: self.store,
};
seq.serialize_element(&wrappedselector)?;
} else {
for subselector in subselector.iter(self.store, false) {
let wrappedselector = WrappedSelector {
selector: &subselector,
store: self.store,
};
seq.serialize_element(&wrappedselector)?;
}
}
}
seq.end()
}
}
impl<'a> Serialize for WrappedSelector<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self.selector {
Selector::ResourceSelector(res_handle) => {
let textresource: Result<&TextResource, _> = self.store().get(*res_handle);
let textresource = textresource.map_err(serde::ser::Error::custom)?;
let mut state = serializer.serialize_struct("Selector", 2)?;
state.serialize_field("@type", "ResourceSelector")?;
if let Some(id) = textresource.id() {
state.serialize_field("resource", &id)?;
} else {
state.serialize_field("resource", &textresource.temp_id().map_err(serde::ser::Error::custom)?)?;
}
state.end()
}
Selector::TextSelector(res_handle, _, _) => {
let textresource: Result<&TextResource, _> = self.store().get(*res_handle);
let textresource = textresource.map_err(serde::ser::Error::custom)?;
let mut state = serializer.serialize_struct("Selector", 3)?;
state.serialize_field("@type", "TextSelector")?;
if let Some(id) = textresource.id() {
state.serialize_field("resource", &id)?;
} else {
state.serialize_field("resource", &textresource.temp_id().map_err(serde::ser::Error::custom)?)?;
}
let offset: Offset = self.selector.offset(self.store()).expect("must have offset");
state.serialize_field("offset", &offset)?;
state.end()
}
Selector::DataSetSelector(dataset_handle) => {
let dataset: Result<&AnnotationDataSet, _> =
self.store().get(*dataset_handle);
let dataset = dataset.map_err(serde::ser::Error::custom)?;
let mut state = serializer.serialize_struct("Selector", 2)?;
state.serialize_field("@type", "DataSetSelector")?;
if let Some(id) = dataset.id() {
state.serialize_field("annotationset", &id)?;
} else {
state.serialize_field("annotationset", &dataset.temp_id().map_err(serde::ser::Error::custom)?)?;
}
state.end()
}
Selector::AnnotationSelector(annotation_handle, _) => {
let annotation: Result<&Annotation, _> = self.store().get(*annotation_handle);
let annotation = annotation.map_err(serde::ser::Error::custom)?;
let mut state = serializer.serialize_struct("Selector", 3)?;
state.serialize_field("@type", "AnnotationSelector")?;
if let Some(id) = annotation.id() {
state.serialize_field("annotation", &id)?;
} else {
state.serialize_field("annotation", &annotation.temp_id().map_err(serde::ser::Error::custom)?)?;
}
if let Some(offset) = self.selector.offset(self.store()) {
state.serialize_field("offset", &offset)?;
}
state.end()
}
Selector::DataKeySelector(dataset_handle, key_handle) => {
let dataset: Result<&AnnotationDataSet, _> =
self.store().get(*dataset_handle);
let dataset = dataset.map_err(serde::ser::Error::custom)?;
let key: Result<&DataKey, _> =
dataset.get(*key_handle);
let key = key.map_err(serde::ser::Error::custom)?;
let mut state = serializer.serialize_struct("Selector", 3)?;
state.serialize_field("@type", "DataKeySelector")?;
if let Some(id) = dataset.id() {
state.serialize_field("annotationset", &id)?;
} else {
state.serialize_field("annotationset", &dataset.temp_id().map_err(serde::ser::Error::custom)?)?;
}
if let Some(id) = key.id() {
state.serialize_field("key", &id)?;
} else {
state.serialize_field("key", &dataset.temp_id().map_err(serde::ser::Error::custom)?)?;
}
state.end()
}
Selector::AnnotationDataSelector(dataset_handle, data_handle) => {
let dataset: Result<&AnnotationDataSet, _> =
self.store().get(*dataset_handle);
let dataset = dataset.map_err(serde::ser::Error::custom)?;
let data: Result<&AnnotationData, _> =
dataset.get(*data_handle);
let data = data.map_err(serde::ser::Error::custom)?;
let mut state = serializer.serialize_struct("Selector", 3)?;
state.serialize_field("@type", "DataKeySelector")?;
if let Some(id) = dataset.id() {
state.serialize_field("annotationset", &id)?;
} else {
state.serialize_field("annotationset", &dataset.temp_id().map_err(serde::ser::Error::custom)?)?;
}
if let Some(id) = data.id() {
state.serialize_field("data", &id)?;
} else {
state.serialize_field("data", &dataset.temp_id().map_err(serde::ser::Error::custom)?)?;
}
state.end()
}
Selector::MultiSelector(subselectors) => {
let mut state = serializer.serialize_struct("Selector", 2)?;
state.serialize_field("@type", "MultiSelector")?;
let subselectors = WrappedSelectors {
selectors: subselectors,
store: self.store,
};
state.serialize_field("selectors", &subselectors)?;
state.end()
}
Selector::CompositeSelector(subselectors) => {
let mut state = serializer.serialize_struct("Selector", 2)?;
state.serialize_field("@type", "CompositeSelector")?;
let subselectors = WrappedSelectors {
selectors: subselectors,
store: self.store,
};
state.serialize_field("selectors", &subselectors)?;
state.end()
}
Selector::DirectionalSelector(subselectors) => {
let mut state = serializer.serialize_struct("Selector", 2)?;
state.serialize_field("@type", "DirectionalSelector")?;
let subselectors = WrappedSelectors {
selectors: subselectors,
store: self.store,
};
state.serialize_field("selectors", &subselectors)?;
state.end()
}
Selector::RangedTextSelector { .. }
| Selector::RangedAnnotationSelector { .. }
=> {
Err(serde::ser::Error::custom(
"Internal Ranged selectors can not be serialized directly, they can be serialized only when under a complex selector",
))
}
}
}
}
impl Selector {
pub fn iter<'a>(
&'a self,
store: &'a AnnotationStore,
recurse_annotation: bool,
) -> SelectorIter<'a> {
SelectorIter {
selector: self,
subiterstack: Vec::new(),
cursor_in_range: 0,
recurse_annotation,
store,
done: false,
}
}
}
pub struct SelectorIter<'a> {
selector: &'a Selector, done: bool,
subiterstack: Vec<SelectorIter<'a>>,
cursor_in_range: usize,
pub(crate) recurse_annotation: bool,
pub(crate) store: &'a AnnotationStore,
}
impl<'a> SelectorIter<'a> {
fn get_internal_ranged_item(&self, selector: &'a Selector) -> Cow<'a,Selector> {
match selector {
Selector::RangedAnnotationSelector { begin, with_text, .. } => {
let handle = AnnotationHandle::new(begin.as_usize() + self.cursor_in_range);
if *with_text {
let annotation: &Annotation = self.store.get(handle).expect("annotation handle must be valid");
if let (Some(textselection_handle), Some(resource_handle)) = (annotation.target().textselection_handle(), annotation.target().resource_handle()) {
Cow::Owned(Selector::AnnotationSelector(handle, Some((resource_handle, textselection_handle, OffsetMode::default()))))
} else {
Cow::Owned(Selector::AnnotationSelector(handle, None))
}
} else {
Cow::Owned(Selector::AnnotationSelector(handle, None))
}
}
Selector::RangedTextSelector { resource, begin, .. } => {
Cow::Owned(Selector::TextSelector(*resource, TextSelectionHandle::new(begin.as_usize() + self.cursor_in_range), OffsetMode::default()) )
}
_ => {
unreachable!()
}
}
}
}
impl<'a> Iterator for SelectorIter<'a> {
type Item = Cow<'a, Selector>;
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.subiterstack.is_empty() {
if !self.done {
match self.selector {
Selector::AnnotationSelector(a_handle, _) => {
if self.recurse_annotation {
let annotation: &Annotation = self
.store
.get(*a_handle)
.expect("referenced annotation must exist");
self.subiterstack.push(SelectorIter {
selector: annotation.target(),
subiterstack: Vec::new(),
cursor_in_range: 0,
recurse_annotation: self.recurse_annotation,
store: self.store,
done: false,
});
}
}
Selector::MultiSelector(v)
| Selector::CompositeSelector(v)
| Selector::DirectionalSelector(v) => {
for subselector in v.iter().rev() {
self.subiterstack.push(SelectorIter {
selector: subselector,
subiterstack: Vec::new(),
cursor_in_range: 0,
recurse_annotation: self.recurse_annotation,
store: self.store,
done: false,
});
}
}
Selector::RangedAnnotationSelector { begin, end, .. } => {
if begin.as_usize() + self.cursor_in_range > end.as_usize() { self.done = true; return None;
} else {
let result = self.get_internal_ranged_item(self.selector);
self.cursor_in_range += 1;
return Some(result);
}
}
Selector::RangedTextSelector { resource: _, begin, end } => {
if begin.as_usize() + self.cursor_in_range > end.as_usize() { self.done = true; return None;
} else {
let result = self.get_internal_ranged_item(self.selector);
self.cursor_in_range += 1;
return Some(result);
}
},
Selector::TextSelector(..) => {},
Selector::DataSetSelector(_) => {}
Selector::ResourceSelector(_) => {}
Selector::DataKeySelector(..) => {}
Selector::AnnotationDataSelector(..) => {}
};
self.done = true; return Some(Cow::Borrowed(self.selector));
} else {
return None;
}
} else {
let result = self.subiterstack.last_mut().unwrap().next();
if result.is_none() {
self.subiterstack.pop();
if self.subiterstack.is_empty() {
return None;
} else {
continue; }
} else {
return result;
}
}
}
}
}