use crate::marks::OldMark;
use crate::op_set::Op;
use crate::op_tree::OpSetData;
use crate::query::{Index, ListState, OpTreeNode, QueryResult, TreeQuery};
use crate::types::{ListEncoding, OpId, OpType};
use std::cmp::Ordering;
use std::collections::HashMap;
use std::fmt::Debug;
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct SeekMark<'a> {
idx: ListState,
id: OpId,
end: usize,
found_begin: bool,
found_end: bool,
mark_name: smol_str::SmolStr,
next_mark: Option<OldMark<'a>>,
super_marks: HashMap<OpId, smol_str::SmolStr>,
marks: Vec<OldMark<'a>>,
}
impl<'a> SeekMark<'a> {
pub(crate) fn new(id: OpId, end: usize, encoding: ListEncoding) -> Self {
SeekMark {
idx: ListState::new(encoding, usize::MAX),
id,
end,
found_begin: false,
found_end: false,
next_mark: None,
mark_name: "".into(),
super_marks: Default::default(),
marks: Default::default(),
}
}
pub(crate) fn finish(mut self) -> Vec<OldMark<'a>> {
if self.idx.pos() == self.end && !self.found_end && self.super_marks.is_empty() {
if let Some(next_mark) = &mut self.next_mark {
next_mark.end = self.idx.index();
self.marks.push(next_mark.clone());
}
}
self.marks
}
}
impl<'a> TreeQuery<'a> for SeekMark<'a> {
fn query_node(
&mut self,
_child: &OpTreeNode,
index: &Index,
_osd: &'a OpSetData,
) -> QueryResult {
self.idx.check_if_node_is_clean(index);
QueryResult::Descend
}
fn query_element(&mut self, op: Op<'a>) -> QueryResult {
match op.action() {
OpType::MarkBegin(_, data) if op.id() == &self.id => {
if op.succ().len() > 0 {
return QueryResult::Finish;
}
self.found_begin = true;
self.mark_name = data.name.clone();
self.next_mark = Some(OldMark::from_data(self.idx.index(), self.idx.index(), data));
self.id = self.id.next();
self.super_marks.retain(|_, v| v == &data.name);
}
OpType::MarkBegin(_, mark) => {
if op.lamport_cmp(self.id) == Ordering::Greater {
if let Some(next_mark) = &mut self.next_mark {
if mark.name == self.mark_name {
self.super_marks.insert(op.id().next(), mark.name.clone());
if self.super_marks.len() == 1 {
next_mark.end = self.idx.index();
self.marks.push(next_mark.clone());
}
}
} else {
self.super_marks.insert(op.id().next(), mark.name.clone());
}
}
}
OpType::MarkEnd(_) if self.end == self.idx.pos() => {
if self.super_marks.is_empty() {
if let Some(next_mark) = &mut self.next_mark {
next_mark.end = self.idx.index();
self.marks.push(next_mark.clone());
}
}
self.found_end = true;
return QueryResult::Finish;
}
OpType::MarkEnd(_) if self.super_marks.contains_key(op.id()) => {
self.super_marks.remove(op.id());
if let Some(next_mark) = &mut self.next_mark {
if self.super_marks.is_empty() {
next_mark.start = self.idx.index();
}
}
}
_ => {}
}
if self.end == self.idx.pos() {
self.found_end = true;
if self.super_marks.is_empty() {
if let Some(next_mark) = &mut self.next_mark {
next_mark.end = self.idx.index();
self.marks.push(next_mark.clone());
}
}
return QueryResult::Finish;
}
let elemid = op.elemid_or_key();
let visible = op.visible(); self.idx.process_op(op, elemid, visible);
QueryResult::Next
}
}