use crate::marks::MarkData;
use crate::op_set::Op;
use crate::op_tree::{OpSetData, OpTree, OpTreeNode};
use crate::types::{Key, ListEncoding, OpBuilder, OpId, OpType};
use fxhash::FxBuildHasher;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
mod insert;
mod list_state;
mod nth;
mod opid;
mod seek_mark;
pub(crate) use insert::InsertNth;
pub(crate) use list_state::{ListState, MarkMap};
pub(crate) use nth::Nth;
pub(crate) use opid::{OpIdSearch, SimpleOpIdSearch};
pub(crate) use seek_mark::SeekMark;
#[derive(Debug, Clone)]
pub(crate) struct ChangeVisibility<'a> {
pub(crate) old_vis: bool,
pub(crate) new_vis: bool,
pub(crate) op: Op<'a>,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct CounterData {
pos: usize,
val: i64,
succ: HashSet<OpId>,
op: OpBuilder,
}
pub(crate) trait TreeQuery<'a>: Clone + Debug {
fn equiv(&mut self, _other: &Self) -> bool {
false
}
fn can_shortcut_search(&mut self, _tree: &'a OpTree, _osd: &'a OpSetData) -> bool {
false
}
fn query_node(
&mut self,
_child: &'a OpTreeNode,
_index: &'a Index,
_osd: &'a OpSetData,
) -> QueryResult {
QueryResult::Descend
}
fn query_element(&mut self, _op: Op<'a>) -> QueryResult {
panic!("invalid element query")
}
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum QueryResult {
Next,
Descend,
Finish,
}
#[derive(Clone, Debug, PartialEq)]
struct TextWidth {
width: usize,
}
impl TextWidth {
fn add_op(&mut self, op: Op<'_>) {
self.width += op.width(ListEncoding::Text);
}
fn remove_op(&mut self, op: Op<'_>) {
self.width = self.width.saturating_sub(op.width(ListEncoding::Text));
}
fn merge(&mut self, other: &TextWidth) {
self.width += other.width;
}
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct Index {
visible: HashMap<Key, usize, FxBuildHasher>,
visible_text: TextWidth,
ops: HashSet<OpId, FxBuildHasher>,
never_seen_puts: bool,
mark_begin: HashMap<OpId, MarkData, FxBuildHasher>,
mark_end: Vec<OpId>,
}
impl Index {
pub(crate) fn has_never_seen_puts(&self) -> bool {
self.never_seen_puts
}
pub(crate) fn new() -> Self {
Index {
visible: Default::default(),
visible_text: TextWidth { width: 0 },
ops: Default::default(),
never_seen_puts: true,
mark_begin: Default::default(),
mark_end: Default::default(),
}
}
pub(crate) fn visible_len(&self, encoding: ListEncoding) -> usize {
match encoding {
ListEncoding::List => self.visible.len(),
ListEncoding::Text => self.visible_text.width,
}
}
pub(crate) fn has_visible(&self, seen: &Key) -> bool {
self.visible.contains_key(seen)
}
pub(crate) fn change_vis<'a>(
&mut self,
change_vis: ChangeVisibility<'a>,
) -> ChangeVisibility<'a> {
let ChangeVisibility {
old_vis,
new_vis,
op,
} = change_vis;
let key = op.elemid_or_key();
match (old_vis, new_vis) {
(true, false) => match self.visible.get(&key).copied() {
Some(1) => {
self.visible.remove(&key);
self.visible_text.remove_op(op);
}
Some(n) => {
self.visible.insert(key, n - 1);
}
None => panic!("remove overun in index"),
},
(false, true) => {
if let Some(n) = self.visible.get(&key) {
self.visible.insert(key, n + 1);
} else {
self.visible.insert(key, 1);
self.visible_text.add_op(op);
}
}
_ => {}
}
change_vis
}
pub(crate) fn insert(&mut self, op: Op<'_>) {
self.never_seen_puts &= op.insert();
self.ops.insert(*op.id());
match op.action() {
OpType::MarkBegin(_, data) => {
self.mark_begin.insert(*op.id(), data.clone());
}
OpType::MarkEnd(_) => {
if self.mark_begin.remove(&op.id().prev()).is_none() {
self.mark_end.push(*op.id())
}
}
_ => {}
}
if op.visible() {
let key = op.elemid_or_key();
if let Some(n) = self.visible.get(&key) {
self.visible.insert(key, n + 1);
} else {
self.visible.insert(key, 1);
self.visible_text.add_op(op);
}
}
}
pub(crate) fn remove(&mut self, op: Op<'_>) {
self.ops.remove(op.id());
match op.action() {
OpType::MarkBegin(_, _) => {
self.mark_begin.remove(op.id());
}
OpType::MarkEnd(_) => {
self.mark_end.retain(|id| id != op.id());
}
_ => {}
}
if op.visible() {
let key = op.elemid_or_key();
match self.visible.get(&key).copied() {
Some(1) => {
self.visible.remove(&key);
self.visible_text.remove_op(op);
}
Some(n) => {
self.visible.insert(key, n - 1);
}
None => panic!("remove overun in index"),
}
}
}
pub(crate) fn merge(&mut self, other: &Index) {
for id in &other.ops {
self.ops.insert(*id);
}
for (elem, other_len) in other.visible.iter() {
self.visible
.entry(*elem)
.and_modify(|len| *len += *other_len)
.or_insert(*other_len);
}
self.mark_begin.extend(other.mark_begin.clone()); self.mark_end.extend(&other.mark_end);
self.visible_text.merge(&other.visible_text);
self.never_seen_puts &= other.never_seen_puts;
}
}
impl Default for Index {
fn default() -> Self {
Self::new()
}
}