After some discussion with PVH I realise that the repo structure in the last reorg was very rust-centric. In an attempt to put each language on a level footing move the rust code and project files into ./rust
63 lines
1.5 KiB
Rust
63 lines
1.5 KiB
Rust
use crate::op_tree::OpTreeNode;
|
|
use crate::query::{QueryResult, TreeQuery};
|
|
use crate::types::{ElemId, Key, Op, OpId};
|
|
|
|
/// Search for an OpId in a tree.
|
|
/// Returns the index of the operation in the tree.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub(crate) struct OpIdSearch {
|
|
target: OpId,
|
|
pos: usize,
|
|
found: bool,
|
|
key: Option<Key>,
|
|
}
|
|
|
|
impl OpIdSearch {
|
|
pub(crate) fn new(target: OpId) -> Self {
|
|
OpIdSearch {
|
|
target,
|
|
pos: 0,
|
|
found: false,
|
|
key: None,
|
|
}
|
|
}
|
|
|
|
/// Get the index of the operation, if found.
|
|
pub(crate) fn index(&self) -> Option<usize> {
|
|
if self.found {
|
|
Some(self.pos)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub(crate) fn key(&self) -> &Option<Key> {
|
|
&self.key
|
|
}
|
|
}
|
|
|
|
impl<'a> TreeQuery<'a> for OpIdSearch {
|
|
fn query_node(&mut self, child: &OpTreeNode) -> QueryResult {
|
|
if child.index.ops.contains(&self.target) {
|
|
QueryResult::Descend
|
|
} else {
|
|
self.pos += child.len();
|
|
QueryResult::Next
|
|
}
|
|
}
|
|
|
|
fn query_element(&mut self, element: &Op) -> QueryResult {
|
|
if element.id == self.target {
|
|
self.found = true;
|
|
if element.insert {
|
|
self.key = Some(Key::Seq(ElemId(element.id)));
|
|
} else {
|
|
self.key = Some(element.key);
|
|
}
|
|
QueryResult::Finish
|
|
} else {
|
|
self.pos += 1;
|
|
QueryResult::Next
|
|
}
|
|
}
|
|
}
|