use crate::protocol::TreeNode;
use std::collections::HashMap;
pub struct GhostNode {
pub node: TreeNode,
pub insert_index: usize,
pub finished: bool,
}
pub struct GhostManager {
ghosts: HashMap<String, Vec<GhostNode>>,
}
impl Default for GhostManager {
fn default() -> Self {
Self::new()
}
}
impl GhostManager {
pub fn new() -> Self {
Self {
ghosts: HashMap::new(),
}
}
pub fn has_active(&self) -> bool {
!self.ghosts.is_empty()
}
pub fn add_ghost(&mut self, parent_id: &str, node: TreeNode, index: usize) {
self.ghosts
.entry(parent_id.to_string())
.or_default()
.push(GhostNode {
node,
insert_index: index,
finished: false,
});
}
pub fn ghosts_for(&self, parent_id: &str) -> Option<&[GhostNode]> {
self.ghosts.get(parent_id).map(|v| v.as_slice())
}
pub fn ghost_count_before(&self, parent_id: &str, sdk_index: usize) -> usize {
self.ghosts
.get(parent_id)
.map(|ghosts| {
ghosts
.iter()
.filter(|g| g.insert_index <= sdk_index)
.count()
})
.unwrap_or(0)
}
pub fn adjust_index(&self, parent_id: &str, sdk_index: usize) -> usize {
sdk_index + self.ghost_count_before(parent_id, sdk_index)
}
pub fn mark_finished(&mut self, parent_id: &str, ghost_index: usize) {
if let Some(ghosts) = self.ghosts.get_mut(parent_id)
&& let Some(ghost) = ghosts.get_mut(ghost_index)
{
ghost.finished = true;
}
}
pub fn prune_finished(&mut self) -> Vec<String> {
let mut removed_ids = Vec::new();
self.ghosts.retain(|_parent_id, ghosts| {
ghosts.retain(|g| {
if g.finished {
removed_ids.push(g.node.id.clone());
false
} else {
true
}
});
!ghosts.is_empty()
});
removed_ids
}
pub fn clear(&mut self) {
self.ghosts.clear();
}
}