automerge/automerge/src/query/insert.rs

79 lines
2.3 KiB
Rust

use crate::error::AutomergeError;
use crate::op_tree::OpTreeNode;
use crate::query::{QueryResult, TreeQuery};
use crate::types::{ElemId, Key, Op, HEAD};
use std::fmt::Debug;
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct InsertNth<const B: usize> {
target: usize,
seen: usize,
pub pos: usize,
last_seen: Option<ElemId>,
last_insert: Option<ElemId>,
}
impl<const B: usize> InsertNth<B> {
pub fn new(target: usize) -> Self {
InsertNth {
target,
seen: 0,
pos: 0,
last_seen: None,
last_insert: None,
}
}
pub fn key(&self) -> Result<Key, AutomergeError> {
if self.target == 0 {
Ok(HEAD.into())
} else if self.seen == self.target && self.last_insert.is_some() {
Ok(Key::Seq(self.last_insert.unwrap()))
} else {
Err(AutomergeError::InvalidIndex(self.target))
}
}
}
impl<const B: usize> TreeQuery<B> for InsertNth<B> {
fn query_node(&mut self, child: &OpTreeNode<B>) -> QueryResult {
if self.target == 0 {
// insert at the start of the obj all inserts are lesser b/c this is local
self.pos = 0;
return QueryResult::Finish;
}
let mut num_vis = child.index.len;
if num_vis > 0 {
if child.index.has(&self.last_seen) {
num_vis -= 1;
}
if self.seen + num_vis >= self.target {
QueryResult::Decend
} else {
self.pos += child.len();
self.seen += num_vis;
self.last_seen = child.last().elemid();
QueryResult::Next
}
} else {
self.pos += child.len();
QueryResult::Next
}
}
fn query_element(&mut self, element: &Op) -> QueryResult {
if element.insert {
if self.seen >= self.target {
return QueryResult::Finish;
};
self.last_seen = None;
self.last_insert = element.elemid();
}
if self.last_seen.is_none() && element.visible() {
self.seen += 1;
self.last_seen = element.elemid()
}
self.pos += 1;
QueryResult::Next
}
}