automerge/automerge/src/query/spans.rs
Orion Henry 06f0b201c9 Revert "remove marks"
This reverts commit c8c695618b.
2022-02-10 12:04:08 -05:00

108 lines
3.2 KiB
Rust

use crate::query::{OpSetMetadata, QueryResult, TreeQuery};
use crate::types::{ElemId, Op, OpType, ScalarValue};
use std::collections::HashMap;
use std::fmt::Debug;
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct Spans<const B: usize> {
pos: usize,
seen: usize,
last_seen: Option<ElemId>,
last_insert: Option<ElemId>,
seen_at_this_mark: Option<ElemId>,
seen_at_last_mark: Option<ElemId>,
ops: Vec<Op>,
marks: HashMap<String, ScalarValue>,
changed: bool,
pub spans: Vec<Span>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Span {
pub pos: usize,
pub marks: Vec<(String, ScalarValue)>,
}
impl<const B: usize> Spans<B> {
pub fn new() -> Self {
Spans {
pos: 0,
seen: 0,
last_seen: None,
last_insert: None,
seen_at_last_mark: None,
seen_at_this_mark: None,
changed: false,
ops: Vec::new(),
marks: HashMap::new(),
spans: Vec::new(),
}
}
pub fn check_marks(&mut self) {
let mut new_marks = HashMap::new();
for op in &self.ops {
if let OpType::MarkBegin(m) = &op.action {
new_marks.insert(m.name.clone(), m.value.clone());
}
}
if new_marks != self.marks {
self.changed = true;
self.marks = new_marks;
}
if self.changed
&& (self.seen_at_last_mark != self.seen_at_this_mark
|| self.seen_at_last_mark.is_none() && self.seen_at_this_mark.is_none())
{
self.changed = false;
self.seen_at_last_mark = self.seen_at_this_mark;
let mut marks: Vec<_> = self
.marks
.iter()
.map(|(key, val)| (key.clone(), val.clone()))
.collect();
marks.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
self.spans.push(Span {
pos: self.seen,
marks,
});
}
}
}
impl<const B: usize> TreeQuery<B> for Spans<B> {
/*
fn query_node(&mut self, _child: &OpTreeNode<B>) -> QueryResult {
unimplemented!()
}
*/
fn query_element_with_metadata(&mut self, element: &Op, m: &OpSetMetadata) -> QueryResult {
// find location to insert
// mark or set
if element.succ.is_empty() {
if let OpType::MarkBegin(_) = &element.action {
let pos = self
.ops
.binary_search_by(|probe| m.lamport_cmp(probe.id, element.id))
.unwrap_err();
self.ops.insert(pos, element.clone());
}
if let OpType::MarkEnd(_) = &element.action {
self.ops.retain(|op| op.id != element.id.prev());
}
}
if element.insert {
self.last_seen = None;
self.last_insert = element.elemid();
}
if self.last_seen.is_none() && element.visible() {
self.check_marks();
self.seen += 1;
self.last_seen = element.elemid();
self.seen_at_this_mark = element.elemid();
}
self.pos += 1;
QueryResult::Next
}
}